Compiling with -std=c++14 the following code:
#include <memory>
class A
{
public:
static constexpr int c = 0;
std::shared_ptr<int> b;
A() {
b = std::make_shared<int> (c);
}
};
int main () {
A a;
return 0;
}
Gives a linker error "undefined reference to `A::c'", while using "A::c" in other contexts that are not "make_shared", this error doesn't occur. In particular, the following code compiles and works correctly:
class A
{
public:
static constexpr int c = 0;
std::shared_ptr<int> b;
A() {
int cc = c;
b = std::make_shared<int> (cc);
}
};
Since C++17 the first code should work correctly: a
static constexprclass member variable is implicitlyinlinewhich means the compiler takes care of making sure a definition exists .Prior to C++17 the code has undefined behaviour (no diagnostic required) due to ODR violation. A static class member that is odr-used must also have an out-of-line definition.
Binding a reference to a variable counts as odr-use, and that happens with
make_shared<int>(c)since that function is defined as :so the argument is bound to a reference parameter.
In theory you should be able to work around it with
make_shared<int>(+c)... then the reference is bound to the temporary result of+cand not tocitself, therefore there is no odr-use. Similar theory to your posted workaround in the question.enum { c = 0 };is another possible workaround, if the type isintin the real code .