Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Static field initialization in template class in C++

I'm trying to create some self-registering classes in C++. So I tried the solution similar to the one provided here. While doing this I stumble over something strange.

Here's the code:

#include <iostream>

class StaticClassType {
public:
  StaticClassType() {
    // Notify when the static member is created
    std::cout << "We're in." << std::endl;
  }
};


template<typename T>
class TestClass1 {
public:
  TestClass1() { &m; }
private:
  // Static member in a template class
  static StaticClassType m;
};

template<typename T>
StaticClassType TestClass1<T>::m;


class TestClass2 : public TestClass1<TestClass2> {
public:
  TestClass2() { } // required; why?
};


int main() {
  return 0;
}

This code create the static member variable TestClass1::m on startup (thereby printing "We're in." to the console) - i.e. before main() is started. However, the code only works if I write a (empty) constructor for TestClass2 (as shown in the example).

Why do I need to write this constructor? Why doesn't the default constructor generated by the compiler does the same thing?

This problem only occurs for template classes. If TestClass1 wasn't a template class, the code would work without writing the empty constructor for TestClass2.

like image 484
Sebastian Krysmanski Avatar asked Nov 04 '22 06:11

Sebastian Krysmanski


1 Answers

I created even smaller example (without constructors, which are not needed) :

#include <iostream>

class StaticClassType {
public:
  StaticClassType(int v) {
    // Notify when the static member is created
    std::cout << "We're in."<<v << std::endl;
  }
};


template<typename T>
class TestClass1 {
protected:
  // Static member in a template class
  static StaticClassType m;
};

template<typename T>
StaticClassType TestClass1<T>::m = StaticClassType(3);


class TestClass2 : public TestClass1<TestClass2> {
public:
    void foo()
    {
        (void)m;
    }
};

int main() {
  std::cout << "main" << std::endl;
}

take a note that foo() method is needed, otherwise the compiler removes the static variable, since it's not used anywhere.

like image 110
BЈовић Avatar answered Nov 09 '22 16:11

BЈовић