2013-10-28 33 views
54

這只是在another question的背景下出現的。「ODR使用」是什麼意思?

顯然,類模板中的成員函數僅在使用ODR時才實例化。 有人可以解釋究竟是什麼意思。 wikipedia article on One Definition Rule (ODR)沒有提及「ODR-使用」。

然而,標準將其定義爲

一個變量,其名稱顯示爲潛在評估表達 是ODR使用的,除非它是滿足出現在常量表達式爲 要求的對象(5.19)和左值到右值 轉換(4.1)立即應用。

in [basic.def.odr]。

編輯:顯然這是錯誤的部分,整個段落包含不同事物的多個定義。這可能是相關的一個類模板的成員函數:

甲非過負荷函數,其名稱顯示爲 潛在評估表達或一組候選 功能的成員,如果由過載分辨率時,選擇參考 潛在評估的表達式,除非它是純粹的虛擬函數並且其名稱沒有明確限定,否則是odr-used。

但我不明白,這條規則是如何在多個編譯單元中工作的?如果我明確實例化類模板,是否所有成員函數都實例化?

+1

請注意[basic.def.odr]/6適用於類模板的成員函數「可以有多個定義[0123]」 – dyp

+2

*「是否所有成員函數都實例化如果我明確實例化一個類模板?「*是的,看看[temp.explicit]/8 + 9 – dyp

回答

48

這只是一個任意的定義,由標準使用的 指定何時必須爲實體提供定義(因爲 與僅僅聲明相對)。該標準並不僅僅說明 「使用」,因爲這可以根據 上下文不同地解釋。而一些ODR的使用並不真正對應於通常與「使用」相關聯的一個 ;例如,除非是純粹的,否則虛擬 函數始終是ODR使用的,即使它不是程序中任何地方實際調用的函數。

完整的定義在§3.2的第二段,儘管這個 包含對其他部分的引用來完成 的定義。

關於模板,使用ODR只是問題的一部分; 另一部分是實例化。特別是,當模板被實例化時,§14.7涵蓋了 。但是這兩者是相關的:儘管 第14.7.1節(隱式實例化)中的文本相當長,但基本原理是隻有在使用 時纔會實例化模板,在這種情況下,意味着ODR-用過的。因此, 類模板的成員函數僅在被調用時纔會被實例化爲 ,或者如果它是虛擬的,並且類自身被實例化,則 。該標準本身在許多地方 統計上這樣的:std::list<>::sort使用<對個人 元素,但你可以在實例化的元素類型 列表不支持<,只要你不叫 sort它。

+7

Upvoted:我喜歡'std :: list <> :: sort'的例子。 –

2

簡而言之,odr-used表示在必須存在定義的上下文中使用的東西(變量或函數)。

例如,

struct F { 
    static const int g_x = 2; 
}; 

int g_x_plus_1 = F::g_x + 1; // in this context, only the value of g_x is needed. 
          // so it's OK without the definition of g_x 

vector<int> vi; 
vi.push_back(F::g_x);  // Error, this is odr-used, push_back(const int & t) expect 
          // a const lvalue, so it's definition must be present 

注意,在MSVC 2013通過上面的push_back,這種行爲是不是符合標準,無論是GCC 4.8.2和3.8.0鏗鏘失敗,錯誤消息是: 未定義參考到`K :: g_x'

+0

是否有可能在C++中使用類似'vi.push_back(F :: g_x);'的靜態數據成員? –

+0

但是右值也可以傳遞給'const int&'嗎?靜態const成員可以作爲右值嗎? – bigxiao