Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

C++ static variables of unreferenced class

In the following program "Here" is printed:

#include <iostream>
class Base
{
  static bool temp;
  static bool initTemp()
  {std::cout<<"Here\n";return true;}
};

bool Base::temp = Base::initTemp();

class Derived : public Base
{};

int main() {int a;std::cin>>a;}

In the following program "Here" is not printed:

#include <iostream>
template <class T>
class Base
{
  static bool temp;
  static bool initTemp()
  {std::cout<<"Here\n";return true;}
};

template <class T>
bool Base<T>::temp = Base<T>::initTemp();

class Derived : public Base<int>
{};

int main() {int a;std::cin>>a;}

In both cases Base is never referenced. The only difference is that in the second case it is a template class. Can anyone explain to me why this behavior occurs. I am using VS 2012.

like image 996
Benjy Kessler Avatar asked Jul 08 '13 14:07

Benjy Kessler


2 Answers

In both cases Base is never referenced.

And that is precisely the reason why you see nothing being printed to the standard output.

The definition of a class template's static data member does not get instantiated unless you use that data member; like member functions, the definitions of static data members of a class template are instantiated on demand.

This is specified in paragraph 14.7.1/1 of the C++11 Standard:

[...] The implicit instantiation of a class template specialization causes the implicit instantiation of the declarations, but not of the definitions or default arguments, of the class member functions, member classes, scoped member enumerations, static data members and member templates. [...]

Since your client code never refers to Base<>::temp, there is no need to construct and initialize it.


As a side note, this signature:

void main()

Is not valid (standard) C++. If you want to write portable code, the return type of main() should always be int.

like image 112
Andy Prowl Avatar answered Oct 17 '22 12:10

Andy Prowl


In the first case, you don't instantiate Base, but you do call the static function:

bool Base::temp = Base::initTemp();

In the second case, you never instantiate the template:

template <class T>
bool Base<T>::temp = Base<T>::initTemp();

You can explicitly instantiate the Base class template, as with:

template class Base<int>;

And then you will see "Here" printed.

like image 2
John Dibling Avatar answered Oct 17 '22 12:10

John Dibling