[英]Does a declaration using “auto” match an extern declaration that uses a concrete type specifier?
標准中對此幾乎沒有什么令人驚訝的。 關於重聲明,我們聽到的所有信息是:
[C++11: 3.1/1]:
聲明(第7條)可以在翻譯單元中引入一個或多個名稱,也可以重新聲明由先前聲明引入的名稱。 [..]
以及auto
語義的唯一相關部分:
[C++11: 7.1.6.4/3]:
否則,將從變量的初始化程序中推斷出變量的類型。 [..]
(提醒我們x
的類型為int
)。
我們知道,所有聲明都必須為變量賦予相同的類型:
[C++11: 3.5/10]:
在對類型進行所有調整之后(在其typedef(7.1.3)被其定義替換之前), 所有引用給定變量或函數的聲明所指定的類型應相同 ,除了數組對象的聲明可以指定因主要數組綁定的存在與否而不同的數組類型(8.3.4)。 違反此類型身份規則的規則不需要診斷。
“所有類型的調整之后”應該解決有關auto
參與所有這些的任何問題; 因此,我的解釋是, 這本質上是在類型為int
全局范圍內對x
的有效重新聲明(和定義),並且Clang是正確的 。 即使我們建議不將auto
視為“類型調整”,因為不需要診斷,最糟糕的是, 所有列出的實現都以自己的方式兼容。
我相信GCC和Visual Studio將從以下方面得到啟發:
[C++11: 7.1.6.4/5]:
在本節中未明確允許的上下文中使用auto
的程序[C++11: 7.1.6.4/5]:
。
…但是我認為這是短視的。 標准語言似乎不可能禁止通常的重新聲明規則,只是因為它們沒有在7.1.6.4
被重復或未明確引用。
C ++ 14增加了與推導類型的函數聲明有關的措辭:
[C++14: 7.1.6.4/13]:
具有使用占位符類型的已聲明返回類型的函數或函數模板的重新聲明或特化也應使用該占位符,而不是推導類型。 [..]
通過對稱有人可能會認為,在你的int
的情況下,其意圖是GCC和VS是拒絕的程序是正確的。 但是,這是一個不同的功能(因為不能將推論僅用於聲明),因此是一個不同的方案。
無論哪種方式,改進的標准措辭都會在這里有所幫助。 我認為這是[合理的次要]編輯缺陷。
我回答了一個與該問題重復的問題。 我要求合並,卻被告知在此處提供答案 。 請參閱下面的原始答案。
我在推特上問了這個問題, 我從理查德·史密斯收到的回復如下:
這不是缺陷,有意使此限制僅適用於推導的返回類型,而不適用於變量類型 。 對於變量,這只是方便的簡寫,但是返回類型推導會影響有關函數(尤其是函數模板)的更基本的內容。
因此,邏輯是[dcl.spec.auto]
允許這樣做,並為推導返回類型限制了這一點,在此部分添加了[dcl.spec.auto]p11
段落。 否則就沒有限制,因此對於變量情況沒有限制。
目前, [dcl.spec.auto]
似乎並未[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.
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.