[c++] constexpr 생성자에서 배열을 초기화하는 것이 합법적입니까?

다음 코드는 합법입니까?

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_sequences의 사용을 상당히 줄일 수 있습니다.



답변

C ++ 20까지constexpr컨텍스트 에서는 간단한 기본 초기화가 금지되었습니다 .

필자가 추측 한 이유는 기본적으로 초기화 된 프리미티브, 프로그램에 정의되지 않은 동작을 제공하는 동작 및 정의되지 않은 동작이있는 표현식은 constexpr( ref ) 금지되어 있기 때문에 “우연히”읽을 수 있기 때문입니다 . 언어는 확장되었으므로 이제 컴파일러는 이러한 읽기가 발생하는지 확인해야하며 그렇지 않은 경우 기본 초기화를 승인해야합니다. 컴파일러에게는 약간 더 많은 작업이지만 프로그래머가 볼 수 있듯이 상당한 이점이 있습니다.

이 논문은 constexpr 컨텍스트에서 사소한 기본 구성 가능 유형에 대한 기본 초기화를 허용하면서 정의되지 않은 동작의 호출을 계속 허용하지 않습니다. 즉, 초기화되지 않은 값을 읽지 않는 한 힙 및 스택 할당 시나리오 모두에서 constexpr에서 이러한 상태를 허용해야합니다.

C ++ 20부터는 v_“초기화되지 않은” 상태로 두는 것이 합법적 입니다. 그런 다음 모든 요소 값을 할당했습니다.


답변