"auto"를 사용하는 선언이 구체적인 유형 지정자를 사용하는 extern 선언과 일치합니까?
다음 프로그램을 고려하십시오.
extern int x;
auto x = 42;
int main() { }
Clang 3.5는이를 허용하지만 ( 라이브 데모 ) GCC 4.9 및 VS2013은 허용하지 않습니다 (전자의 경우 라이브 데모 ). 누가 옳고 C ++ 표준에 지정된 올바른 동작은 어디입니까?
이것에 대한 표준에는 놀랍게도 거의 없습니다. 재 선언에 대해 우리가 듣는 모든 내용은 다음과 같습니다.
[C++11: 3.1/1]:
선언 (Clause 7)은 하나 이상의 이름을 번역 단위에 도입하거나 이전 선언에서 도입 한 이름을 재 선언 할 수 있습니다. [..]
auto
의 의미론 의 유일한 관련 부분 :
[C++11: 7.1.6.4/3]:
그렇지 않으면 변수의 유형이 초기화 프로그램에서 추론됩니다. [..]
(의 유형이 있음을 상기시키는 x
것입니다 int
).
우리는 변수가 모든 선언에서 동일한 유형을 제공해야한다는 것을 알고 있습니다.
[C++11: 3.5/10]:
모든 유형 조정 후 (어떤 typedef (7.1.3)가 정의로 대체되는 동안), 주어진 변수 또는 함수를 참조하는 모든 선언에 의해 지정된 유형은 동일해야합니다 . 단, 배열 객체에 대한 선언은 다음과 같은 배열 유형을 지정할 수 있습니다. 주요 배열 바운드 (8.3.4)의 유무에 따라 다릅니다. 유형 ID에 대한이 규칙 위반은 진단이 필요하지 않습니다.
그리고 "모든 유형의 조정 이후"는 auto
'이 모든 것에 참여하는 것과 관련된 모든 질문을 처리해야합니다 . 내 해석은 이것이 본질적 x
으로 유형 이있는 at 전역 범위 의 유효한 재 선언 (및 정의)이며 int
Clang이 정확하다는 것 입니다. auto
진단이 필요하지 않기 때문에 "유형 조정"으로 간주되지 않는다고 제안하더라도 , 최악의 경우 나열된 모든 구현은 자체 방식으로 호환됩니다.
GCC와 Visual Studio는 다음을 영감으로 삼고 있다고 생각합니다.
[C++11: 7.1.6.4/5]:
auto
이 섹션에서 명시 적으로 허용되지 않은 컨텍스트에서 사용하는 프로그램 은 형식이 잘못되었습니다.
…하지만 근시안적이라고 생각합니다. 표준 언어가에서 반복되거나 명시 적으로 참조되지 않는다는 이유로 일반적인 재 선언 규칙을 금지하려는 의도는 아닌 것 같습니다 7.1.6.4
.
C ++ 14는 추론 된 유형 이있는 함수 선언과 관련된 문구를 추가합니다 .
[C++14: 7.1.6.4/13]:
자리 표시 자 형식을 사용하는 선언 된 반환 형식이있는 함수 또는 함수 템플릿의 재 선언 또는 특수화는 추론 된 형식이 아닌 해당 자리 표시자를 사용해야합니다. [..]
대칭 적으로 당신의 int
경우 GCC와 VS가 프로그램을 거부하는 것이 정확하다는 것을 제안 할 수 있습니다 . 그러나 이것은 다른 기능이며 (단순한 선언에는 공제가 적용될 수 없기 때문에) 다른 시나리오입니다.
어느 쪽이든 개선 된 표준 문구가 여기에 도움이 될 것입니다. 나는 그것이 [합리적으로 사소한] 편집상의 결함이라고 생각합니다.
노트
나는 이 질문과 중복 된 질문 에 답했다 . 나는 병합을 요청했고 대신 여기에 대답 을 제공 하라는 지시를 받았다 . 내 원래 답변은 아래를 참조하십시오.
업데이트 clang이 정확합니다.
나는에이 질문을 트위터 와 나는 리처드 스미스로부터받은 응답은 다음과 같이했다 :
결함이 아닙니다. 이 제한은 추론 된 반환 유형에만 적용되고 변수 유형에는 적용되지 않습니다 . 변수의 경우 이는 편의상의 속기 일 뿐이지 만 반환 유형 추론은 함수 (특히 함수 템플릿)에 대해 더 근본적인 것에 영향을줍니다.
따라서 논리는 이것이 허용되고 [dcl.spec.auto]
추론 된 반환 유형에 대해 이것을 제한하는 것입니다. 단락 [dcl.spec.auto]p11
이 섹션에 추가되었습니다. 그렇지 않으면 제한이 없으므로 변수 케이스에 대해 제한되지 않습니다.
실물
현재 [dcl.spec.auto]
는이 경우를 명시 적으로 다루지 않는 것 같지만 [dcl.spec.auto] p5 에서는 다음과 같이 말합니다 .
이 하위 절에서 명시 적으로 허용되지 않는 컨텍스트에서 auto 또는 decltype (auto)을 사용하는 프로그램은 형식이 잘못되었습니다.
[dcl.spec.auto] p11 에서 형식이 잘못된 함수에 대해서도 비슷한 경우가 발생하는 것을 볼 수 있습니다 .
자리 표시 자 형식을 사용하는 선언 된 반환 형식이있는 함수 또는 함수 템플릿의 재 선언 또는 특수화 는 추론 된 형식이 아닌 해당 자리 표시자를 사용해야합니다 . 마찬가지로 자리 표시 자 형식을 사용하지 않는 선언 된 반환 형식이있는 함수 또는 함수 템플릿의 재 선언 또는 특수화 는 자리 표시자를 사용하지 않습니다 . [ 예:
auto f(); auto f() { return 42; } // return type is int auto f(); // OK int f(); // error, cannot be overloaded with auto f()
....
따라서 이것이 현재 표현 된대로 설명을 사용할 수 있지만 gcc가 정확하고 잘못된 형식 인 것처럼 느껴집니다.
[dcl.spec.auto] p11 의 제한 이 존재한다고 생각합니다. 그렇지 않으면 다음을 허용합니다.
int f();
auto f(); // What's the return type here?
문제는 추론되지 않은 유형이 함수의 반환 유형을 가질 수 있다는 것입니다. 이전 선언에 기반한 공제 규칙이 없기 때문에 다음과 같은 경우에도 이러한 혼합이 함수에 대해 허용되지 않습니다.
int f();
auto f() { return 1; }
변수에는이 문제가 없습니다.
extern int v;
extern auto v; // ill-formed
모든 선언 전용 변수는 자리 표시자가 아닌 유형을 사용해야합니다. 이것이 의미하는 바는의 정의에 자리 표시 자 유형을 사용하면 v
문제없이 추론 될 수 있으며 물론 첫 번째 선언에서 사용 된 자리 표시자가 아닌 유형과 일치해야한다는 것입니다.
extern int v;
auto v = 1; // ok, type deduced as 'int', matches first declaration.
'your programing' 카테고리의 다른 글
가능한 값 : PHP_OS (0) | 2020.12.31 |
---|---|
new char은 실제로 클래스 유형에 대해 정렬 된 메모리를 보장합니까? (0) | 2020.12.31 |
java.lang.Object에서 'shadow $ _klass_'및 'shadow $ _monitor_'변수는 무엇입니까? (0) | 2020.12.31 |
Rails 마이그레이션을 어떻게 테스트하나요? (0) | 2020.12.31 |
size_t가 서명되지 않은 이유는 무엇입니까? (0) | 2020.12.30 |