简体   繁体   English

constexpr类的全球类型

[英]constexpr global of class type

My understanding is that constexpr globals of class type are all but unusable because 我的理解是,类型的constexpr全局变量几乎无法使用,因为

  • Such an object must be defined in every TU, because constexpr does not permit forward declaration of an object. 必须在每个TU中定义这样的对象,因为constexpr不允许对象的前向声明。

  • Default linkage as static would cause naming the object (ODR-use or not) in an inline function to violate the ODR, because the respective inline definitions would have different meaning. 默认链接为static会导致在内联函数中命名对象(ODR使用与否)以违反ODR,因为相应的inline定义具有不同的含义。

  • Declaration as extern constexpr with one definition per TU would violate the ODR rule if the object is ODR-used, which occurs when a reference to it is taken. 如果对象是ODR使用的,则每个TU具有一个定义的extern constexpr声明将违反ODR规则,这在对其进行引用时会发生。

    • A reference is taken for an implicit this parameter, even if it's unused by a member function. 引用隐式this参数,即使它已被成员函数使用。
    • Obviously happens if you try to pass the object by reference. 如果您尝试通过引用传递对象,显然会发生这种情况。
    • Also happens if you try to pass the object by value, which implicitly uses a copy or move constructor, which by definition passes by reference. 如果您尝试按值传递对象也会发生这种情况,该值隐式使用复制或移动构造函数,根据定义,它通过引用传递。
    • GCC and Clang both complain of ODR violations (multiple definitions) if an object is declared extern constexpr even if not ODR-used. 如果一个对象被声明为extern constexpr即使没有使用ODR,GCC和Clang都会抱怨ODR违规(多个定义)。

Is this all correct? 这都是正确的吗? Is there any way to have a constexpr global of class type without wrapping it in an inline function? 是否有任何方法可以在没有将其包含constexpr inline函数中的情况下拥有类型的constexpr全局?

Global constexpr variables can ODR-safely be defined in headers using a bit of macro magic and the proverbial extra level of indirection 全局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;                           \
}

The macro provides a reference inside an unnamed namespace to an object instance in an implementation class template. 宏在未命名的命名空间内向实现类模板中的对象实例提供引用。

Each object in an unnamed namespace inside a header generates a unique instance in every translation unit that includes its header. 标头内未命名的命名空间中的每个对象在包含其标头的每个转换单元中生成唯一的实例。 Furthermore, to prevent ODR violations, it is important that the objects in eg multiple instantiations of a function template are the same. 此外,为了防止ODR违规,重要的是例如功能模板的多个实例中的对象是相同的。

However, for references it doesn't matter that they have a different identity; 但是,对于参考文献而言,它们具有不同的身份并不重要; as long as they refer to the same object instance in an implementation class template. 只要它们在实现类模板中引用相同的对象实例。

You can wrap this macro in a header and safely include it in many TUs without a problem. 您可以将此宏包装在标头中,并将其安全地包含在许多TU中而不会出现问题。

See the following discussion on the Boost mailinglist for more details: http://lists.boost.org/Archives/boost/2007/06/123380.php 有关详细信息,请参阅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