3

I know that in C++11, I can write

class foo {
    static constexpr const char *one = "one";
}

However, when I try to do the same for an array

class bar {
    static constexpr const float prim[4] = {2, 3, 5, 7};
}

(and reference it later on) I get an undefined reference linker error.

Is this just not possible for arrays or am I missing something in the syntax?

llllllllll
  • 16,169
  • 4
  • 31
  • 54
schtandard
  • 387
  • 4
  • 18
  • The declaration and usage of this example compiles fine on GCC 7.2 – Fureeish Feb 06 '18 at 16:13
  • Look at good answer there https://stackoverflow.com/questions/29397864/why-does-constexpr-static-member-of-type-class-require-a-definition – 273K Feb 06 '18 at 16:32

1 Answers1

2

Static constexpr data member declarations aren't definitions in C++11/14, therefore you cannot odr-use prim.
To work around it, put the following statement somewhere in your cpp file as you would do with any other non-constexpr static data member:

constexpr const float bar::prim[4];

In other terms, this returns an undefined reference:

struct bar {
    static constexpr const float prim[4] = {2, 3, 5, 7};
};

int main() {
    auto *foo = bar::prim;
}

This doesn't:

struct bar {
    static constexpr const float prim[4] = {2, 3, 5, 7};
};

constexpr const float bar::prim[4];

int main() {
    auto *foo = bar::prim;
}

Because in the second case you are actually defining prim other than declaring it and thus you can get its address, use it by means of a reference, and so on...

skypjack
  • 49,335
  • 19
  • 95
  • 187
  • Is this still required in C++17, Which allows inline variables to be initialized in the class? – Robert Andrzejuk Feb 06 '18 at 19:34
  • @RobertAndrzejuk In C++17 (I cite the standard) _a function or static data member declared with the constexpr specifier is implicitly an inline function or variable_. Therefore things changed with C++17 actually. – skypjack Feb 06 '18 at 20:25