Ziqi Liu
Ziqi Liu

Reputation: 3171

C++ what's the correct way to define static member

I'm trying to use a static member in a normal member function. But the compiler report some errors. Pls take a look at this code

#include <memory>

template<typename T>
class MyClass {
private:
  static std::allocator<T> alloc;
  T *p;
public:
  void assign(T e) {
    p = alloc.allocate(1);
    alloc.construct(p, e);
  }
};

and this is how I use it:

#include 'myclass.h'

int main() {
  MyClass<int> cls;
  cls.assign(4);

};

And the compiler give this error:

/Users/liuziqi/CLionProjects/cpplearning/src/tt.h:17:9: warning: instantiation of variable 'MyClass<int>::alloc' required here, but no definition is available [-Wundefined-var-template]
    p = alloc.allocate(1);
        ^
/Users/liuziqi/CLionProjects/cpplearning/src/main.cpp:49:7: note: in instantiation of member function 'MyClass<int>::assign' requested here
  cls.assign(4);
      ^
/Users/liuziqi/CLionProjects/cpplearning/src/tt.h:13:28: note: forward declaration of template entity is here
  static std::allocator<T> alloc;
                           ^
/Users/liuziqi/CLionProjects/cpplearning/src/tt.h:17:9: note: add an explicit instantiation declaration to suppress this warning if 'MyClass<int>::alloc' is explicitly instantiated in another translation unit
    p = alloc.allocate(1);

I can not figure out which part is wrong.....I have defined that static member and any member function should be able to use it. Is this error relevant to template? (I've just learned template and not sure If I use it correctly.)

Upvotes: 2

Views: 171

Answers (1)

xaxxon
xaxxon

Reputation: 19761

I'm going to take a shot at describing what the warning is referring to in addition to answering the "how to fix it" question (which certainly has been answered many times before)...

Because MyClass is a template, the compiler expects all the code for the templated class to be available in the same file (myclass.h). Since you only declare but do not define alloc in myclass.h, the compiler assumes you made a mistake. It's not absolutely required to be there (hence the warning and not error) and you could disable the warning if you define the variable elsewhere, but it's almost certainly just a mistake.

If you're using c++17, the easiest way to deal with this is to declare the static member as inline, so it will be defined right there:

  static inline std::allocator<T> alloc;

live: https://godbolt.org/g/cr1aUP

Prior to C++17, you would explicitly define the variable in myclass.h:

template<typename T>
std::allocator<T> MyClass<T>::alloc;

live: https://godbolt.org/g/2Znqst

Upvotes: 4

Related Questions