2015-02-04 2 views
3

다음 코드는 Intel-2015에서 ok로 컴파일되지만 gcc 4.8.3에서는 실패합니다. 누가 맞습니까?인텔 대 constexpr의 GCC

#include <iostream> 

void f(int const& x) { std::cout << x << std::endl; } 

struct S 
{ 
    static constexpr int ce = 42; 
}; 

int main() 
{ 
    f(S::ce); 

    return 0; 
} 

g ++ 오류 : 나는 GCC를 잘 생각

/tmp/ccOIxa2V.o: In function `main': 
test_constexpr.cpp:(.text+0x36): undefined reference to `S::ce' 
collect2: error: ld returned 1 exit status 
+1

GCC의 권한입니다. 's.se'하지만'std :: cout'을 사용하는 것은 맞습니다. – ForceBru

+1

'ce'는 정적이고's :: ce'는 옳습니다. 'constexpr'와 관련이 있습니다 – user2052436

+2

@ForceBru 도트 연산자는 유형이 아닌 객체에서 작동합니다. – chris

답변

4

함수 f은 참조 인수를 취하기 때문에 런타임에 참조가 가리킬 수있는 S::ce의 정의가 있어야합니다. 컴파일러는 리터럴 (42) 그래서 당신은 밖으로의 클래스 정의를 추가 할 필요가로 인수를 대체 할 수 없습니다 :

const int S::ce; 

당신이 비 constexpr 변수에서와 같이합니다. 이것은 컴파일 타임에 계산할 수 없었던 참조 나 다른 것들에 사용하기 위해 런타임에 값을위한 메모리 위치를 할당합니다.

자세한 내용은 this GCC bug report (실제로 버그가 아닌 이유 설명) 주석을 참조하십시오.

+0

방금 ​​확인한 바 : 당신이 제안한 것처럼 클래스 밖의'const int test :: ce;'를 추가하면 icc가 작동하고 g ++는'error : redeclaration 'S :: ce'로 실패합니다. 'constexpr int test :: ce;'를 추가하면 두 함수 모두 작동합니다. – user2052436

+0

죄송합니다.'test ::'일은 유감스럽게 생각합니다. 테스트 프로그램에서 코드를 복사했는데, 실제로 여러분의 질문에 대해 다시 검사하지 않았습니다. 그러나'const int S :: ce;'는 나를 위해 작동합니다. 당신은 클래스 정의에서'constexpr'을 필요로하지 않아야한다. – Wyzard

+0

'S :: ce'가'const'로 선언되면 그것은 저에게 효과적입니다. 그러나 그것이'constexpr'으로 선언되면, 클래스 밖의 정의는'constexpr'이어야합니다. 그렇지 않으면 icc와 g ++가 모두 실패합니다. 즉, 정의와 선언은 정확히 일치해야하며, 한 곳에서는'const'를, 다른 곳에서는'constexpr'을 가질 수 없습니다. 컴파일러 버전에 따라 다른가요? – user2052436

4

. BTW, CLang 3.5.1도 같은 에러를 낸다.

고정 정적 변수는 주소가 지정되지 않고 참조에 바인딩되지 않은 경우에만 정의 할 수 있습니다.

귀하의 예는 그것에 대한 참조를 제한하므로 명시적인 정의가 필요합니다. 는 C++ 11 초안 (9.4.2.3)에서

가 편리하게 편집 :

A static data member of literal type can be declared in the class definition with the constexpr specifier; [...] The member shall still be defined in a namespace scope if it is odr-used (3.2) in the program [...].

그리고 3.2 :

A variable [...] whose name appears as a potentially-evaluated expression is odr-used unless it is an object that satisfies the requirements for appearing in a constant expression (5.19) and the lvalue-to-rvalue conversion (4.1) is immediately applied.

그 좌변 투를 rvalue 변환 물건은 대략 말하기 단항 테이크 주소 연산자 &에 참조 또는 인수를 바인딩 할 때를 제외하고는 변수가 사용될 때마다 수행됩니다.

+0

'정적 인 '클래스 내 선언은 그들 앞에 암시적인'extern'이 있다고 너무 과감하게 표현할 수 있습니까? –

+1

@AaronMcDaid : 일반적으로 네, 정적 멤버 선언은 외부 링키지를 가지고 있습니다. – rodrigo

+0

@AaronMcDaid 그건 설명하기위한 명확하고 간결한 방법입니다. – user2052436

관련 문제