2016-05-16 71 views
-3

爲什麼通過const引用傳遞參數總是意味着該對象是ODR使用?我明白,因爲Standard以這種方式定義它,但爲什麼它沒有至少爲整型常量做例外?ODR使用行爲的基本原理

例如(從幾個小時前在回答我自己的例子):

struct T { 
    static constexpr int i = 42; 
}; 

void check(const int& z); 

int main() { 
    check(T::i); // <- 1 
    check(42); // <- 2 
} 

(1)將通過靶向鏈接時錯誤 - 標準考慮它的T::i ODR-使用是,並沒有定義在望。但是,示例(2)的標準沒有問題。而且由於(2)已經工作,爲什麼不能(1)工作constexpr內?我意識到,通常你需要把對象的地址通過引用傳遞給它,但肯定不是在數字文字的情況下。爲什麼標準不會爲某些constexpr類型制定例外規定?

僅僅是爲了避免標準中出現太多例外情況?但我看到允許使用如上所述非常有益!還有什麼我看不到的?

+2

如果您告訴我們「x」是什麼以及「檢查」是幹什麼的,您寫的內容會更有意義,正如您在此處所做的:http://stackoverflow.com/a/372​​59949/3758484 – johnbakers

+1

簡單回答:是不是× – NathanOliver

+0

我想知道爲什麼人們低估了這個問題。我也想知道爲什麼它'主要基於意見' - 沒有任何意見基礎,@巴里解釋得很好。 – SergeyA

回答

4

然而,標準與例如沒有問題(2)

因爲在(2)中,我們創建int const&類型的臨時綁定到所述prvalue 42的情況下。

T::i不是一個右值,它是一個左值 - 所以我們不會嘗試創建一個臨時值,我們將嘗試綁定到實際的對象。但編譯器如何知道T::i是一個左值,你不想最終提供一個定義,在這種情況下,你真正的意思是構造一個臨時的並複製它? constexpr不是該類型的一部分,i的類型僅僅是int const。你可能不得不跳過一大堆障礙,甚至試圖提出一個措辭,可以正確地免除你的static constexpr int i,但某些成員const int i

全部解決什麼問題?您可以通過+T::i手動執行左值到右值轉換,並實現相同的目的。或者提供T::i的定義。

ODR規則足夠複雜 - 您需要一個令人信服的理由在其中鑽出一個洞。

+0

事實上,現在它是有道理的,當你用左值和右值表示它時。我沒有看到這是定義的原因。 – SergeyA

+0

很酷,我現在知道兩個真正晦澀的事情,你可以使用一元+! (整體推廣是另一種。) –

+0

@AlanStokes [這是第三個](http://stackoverflow.com/q/18889028/2069064)。 – Barry

2

假設在兩個TU中發生相同的呼叫。功能check可以取z的地址,並且標準保證它將在兩個呼叫中看到相同的地址。

除了分配一個存儲位置並在那裏放置i以外,你會如何做到這一點?這幾乎是ODR使用的說法。

+0

這不回答我的問題。如果地址是唯一的問題,它可以像文字一樣工作。 – SergeyA

+1

不,它不能。允許從兩個不同TU調用的「check(1)」傳遞兩個不同的地址; '檢查(T :: i)'不是。而「檢查」可以說明差異。 –

+0

我們可以爲'constexpr'和地址制定一個例外,並且制定與文字相同的規則?我認爲,我發現@Barry在rvalue和rvalue方面的回答更具說服力。 – SergeyA