Search code examples
c++11atomic

can't use static std::atomic (and don't know how to initialize it)


I have the following code:

#include <cstdlib>
#include <cstdio>
#include <atomic>

enum ATYPE { Undefined = 0, typeA, typeB, typeC };

template<ATYPE TYPE = Undefined>
struct Object
{
    Object() { counter++; }
    static std::atomic<int> counter;
};

//template<ATYPE TYPE>
//std::atomic<int> Object<TYPE>::counter = 0;

template<ATYPE TYPE>
void test()
{
    printf("in test\n");
    Object<TYPE> o;
}

int main(int argc, char **argv)
{
    test<typeA>();
    printf("%d\n", Object<typeA>::counter.load());
    return 0;
}

and when I compile it with the following command line:

clang++ -o test -std=c++11 -stdlib=libc++ test.cpp

I got the following error:

Undefined symbols for architecture x86_64:
"Object<(ATYPE)1>::counter", referenced from:
_main in testray-D4iTOH.o
Object<(ATYPE)1>::Object() in testray-D4iTOH.o
ld: symbol(s) not found for architecture x86_64
clang: error: linker command failed with exit code 1 (use -v to see invocation)

I have no idea if what I am trying to do is technically possible. As the code hopefully shows, I am trying to create a static instance of the atomic class (BTW, I have no idea how to initialize this variable either. How do you intialize a static std::atomic<>?). What I am trying to do is count the number of instances of the class Object created while running the program, for each possible type (typeA, B, C, etc.). That's the mechanism I came up with but maybe (beside the problem I have which I would like to fix if possible) someone could advice a better solution? It would be much appreciated.

Thank you so much.


Solution

  • As pointed by Dave in the comment, the static variable needs to be declared somewhere:

    include

    #include <cstdio>
    #include <atomic>
    
    enum ATYPE { Undefined = 0, typeA, typeB, typeC };
    
    template<ATYPE TYPE = Undefined>
    struct Object
    {
        Object() { counter++; }
        static std::atomic<int> counter;
    };
    
    template<ATYPE TYPE>
    std::atomic<int> Object<TYPE>::counter(0);
    
    template<ATYPE TYPE>
    void test()
    {
        printf("in test\n");
        Object<TYPE> o;
    }
    
    int main(int argc, char **argv)
    {
        test<typeA>();
        printf("%d\n", Object<typeA>::counter.load());
        return 0;
    }
    

    It compiles fine.