다음 코드는 합법입니까?
template <int N>
class foo {
public:
constexpr foo()
{
for (int i = 0; i < N; ++i) {
v_[i] = i;
}
}
private:
int v_[N];
};
constexpr foo<5> bar;
Clang은 수락하지만 GCC 및 MSVC는 거부합니다.
GCC의 오류는 다음과 같습니다
main.cpp:15:18: error: 'constexpr foo<N>::foo() [with int N = 5]' called in a constant expression
15 | constexpr foo<5> bar;
| ^~~
main.cpp:4:15: note: 'constexpr foo<N>::foo() [with int N = 5]' is not usable as a 'constexpr' function because:
4 | constexpr foo()
| ^~~
main.cpp:4:15: error: member 'foo<5>::v_' must be initialized by mem-initializer in 'constexpr' constructor
main.cpp:12:9: note: declared here
12 | int v_[N];
| ^~
이런 종류의 코드가 정상이라면 index_sequence
s의 사용을 상당히 줄일 수 있습니다.
답변
C ++ 20까지 의 constexpr
컨텍스트 에서는 간단한 기본 초기화가 금지되었습니다 .
필자가 추측 한 이유는 기본적으로 초기화 된 프리미티브, 프로그램에 정의되지 않은 동작을 제공하는 동작 및 정의되지 않은 동작이있는 표현식은 constexpr
( ref ) 금지되어 있기 때문에 “우연히”읽을 수 있기 때문입니다 . 언어는 확장되었으므로 이제 컴파일러는 이러한 읽기가 발생하는지 확인해야하며 그렇지 않은 경우 기본 초기화를 승인해야합니다. 컴파일러에게는 약간 더 많은 작업이지만 프로그래머가 볼 수 있듯이 상당한 이점이 있습니다.
이 논문은 constexpr 컨텍스트에서 사소한 기본 구성 가능 유형에 대한 기본 초기화를 허용하면서 정의되지 않은 동작의 호출을 계속 허용하지 않습니다. 즉, 초기화되지 않은 값을 읽지 않는 한 힙 및 스택 할당 시나리오 모두에서 constexpr에서 이러한 상태를 허용해야합니다.
C ++ 20부터는 v_
“초기화되지 않은” 상태로 두는 것이 합법적 입니다. 그런 다음 모든 요소 값을 할당했습니다.