Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Using static variable along with templates

I have a template class defined in a header file like this. Here I have defined a static variable as well:

#ifndef TEST1_H_
#define TEST1_H_

void f1();

static int count;

template <class T>
class MyClass
{
public:

    void f()
    {
        ++count;
    }


};

#endif

And I have defined main() function in a different cpp file like this:

int main(int argc, char* argv[])
{
    MyClass<int> a;
    a.f();
    f1();

    cout<<"Main:" << count << "\n";

    return 0;
}

I have implemented function f1() in a different cpp file like this:

void f1()
{
    MyClass<int> a;
    a.f();

    cout<<"F1: " <<count <<"\n";
}

When I compiled this using VC6, I got the output as "F1:0 Main:2". How is this possible? Also, in general how should I handle if I want to use static variables along with templates?

like image 716
Naveen Avatar asked Mar 03 '09 17:03

Naveen


People also ask

How do you define a static variable for a template class?

Each instantiation of function template has its own copy of local static variables. For example, in the following program there are two instances: void fun(int ) and void fun(double ). So two copies of static variable i exist. Each instantiation of class template has its own copy of member static variables.

What happens when there is a static member in template?

Each class template instantiation has its own copy of any static data members. The static declaration can be of template argument type or of any defined type. The statement template T K::x defines the static member of class K , while the statement in the main() function assigns a value to the data member for K <int> .

Why static variable should not be used?

Static variables are generally considered bad because they represent global state and are therefore much more difficult to reason about. In particular, they break the assumptions of object-oriented programming.

Can we use static variable in another file?

Static variables in C have the following two properties: They cannot be accessed from any other file. Thus, prefixes “ extern ” and “ static ” cannot be used in the same declaration. They maintain their value throughout the execution of the program independently of the scope in which they are defined.


1 Answers

You're getting two copies of the same variable because you've declared a static variable in a header file. When you declare a global variable static this way, you're saying it's local to the compilation unit (the .o file). Since you include the header in two compilation units, you get two copies of count.

I think what you really want here is a static template member variable associated with each instance of the template class. It would look like this:

template <class T>
class MyClass
{
    // static member declaration
    static int count;
    ...
};

// static member definition
template<class T> int MyClass<T>::count = 0;

This will get you a count for each instantiation of your template. That is, you'll have a count for MyClass<int>, MyClass<foo>, MyClass<bar>, etc. f1() would now look like this:

void f1() {
    MyClass<int> a;
    a.f();

    cout<<"F1: " << MyClass<int>::count <<"\n";
}

If you want a count for all instantiations of MyClass (regardless of their template parameters), you do need to use a global variable.

However, you probably don't want a global variable directly because you run the risk of using it before it gets initialized. You can get around this by making a global static method that returns a reference to your count:

int& my_count() {
    static int count = 0;
    return count;
}

Then accessing it from within your class like this:

void f() {
    ++my_count();
}

This will ensure that count gets initialized before it's used, regardless of which compilation unit you access it from. See the C++ FAQ on static initialization order for more details.

like image 124
Todd Gamblin Avatar answered Nov 06 '22 05:11

Todd Gamblin