2014-10-04 2 views
7

gcc의 다음 작품이 있지만 clang에하지 않는 (see it live)를 오는 방법 : 정적 constexpr odr - 사용 또는하지?

constexpr int giveMeValue() { return 42; } 

struct TryMe { 
    static constexpr int arr[1] = { 
     giveMeValue() 
    }; 
}; 

int main() { 
    int val = TryMe::arr[0]; 
    return val; 
} 

내가 그 소리와 함께 확인되지 않은 외부 기호를 얻을.

TryMe::arr[0]입니까? 그렇다면 odr-used입니까?

+1

어떤 버전의 clang입니까? –

+0

coliru에있는 것 – Dean

+0

잘 작동합니다. http://coliru.stacked-crooked.com/a/2b319b9351784244'C++ 11 플래그 '를 켜셨습니까? – texasbruce

답변

7

TryMe::arrodr-used하지만 당신은 정의 (see it live) 제공하지 않습니다

constexpr int TryMe::arr[1]; 

gccclang 사이의 일치 결과가 있습니까?

는 모든 프로그램이 아닌 모든 인라인 정확히 하나의 정의를 포함해야한다 : ODR 위반하는 disagnostic을 필요로하지 않는 C++ (11)와 C++ 14 표준 초안 (강조 광산)에서 모두 있기 때문이다 해당 프로그램에서 odr- 사용되는 함수 또는 변수. 진단 없음 필요.

우리는 그것을 볼 수 말한다 초안 C++ 11 표준, 섹션 3.2에서 ODR 사용하는 것이다 : 그것은 미 평가 피연산자 아니라면

식은 가능성 평가 (5 절) 또는 그 서브 표현. 이 잠재적으로 평가되는 표현식으로 나타나는 변수는 이 아닌 경우 표현식 (5.19)에 나타나는 요구 사항을 만족하는 객체이고 lvalue-to-rvalue 변환 (4.1)은 즉시 입니다. 적용된.

TryMe::arr 개체이며 일정한 식에 표시되지만 좌변 투 r- 수치 변환 즉시 TryMe::arr뿐만 TryMe::arr[0]인가되지 않는 요건을 충족한다.

결함 리포트 (DR 712)를 통해도가인가 된 이후 C++ (11)에 적용되는 임시 C++ 14 표준에서 업데이트 된 표현 : 이름이 표시

변수 X (xterm)에ex는 x 축에 대해 을 호출하지 않는 상수 표현식 (5.19)을 생성하고 x 값이 0 일 경우 object, ex는 표현식 e의 잠재적 결과 세트 집합의 요소이며, 여기서,363,210 좌변 투 r- 수치 변환 (4.1) E에인가되는, 또는 E는 폐기 치 식

이다 3.2 단락 2 등의 표현 TryMe::arr[0]의이 기준에 비어 전위 결과 그것은 odr- 사용됩니다.

참고 :이 섹션에 따라 클래스의 외부 정의를 제공해야 9.4.2[class.static.data] 말한다 (강조 광산) : 문자의

정적 데이터 멤버 타입은 constexpr 지정자를 사용하는 클래스 정의에서 선언 할 수 있습니다. 그렇다면 그 선언은 할당 표현식 인 모든 initializer-clause 이 상수 표현식 인 중괄호 또는 동등 초기자를 지정해야한다. [참고 :이 두 경우 모두 에서 회원은 상수 표현에 나타날 수 있습니다. -end 참고] 그 가 초기화

에게

업데이트을 포함하지 않는다 프로그램 및 공간 범위 정의 에서 (3.2) 사용 ODR-이면 부재는 여전히 공간 범위에 정의한다

TC 3.2에 다음 탄환 추가 defect report 1926 지적 [basic.def.odr] 제 2

  • E 배열 피연산자와 첨자 작업 (5.2.1 [expr.sub])의 경우, 세트에는 해당 피연산자가 들어 있습니다.

어떤 배열 첨자 것은 더 이상 ODR 사용하고 그래서 작전 코드가 C++ 1Z에서 잘 형성하고처럼 결함이 보인다 이후는 C++ (14)처럼 보인다 될 것이다 의미 C++과 비교하여 14.

+0

선언 대 정의에 대한 좀 더 명확한 설명. OP가'TryMe' 구조체에서 가지고있는 것은 정의로 보일지도 모르지만 실제로 선언문이 정의 일 때 재미있는 규칙 때문에 선언입니다.여기서 OP는 클래스 내 멤버 initializer를 가진'static' 변수를 가지고 있습니다. 이것은 보통 허용되지 않지만'constexpr' (그리고'int') 때문에 허용됩니다. 그러나 OP는'TryMe :: arr'에 실제로 메모리를 할당하지 않았습니다. 변수가 외부 저장 장치를 필요로하는'static'이기 때문입니다. 그래서, 어떤'static' 변수와 마찬가지로, OP는 여전히 구조체 밖에서 선언을 제공해야합니다. – AndyG

+0

(룸이 다 떨어지기 때문에 계속되는 코멘트). 그러나,'TryMe' 구조체를 정의하는 동일한 파일에서'structexpr int TryMe :: arr [1];'정의를 제공하는 것은 좋은 생각이 아닙니다. 왜냐하면'TryMe' 구조체의 정의를 포함하고자하는 클래스가 One Try Rule을 위반하는'TryMe :: arr [1]'의 저장 공간을 할당하려고 시도한다. 그래서 대개 어떤 일이 일어나는지는 헤더에서 분리 된 일종의 .cpp 파일에'constexpr int TryMe :: arr [1]'을 넣는 것입니다. – AndyG

+0

@AndyG 공정한 점, 나는 약간의 지식을 추측했다, 나는 더 상세한 것을 더해야했다. 좀 더 자세히 알려 드리겠습니다. –

관련 문제