Follow

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use
Contact

Undefined reference to initialized static member variable with make_shared

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);
    }

};

MEDevel.com: Open-source for Healthcare and Education

Collecting and validating open-source software for healthcare, education, enterprise, development, medical imaging, medical records, and digital pathology.

Visit Medevel

>Solution :

Since C++17 the first code should work correctly: a static constexpr class member variable is implicitly inline which 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 :

template< class T, class... Args >
shared_ptr<T> make_shared( Args&&... args );

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 +c and not to c itself, 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 is int in the real code .

Add a comment

Leave a Reply

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use

Discover more from Dev solutions

Subscribe now to keep reading and get access to the full archive.

Continue reading