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
staticdata member is declaredconstexpr, it is implicitlyinlineand 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