Reputation: 63
I am hoping to design a template class that has a unique number across all types, some thing like following. I wonder if it is possible or what would be the recommended design?
template<typename T> class MyClass
{
public:
static int counter; // a unique counter shared by all instantiations (e.g float, double, int, etc)
void increment() { counter++; }
MyClass(T x) : val(x) {;}
T val;
void operations() { /* other operations on val */; }
};
Upvotes: 1
Views: 92
Reputation: 1687
Actually the different types you instantiate will have different initial value set for counter
. Asking this question is as good as asking If i have multiple non templatized classes and i want to share an unique variable with all of them then how would i achieve it? .
Ways could be :
1. To define a global variable accesible to all classes. Often it is better to avoid global variables.
2. Create a Parent class and have your templatized class defined inside this parent class (though you wont be able to access the counter variable directly but by Parent::counter
but here you are atleast avoiding global vars)
3. Inheritance of templatized class from the parent class and having your counter as a part of Parent class.
Upvotes: 0
Reputation: 27538
template<typename T> class MyClass { public: static int counter; // a unique counter shared by all instantiations
Not quite. Every instantiation of MyClass
will have a different counter
.
I wonder if it is possible or what would be the recommended design?
The recommended design depends on what kind of problem you actually want to solve.
Technically, an easy and clear way to achieve the desired result would be putting the variable into a base class:
#include <iostream>
class MyClassBase
{
public:
static int counter; // a unique counter shared by all instantiations (e.g float, double, int, etc)
};
int MyClassBase::counter = 0;
template<typename T> class MyClass : public MyClassBase
{
public:
void increment() { counter++; }
MyClass(T x) : val(x) {}
T val;
void operations() { /* other operations on val */; }
};
int main()
{
MyClass<float> o1(0);
MyClass<double> o2(0);
MyClass<int> o3(0);
o1.increment();
std::cout << o2.counter << "\n";
std::cout << o3.counter << "\n";
}
Output:
1
1
In real code, you will likely want to make counter
a protected
member and use private
inheritance instead of exposing both the base class and the variable to the whole world.
Upvotes: 2
Reputation: 25
This isn't the worst implementation of a serial id for a template class. As Duck said, it could come back to haunt you though if you output and input back. You need to have more than one state in it, like a typeref id along with your serial id to properly implement this. It is a pretty good idea. I think you're doing well and you programming is better schooled than a lot of coders out there whom are just beginning. This kind of practice should be good for a newcomer to programming to have in his portfolio for an interviewer to see. Don't give up. The typeref id is all you need now.
Upvotes: 0