c++ constexpr類的全域性型別
我的理解是,型別的constexpr全域性變數都是不可用的,因為
>這樣的物件必須在每個TU中定義,因為constexpr不允許向前宣告一個物件.
>預設連結為靜態會導致命名行內函數中的物件(ODR-使用或不使用)違反ODR,因為相應的內聯定義具有不同的含義.
>作為extern constexpr的宣告,每個TU有一個定義,如果物件是使用ODR,則會導致ODR規則,當引用該引用時,會出現ODR規則.
>對於一個隱含的引數,即使沒有被一個成員函式使用也是一個引用.
>如果您嘗試通過引用傳遞物件,顯然會發生.
>如果您嘗試通過值傳遞物件,也會發生,該值隱式使用複製或移動建構函式,按定義通過引用.
如果物件被宣告為extern constexpr,即使不使用ODR,GCC和Clang都會抱怨ODR違規(多個定義).
這是否正確?有沒有任何方法可以將constexpr的全域性類型別包裝在一個行內函數中?
全域性constexpr變數可以使用一點巨集觀魔法和諺語間接的額外級別在標頭檔案中定義ODR
#define PP_GLOBAL_CONSTEXPR_VARIABLE(type, var, value)\ namespace var##detail {\ template<class = void>\ struct wrapper\ {\ static constexpr type var = value;\ };\ template<class T>\ constexpr type wrapper<T>::var;\ }\ namespace {\ auto const& var = var##detail::wrapper<>::var;\ }
巨集提供了一個未命名的名稱空間中的引用
到實現類模板中的物件例項.
標頭內未命名的名稱空間中的每個物件都會生成
每個翻譯單元中包含其標題的唯一例項.
此外,為了防止ODR違規,重要的是物件
在例如功能模板的多個例項是相同的.
然而,對於參考,它們並不重要,它們具有不同的身份;
只要它們在實現中引用相同的物件例項
類模板.
您可以將此巨集包裝在標題中,並將其安全地包含在許多TU中而沒有問題.
程式碼日誌版權宣告:
翻譯自:http://stackoverflow.com/questions/20370024/constexpr-global-of-class-type