1

Consider this use case of a static constexpr member:

// smart_enum.h
class smart_enum {
    // Some data, operations, etc.
    // Cannot use constexpr here, smart_enum is incomplete at this point
    static const smart_enum first, second;
};

constexpr smart_enum smart_enum::first = {}, smart_enum::second = {};

Are first and second automatically inline variables? Or do I need to qualify them as such? Or am I unable to qualify them as inline and need to provide a definition in some source file later? I have always been confused by this "redefinition" from const to constexpr and would like more light to be shed on what this really means.

Specifically I am wondering about the interaction of const declaration to constexpr definition and how that plays out with automatic inline of a static constexpr (Redefinitions of constexpr static data members are allowed now? (but not inline const)?)

user975989
  • 2,578
  • 1
  • 20
  • 38
  • "Also, the ​constexpr​ specifier implies inline for static data members as well as functions." - however I'd put that constexpr in the class I think. – lorro Oct 11 '17 at 06:46
  • @lorro but you can't put it in the class, which is where my confusion stems. – user975989 Oct 11 '17 at 06:47

2 Answers2

1

the standard says:

[c++17-12.2.3.2-2]The declaration of a non-inline static data member in its class definition is not a definition and may be of an incomplete type other than cv void.

now, maybe your confusion stems from believing that the two expressions

static const smart_enum first; // class scope
constexpr smart_enum smart_enum::first = ...; // namespace scope

declare different types. This is not the case because the type of a constexpr T is still const T ( in fact you can always write constexpr const T to mean the same thing ).

So, in your code, you first declare a name 'first' of incomplete type 'const smart_enum', then you leter define it as "constexpr smart_enum" ( or "constexpr inline const smart_enum" if we add everything constexpr implies explictly ).

Massimiliano Janes
  • 5,524
  • 1
  • 10
  • 22
1

In C++14, no variables are inline, of course. Making variables like this automatically inline was an unintentional breaking change (since it means that the definition must appear in every translation unit). I filed CWG2531 to try to have this rectified. There are now of course backwards-compatibility concerns with C++17 implementations, although any code that wants the other behavior can just add inline to the out-of-class definition as is already allowed.

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