I have a Config class
// config.hpp
class Config {
public:
static constexpr int a = 1;
static constexpr int b = 1;
}
and include in main.cpp
// main.cpp
#include "config.hpp"
int main () {
std::cout << Config::a << std::endl; // this is ok
std::shared_ptr<otherClass> stream = std::make_shared<otherClass>(
Config::a); // compile error
}
and compiler said that undefined reference to Config::a
and it works when using cout
, but not work when within shared_ptr
constructor.
I have no idea why this happens.
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 declaredconstexpr
, it is implicitlyinline
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
Your a is private, and either a public: needs to preceed it or make the class a struct to get default public. But this compiles under C++14 https://godbolt.org/g/tS4M1Z
#include <iostream>
#include <memory>
struct Config {
static constexpr int a = 1;
static constexpr int b = 1;
};
struct otherClass {
otherClass( int c ) { }
};
int main () {
std::cout << Config::a << std::endl; // this is ok
std::shared_ptr<otherClass> stream = std::make_shared<otherClass>( Config::a ); // compile error
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With