Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Can a C++ class contain a static const std::array initialized inline in a header file?

Tags:

c++

c++11

This is what I've got:

struct Foo
{
   static std::array<double, 4> acgt_default_background_frequencies() { return {0.281774, 0.222020, 0.228876, 0.267330}; }
};

But I'd prefer to not use a function and instead just have a variable, like this:

struct Foo
{
   static constexpr std::array<double, 4> acgt_default_background_frequencies = {0.281774, 0.222020, 0.228876, 0.267330};
};

What I want compiles, but when I try to use Foo::acgt_default_background_frequencies it gives the linker error "undefined reference to `Foo::acgt_default_background_frequencies'".

Is what I am trying to do possible? I think it is clearer to the reader of my header if I have the value inlined as a const than to hide it in the .cpp file and having a constant as opposed to a function also seems clearer. Isn't the point of constexpr to allow stuff like this? If it isn't possible, why not?

like image 828
JDiMatteo Avatar asked Oct 18 '15 22:10

JDiMatteo


1 Answers

What you have in the second example is a declaration of a static data member which has an initializer, but you haven't provided a definition anywhere. If you make odr-use of that member, a definition will be required.

To provide a definition, add the following to your .cpp file

constexpr std::array<double, 4> Foo::acgt_default_background_frequencies;

The declaration in the question works in C++14, but note that in C++11 you need an extra set of curly braces, e.g.

struct Foo
{
  static constexpr std::array<double, AlphabetSize> acgt_default_background_frequencies = {{0.281774, 0.222020, 0.228876, 0.267330}};
};

The relevant standardese from N3337 §9.4.2/3 [class.static.data]

... 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.

like image 62
Praetorian Avatar answered Nov 02 '22 20:11

Praetorian