2016-12-29 7 views
2

t.n은 컴파일 타임 상수가 아니므로이 코드는 clang에 의해 거부되었습니다.constexpr 멤버를 static_assert에 사용할 수없는 이유는 무엇입니까?

template<int N> 
struct s{ 
    constexpr static int n = N; 
}; 

template<typename T> 
void test(T& t){ 
    static_assert(t.n == 1); 
} 

int main(){ 
    s<1> str; 
    test(str); 
} 

하지만 g ++에게 맡기십시오.

표준 호환 동작은 무엇입니까?

또 하나 궁금한 점은 test의 인수를 T& t에서 T t으로 변경하면이 두 가지가 모두 구현된다는 것입니다. const에 대해 변경된 사항은 무엇입니까?

(I 제목이 제대로이 문제를 설명하거나 상세하지 않을 수 있습니다 무서워. 나에게 더 적합한 제목을주고 자유롭게)

답변

1

나는 연타가에 따라 때문에 올바른지 (그러나 낮은 확신을 가지고) 생각 표준, 코어 상수 표현식 하지가 포함될 수

참조 형식의 변수 또는 데이터 부재를 참조하는 ID 표현 기준 않는 선행 초기화를 가지며 하나

012,

- 상수 표현식으로 초기화되거나

- 수명이 평가 시작일의 e 인 객체의 비 정적 데이터 멤버입니다.

t은 참조 유형의 변수입니다. "이전 초기화"는 상수 표현식이 발생하는 지점에서 어휘 적으로 범위에있는 초기화를 의미하며 매개 변수의 초기화는 호출자의 범위에서 발생하기 때문에 t은 (낮은 신뢰도로) 수행한다고 가정합니다. 이 요구 사항을 만족시키지 않으므로, t.n은 실제로 상수 표현식에서 사용될 수 없습니다.

매개 변수 유형을 T으로 변경하면이 적합하지 않은 글 머리 기호가 더 이상 적용되지 않습니다.

(내 해석을 수용하더라도,이 모호함은 여전히, CWG 2186 참조)

0

내가 컴파일러 오류의 원인을 모르지만 당신은에 액세스하는 범위 결정 연산자를 사용하는 코드를 변경하는 경우 정적 변수 다음 코드는 두 컴파일러 모두에서 컴파일됩니다.

#include <iostream> 

using namespace std; 

template<int N> 
struct s{ 
    constexpr static int n = N; 
}; 

template<typename T> 
void test(T&){ 
    static_assert(T::n == 1, "blah"); 
} 

int main(){ 
    s<1> str; 
    test(str); 
}