簡體   English   中英

在源文件中聲明 function 模板時,我是否應該防止違反 ODR?

[英]Should I protect against ODR violations when declaring function templates in source files?

一個“普通的”function,當在單個翻譯單元中定義和使用時,聲明和定義如下:

// implementation.cpp
static void fun(int arg) { /* implementation */ }

或者,您可以刪除static關鍵字並將 function 包裝在未命名的命名空間中。 但未能執行上述任一操作可能會導致ODR 違規:如果不同的翻譯單元也具有fun的聲明/定義(具有相同的參數),則喜歡者可能不得不默默地丟棄其中一個實現以保留單個定義(在這種情況下,您最好對兩者都有完全相同的定義,否則您會看到意外的行為)。

如上所述,問題更“面向實現”,但即使是標准也會敦促您使用staticnamespace { /**/ }來防止此類副作用。

問題是當funfunction 模板時會發生什么? 我是否還需要將其包裝在未命名的命名空間中或在翻譯單元內將其聲明為 static?

template <class T>
/* static ? */ void fun(T arg) { /*...*/ }

cppreference中提到,如果 function 是inline的,那顯然沒問題(對單一定義的要求僅針對非內聯函數提出),因此無需擔心 ODR:

每個非內聯function 或 odr 使用的變量(見下文)的一個且只有一個定義需要出現在整個程序中

我們知道 function 模板是內聯的,但這足以保證 ODR 的正確性嗎?

cppreference中提到,如果 function(帶有外部鏈接)被標記為inline ,則必須格外小心,因為該定義必須存在於使用該 function 的每個翻譯單元中。 當有多個定義時,必須滿足幾個條件,包括:

每個定義都由相同的標記序列組成

如果不滿足此要求,則程序格式錯誤,不需要診斷。 此要求同樣適用於內聯函數和 function 模板。 有時這會成功,但如果編譯器選擇不內聯對 function 的調用( inline關鍵字不會影響這一點),您最終可能會調用錯誤版本的 function。 不需要鏈接器來檢測這一點。

事實上,是鏈接器傾向於默默忽略的 ODR 違規。 盡管問題中聲稱有多個定義,但當有多個具有外部鏈接的非內聯 function 定義時,鏈接器往往會產生錯誤並中止。

注意:標記 function static或將其包含在匿名命名空間中將導致它不再具有外部鏈接。


我想指出,這個問題以一種相當常見但非標准的方式使用了“顯然”這個詞,意思是“我需要以下虛假陳述為真,所以毫無疑問地接受它。” 每當你覺得有必要證明某件事是“顯而易見的”時,學會停下來質疑自己是很有用的。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM