2016-07-14 54 views
16

所以我很困惑這是如何工作的。鑑於:不應該decltype觸發器編譯它的參數?

template <typename T> 
int foo(T t) { t.foo(); } 

好像這個調用失敗了:

decltype(foo(int{ 13 })) fail = 42; 

cout << fail << endl; 

相反it just prints

它適用於所有我的編譯器這樣進入。這是正確的行爲?我請求來自C++標準的報價。

+0

'std :: type_info :: name()'不保證給任何可靠的東西。在其他情況下是否給予其他任何東西? – StoryTeller

+0

@StoryTeller我已經從問題中消除了'type_info'。希望這有助於澄清問題。這是一個關於'decltype'和它需要什麼的問題,我只是試圖用'type_info'來演示這個問題。 –

+5

'decltype'確實不需要全功能定義來知道結果類型。 ([見](http://ideone.com/eHSQ92))。所以除了原型之外沒有任何理由要編譯它。但我沒有標準報價。 – StoryTeller

回答

17

[dcl.spec]

對於表達式e,通過decltype(e)中表示的類型定義爲 如下:

如果e是一個括號的ID-表達命名引入左值或參考從分解 聲明的標識符列表中,decltype(e)是分解聲明([dcl.decomp])的 規範中給出的引用類型;否則,如果e是非隱含的id表達式或未隱含的類成員訪問([expr.ref]),decltype(e)是由e命名的實體的 類型。如果沒有這樣的實體,或者如果命名一組重載函數,則該程序是不合格的;如果e是x值,則decltype(e)是T & &,其中T是e的類型;否則,如果e是左值,則decltype(e)是T &,其中T是e的類型;如果e是左值,則decltype(e)是T &,其中T是e的類型;

否則,decltype(e)是e的類型。

decltype說明符的操作數是未評估的操作數 (子句[expr])。

(重點煤礦)

所以你foo(int{ 13 })不會求。

+0

完美的答案,謝謝。我很害怕我會接受[Jesper Juhl的「因爲我這麼說」答案)(http://stackoverflow.com/a/38373961/2642059)。 –

+0

我不知道這是否真的意味着編譯必須成功。例如。在'1? 0:foo(int {13})'調用永遠不會被評估,但我不希望這個編譯。 (可能有一些關於在檢查未評估的操作數時做了什麼的具體規則......?) – chi

+4

如果將上述函數模板的定義更改爲'template auto foo(T t){t.foo(); },模板的實例化似乎雖然發生了 - 這對我來說很有意義,因爲沒有返回類型推理,'decltype'沒有辦法產生任何東西。這當然會以編譯時錯誤結束。上述條款中的哪個部分反映了這種行爲?我錯過了什麼嗎? – thokra

5

decltype中的表達式被標準定義爲不被評估,它們只被解析以獲取表達式的類型。

+5

提到宇宙主文檔的必要問題。 –

+6

這是一個簡短的答案。我將對此發表評論,而不是回答本身:我已經確定我有權訪問的編譯器支持您的聲明。所以問題是:「這是正確的行爲嗎?」要確定你需要引用的東西比你獲得的知識更多。 –

+0

@JonathanMee對你有什麼用處?你被告知編譯器是正確的,爲什麼你需要一個規範參考?你打算根據規範文本來驗證他的答案嗎?不管標準實際上是怎麼說的,你有多確信你沒有被相信標準所說的答案所愚弄? –