Proper initialization of static constexpr array in class template?

不问归期 提交于 2019-12-05 00:32:12

I think you want 9.4.2p3:

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.

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;

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;

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.

In case it helps anyone out, the following worked for me with GCC 4.7 using constexpr:

template<class T> class X {
  constexpr static int s = 0;
};
template<class T> constexpr int X<T>::s; // link error if this line is omitted

I'm not making any claims of whether this is "proper". I'll leave that to those more qualified.

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!