your programing

"auto"를 사용하는 선언이 구체적인 유형 지정자를 사용하는 extern 선언과 일치합니까?

lovepro 2020. 12. 31. 23:05
반응형

"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 전역 범위 의 유효한 재 선언 (및 정의)이며 intClang이 정확하다는 것 입니다. 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.

참조 URL : https://stackoverflow.com/questions/26386010/does-a-declaration-using-auto-match-an-extern-declaration-that-uses-a-concrete

반응형