C ++ 17은 인라인 변수를 소개합니다
C ++ 17 constexpr static
은 odr-used 인 경우 out-of-line 정의가 필요한 멤버 변수에 대해이 문제를 해결합니다 . C ++ 17 이전의 세부 사항은이 답변의 후반부를 참조하십시오.
제안 P0386 인라인 변수 는 inline
지정자 를 변수 에 적용하는 기능을 소개합니다 . 특히이 경우 정적 멤버 변수를 constexpr
의미 inline
합니다. 제안은 다음과 같이 말합니다.
인라인 지정자는 변수뿐만 아니라 함수에도 적용 할 수 있습니다. 인라인으로 선언 된 변수는 인라인으로 선언 된 함수와 동일한 의미를 갖습니다. 여러 번역 단위로 동일하게 정의 될 수 있으며, 변수가 사용되는 모든 변환 단위에서 정의되어야하며 프로그램의 동작은 마치 정확히 하나의 변수가 있습니다.
수정 된 [basic.def] p2 :
선언은
...이 아닌 한 정의입니다 .
- 클래스 정의 외부에서 정적 데이터 멤버를 선언하고 변수는 constexpr 지정자를 사용하여 클래스 내에 정의되었습니다 (이 사용법은 더 이상 사용되지 않습니다. [depr.static_constexpr] 참조).
...
[depr.static_constexpr]을 추가하십시오 :
이전 C ++ 국제 표준과의 호환성을 위해 constexpr 정적 데이터 멤버는 이니셜 라이저없이 클래스 외부에서 중복 적으로 다시 선언 될 수 있습니다. 이 사용법은 더 이상 사용되지 않습니다. [ 예:
struct A {
static constexpr int n = 5; // definition (declaration in C++ 2014)
};
constexpr int A::n; // redundant declaration (definition in C++ 2014)
— 최종 예]
C ++ 14 및 이전
C ++ 03에서는 const 정수 또는 const 열거 형에 클래스 내 이니셜 라이저 만 제공 할 수있었습니다.이를 사용하는 C ++ 11에서는 리터럴 형식constexpr
으로 확장되었습니다 .
C ++ 11에서 우리는 정적에 대한 네임 스페이스 범위 정의를 제공 할 필요가 없습니다 constexpr
, 그렇지 않은 경우는 회원 ODR 사용되는 , 우리는 초안 C ++ 11 표준 섹션이를 볼 수 있습니다 9.4.2
[class.static.data] 말한다 ( 앞으로 강조하는 광산 ) :
[...] 리터럴 타입의 정적 데이터 멤버는 constexpr 지정자를 사용하여 클래스 정의에서 선언 할 수 있습니다. 그렇다면 선언은 할당 식인 모든 이니셜 라이저 절이 상수 표현식 인 중괄호 또는 이니셜 이니셜 라이저를 지정해야합니다. [참고 :이 두 경우 모두 멤버가 상수 식으로 나타날 수 있습니다. —end note]
멤버는 프로그램에서 odr-used (3.2) 를 사용하는 경우 네임 스페이스 범위에서 계속 정의되고 네임 스페이스 범위 정의에는 이니셜 라이저가 포함되지 않아야합니다.
그래서 질문은 여기에서 baz
odr-used 됩니다.
std::string str(baz);
대답은 yes 이므로 네임 스페이스 범위 정의도 필요합니다.
그렇다면 변수가 odr-used 인지 어떻게 알 수 있습니까? 3.2
[basic.def.odr] 섹션의 원래 C ++ 11 문구 는 다음과 같습니다.
표현식은 평가되지 않은 피연산자 (Clause 5) 또는 하위 표현식이 아닌 한 잠재적으로 평가됩니다. 상수 식 (5.19) 에 나타나고 lvalue-to-rvalue 변환 (4.1)에
해당 하는 조건 이 충족 되지 않는 개체가 아닌 경우 이름이 잠재적으로 평가되는 식으로 나타나는 변수 는 odr-used 입니다.
따라서 상수 표현식baz
이 생성 되지만 lvalue-to-rvalue 변환은 배열 로 인해 적용 할 수 없으므로 즉시 적용되지 않습니다 . 이것은 [conv.lval] 섹션에서 다루고 있습니다 :baz
4.1
비 기능, 비 배열 타입 T 의 glvalue (3.10) 는 prvalue로 변환 될 수 있습니다. [...]
무엇이에 적용되는 배열에 대한 포인터 변환 .
[basic.def.odr] 의이 문구는 일부 사례가이 문구로 다루지 않았기 때문에 결함 보고서 712 로 인해 변경되었지만 이러한 변경 으로 인해이 사례의 결과는 변경되지 않습니다.