6

consider a class with a constant member:

class foo {
public:
    const static int N;
};

foo::N needs to initialized:

constexpr int foo::N = 5;

and note how using the constexpr qualifier instead of const here seems like a mistake.

but GCC, Clang and MSVC all compile just fine!

  • is there something in the language that allows changing qualifiers here?
  • is it an error overlooked by all three compilers?

Clang even allows both qualifier versions simultaneously:

constexpr int foo::N = 3;
const int foo::N = 5;

int main(){
    return foo::N; //returns 3
}

what's going on?

Stack Danny
  • 7,754
  • 2
  • 26
  • 55

1 Answers1

2

Since obviously the value of a variable that has been declared but not defined cannot be used in a constant expression, constexpr pertains only to the definition of a variable. (Of course, if the variable is inline, perhaps because of being a static member declared constexpr, every definition must have constexpr.) It implies const (on the variable itself: constexpr char* is char *const, not const char*), so you haven’t changed the variable’s type. This is no different from

// foo.hpp
extern const int x;

// foo.cpp
constexpr int x=2;

which is perhaps less surprising.

So everything is fine! The variable’s value can be used in constant expressions only in the translation unit that contains the definition, but that’s no surprise, and could easily be construed as a feature for modularity. Clang is buggy to allow two definitions: presumably it’s trying to ignore the (deprecated, as of C++17) out-of-class definition for a constexpr static data member defined in the class.

Davis Herring
  • 36,443
  • 4
  • 48
  • 76