簡體   English   中英

constexpr類的全球類型

[英]constexpr global of class type

我的理解是,類型的constexpr全局變量幾乎無法使用,因為

  • 必須在每個TU中定義這樣的對象,因為constexpr不允許對象的前向聲明。

  • 默認鏈接為static會導致在內聯函數中命名對象(ODR使用與否)以違反ODR,因為相應的inline定義具有不同的含義。

  • 如果對象是ODR使用的,則每個TU具有一個定義的extern constexpr聲明將違反ODR規則,這在對其進行引用時會發生。

    • 引用隱式this參數,即使它已被成員函數使用。
    • 如果您嘗試通過引用傳遞對象,顯然會發生這種情況。
    • 如果您嘗試按值傳遞對象也會發生這種情況,該值隱式使用復制或移動構造函數,根據定義,它通過引用傳遞。
    • 如果一個對象被聲明為extern constexpr即使沒有使用ODR,GCC和Clang都會抱怨ODR違規(多個定義)。

這都是正確的嗎? 是否有任何方法可以在沒有將其包含constexpr inline函數中的情況下擁有類型的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中而不會出現問題。

有關詳細信息,請參閱Boost郵件列表中的以下討論: http//lists.boost.org/Archives/boost/2007/06/123380.php

暫無
暫無

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

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