c++ - latest - std gnu++ 98




GCC는 constexpr 정적 데이터 멤버의 정의가 constexpr로 표시되어야한다고 생각하는 이유는 무엇입니까? (2)

constexpr 정적 데이터 멤버는 7.1.5 (9)에 따라 클래스에서 초기화되어야합니다. 이것은 회원의 정의입니다. ODR 때문에 다른 정의는 허용되지 않으므로 T :: dur_1은 선언 일뿐입니다. 그러나 정적 본문 데이터 멤버를 클래스 본문 외부에 선언 할 수있는 규칙이 없으므로이 선언은 허용되지 않습니다.

GCC는 constexpr가 일관되게 사용되는 경우에만 확장으로서 이것을 지원합니다.

아니면 내가 틀렸어. 벌레 야.)

FWIW : clang은 경고없이이 코드를 허용합니다.

[C++14: 7.1.5/1]: constexpr 지정자는 변수 또는 변수 템플릿의 정의, 함수 또는 함수 템플릿의 선언 또는 리터럴의 정적 데이터 멤버 선언에만 적용됩니다 유형 (3.9). 함수, 함수 템플릿 또는 변수 템플릿의 선언에 constexpr 지정자가 있으면 모든 선언에 constexpr 지정자가 포함됩니다. [..]

두 번째 문장은 첫 번째 문장의 방식대로 "정적 데이터 멤버"를 언급하지 constexpr 에서 constexpr static 데이터 멤버의 모든 선언 (특히 여기서는 정의 된 선언을 고려 중입니다) constexpr 지정자를 가진다.

나는 이것을 강제하기 위해 다른 곳에서도 규칙을 찾을 수 없다.

그렇다면 왜 GCC는 다음 프로그램을 거부합니까?

#include <chrono>

using namespace std::chrono_literals;

#define DUR 1000ms

struct T
{
   static constexpr auto dur_1 = DUR;
};

decltype(T::dur_1) T::dur_1;

// main.cpp:12:23: error: 'constexpr' needed for in-class initialization of static data member 'const std::chrono::duration<long int, std::ratio<1l, 1000l> T::dur_1' of non-integral type [-fpermissive] 
// decltype(T::dur_1) T::dur_1;
//                       ^

내 이전 대답은 코드의 문제는 std :: chrono_literals 객체가 constexp 유효하지 않다고 생각했지만 Lightspeed가 지적한 것처럼이 경우가 아닙니다.

좀 더 연구를 수행하여 코드의 문제 줄이 struct t : 즉이 줄을 결정했습니다.

static constexp auto ...

이것에 대한 또 다른 대답이 here

왜 이것이 귀하의 문제인지 명시 적으로 지적하십시오 (주석이 즉시 명백하지 않음을 나타냄).

constexp 로 레이블 된 표현식은 컴파일 타임에 결정됩니다. 이 정도는 이미 알고 있습니다. decltype(T::dur_1) T:dur_1 표현식을 사용하여 인스턴스를 만들려고 할 때, 당신은 chrono 리터럴 생성자 ( constexp )에 적절한 자격 증명을 제공하고 있습니다. 문제는 형식이 명시 적으로 정의되어 있지 않아서 1000ms의 DUR 교체에 대한 프로세서 전제 정의에서 온 것으로 생각되는 것 같습니다.

다음을 시도하십시오.

template <class T>
struct foo {
    static constexpr auto dur_1 = DUR;
    typedef decltype(DUR) milliseconds;
}

template <class T>
constexp milliseconds foo<T>::milliseconds foo<T>::DUR; 

GCC 컴파일러가 명시 적 정의를 통해 컴파일 할 때 자동 유형을 결정할 수 없도록 제거함으로써 문제를 해결해야합니다.

이것이 원래 링크가 제공된 이유입니다. GCC는 컴파일 타임에 자동 타이핑을 잘못 판단 할 수 없습니다.





constexpr