在类模板中正确初始化静态constexpr数组? [英] Proper initialization of static constexpr array in class template?

查看:180
本文介绍了在类模板中正确初始化静态constexpr数组?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

由于标准的困扰,C ++中的静态类成员对我造成了一些困惑:

Static class members in C++ have caused a little confusion for me due to the standard's verbiage:


9.4.2静态数据成员 [class.static.data]

在其类定义中声明静态数据成员不是定义...

The declaration of a static data member in its class definition is not a definition...

但是在其声明时(例如,在 constexpr 中需要初始化 constexpr

However a constexpr is required to be initialized (AFAIK, couldn't find a quote from the standard) at its declaration (e.g., in the class definition).

由于对constexpr的限制,我实际上已经忘记了在类外定义静态成员的必要条件,直到尝试访问静态constexpr数组为止。 此相关问题提供了定义数组成员的正确方法,但是我我对类模板中此定义的含义感兴趣。

Because of the restrictions on constexpr I had actually forgotten about the requisite for static members to be defined outside of the class, until I tried accessing a static constexpr array. This related question provides the correct way of defining the array member, but I'm interested as to the implications on this definition in a class template.

这就是我最终得到的结果:

This is what I ended up with:

template<typename T>
class MyClass
{
private:
  static constexpr std::size_t _lut[256] = { /* ... */ };
  T _data;

public:
  static constexpr std::size_t GetValue(std::size_t n) noexcept
  {
    return _lut[n & 255];
  }

  // ...
};

template<typename T>
constexpr std::size_t MyClass<T>::_lut[256];

这是正确的语法吗?特别是在定义中使用模板感觉很尴尬,但是GCC似乎在适当地链接所有内容。

Is this the right syntax? Particularly the use of template in the definition feels awkward, but GCC seems to be linking everything appropriately.

作为后续问题,是否应该类似地定义非数组静态constexpr成员(使用类之外的模板定义)?

As a follow-up question, should non-array static constexpr members be similarly defined (with template definition outside of class)?

推荐答案

我想您想要9.4.2p3:

I think you want 9.4.2p3:


如果非易失性 const static 数据成员为整数或枚举类型,则其在类定义中的声明可以指定 brace-or-equal-initializer ,其中每个作为 assignment-expression initializer-clause 都是一个常数表达式(5.19)。可以使用 constexpr 说明符在类定义中声明文字类型的静态数据成员;如果是这样,则其声明应指定一个
brace-or-equal-initializer ,其中每个 assignment-expression initializer-clause 常数表达式。 [...]如果在程序中使用了成员(3.2),则该成员仍应在命名空间范围内定义,并且该命名空间范围定义不应包含 initializer

If a non-volatile const static data member is of integral or enumeration type, its declaration in the class definition can specify a brace-or-equal-initializer in which every initializer-clause that is an assignment-expression is a constant expression (5.19). A static data member of literal type can be declared in the class definition with the constexpr specifier; if so, its declaration shall specify a brace-or-equal-initializer in which every initializer-clause that is an assignment-expression is a constant expression. [...] The member shall still be defined in a namespace scope if it is odr-used (3.2) in the program and the namespace scope definition shall not contain an initializer.

template 静态数据成员的定义是 template-declaration (14p1)。在14.5.1.3p1中给出的示例是:

The definition of a template static data member is a template-declaration (14p1). The example given in 14.5.1.3p1 is:

template<class T> class X {
  static T s;
};
template<class T> T X<T>::s = 0;

但是,与上面的 constexpr static 或在类声明中指定 initializer const static 成员,其名称空间范围定义中不应包含 initializer 。语法变为:

However, as above a constexpr static or const static member whose in-class declaration specifies an initializer should not have an initializer in its namespace scope definition, so the syntax becomes:

template<class T> class X {
  const static T s = 0;
};
template<class T> T X<T>::s;

与非数组(即整数或枚举)静态constexpr数据成员的区别在于其用途在左值到右值转换中,不能使用odr;您只需定义其地址或对其构成const引用即可对其进行定义。

The difference with the non-array (i.e. integral or enumeration) static constexpr data member is that its use in lvalue-to-rvalue conversion is not odr-use; you would only need to define it if taking its address or forming a const reference to it.

这篇关于在类模板中正确初始化静态constexpr数组?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆