Note that std::make_shared takes parameter by reference, which causes Config::a
to be odr-used because it'll be bound to the reference parameter, then its definition at namespace scope is required (before C++17).
On the other hand, std::cout << Config::a
won't cause Config::a
to be odr-used, because std::basic_ostream::operator<< (int) takes parameter by value, Config::a
is then subject to lvalue-to-rvalue conversion requested to copy-initialize the parameter, therefore Config::a
is not odr-used.
If an object is odr-used, its definition must exist. You can add the definition (in an implementation file) as
constexpr int Config::a; // only necessary before C++17
Note that it cannot have an initializer.
LIVE
Since C++17 constexpr
static data member is implicitly inline then such definition is not required again, so your code works well from C++17.
If a static
data member is declared constexpr
, it is implicitly inline
and does not need to be redeclared at namespace scope. This redeclaration without an initializer (formerly required as shown above) is still permitted, but is deprecated.
LIVE
a
at namespace scope like a static member prior to c++17, ieconstexpr int Config::a;
– Sheepherdercout
works? – Sharlamake_shared
not work.make_shared<otherClass>(int(Config::a))
will also work – Sheepherder