9
votes

There is plenty of information on when constructors of static members of ordinary classes are called. However, I am seeing some strange behavior with regard to template classes.

What should the output of the following program be? (Note I use printf to avoid any static initialization order fiasco complications with std::cout.)

#include <iostream>

class B {
public:
  B(const std::string &s) { printf("Hello I am B from %s\n", s.c_str()); }
};

template<typename T>
class Atempl {
public:
  static B b_;
};

class A {
public:
  static B b_;
};

template<typename T>
B Atempl<T>::b_("Atempl");
B A::b_("A");

class C : public Atempl<int> {
};

int main(int argc, const char *argv[]) {
  return 0;
}

I think the output should be:

Hello I am B from A
Hello I am B from Atempl

But with g++ 4.3 on FreeBSD 7.3 I get:

Hello I am B from A

If I add the line

template class Atempl<int>;

all is well and I get the expected output. The question is, why doesn't the declaration of class C count as an instantiation of the template Atempl and cause B's constructor to be called? Is this part of the standard or a bug in g++ 4.3?

3

3 Answers

10
votes

In a class template, when performing implicit instantiation, the members are instantiated on demand. Since the code does not use the static member, it is not even instantiated in the whole application.

When you do an explicit intantiation, the whole class and all of its members are instantiated, and that includes the static member variable, which is then initialized and you get your expected result.

Without the explicit instantiation you could do something like B* p = &Atempl<int>::b_; (or any other use of the static member) to trigger the instantiation.

3
votes

When a static member of a class template template is initialized is unspecified. In fact, unless you actuall use the static member, it should not be instantiated, and so never be initialized. If you explicitly instantiate the template, you force the instantiation of all of the members, which in turn forces the initialization (but I think exactly when it will be initialized is still unspecified).

0
votes

They are called by the C++ runtime sometime after the start of the process and before main() is called. There is no difference between 'regular' classes and class template instances. The order in which the constructors are called is undefined.