2

I am trying to create a template class which contains a static list of objects which there is only one of. What i have so far works but it gives me a copy of "mylist" for each different type of class B parameter. How can i change it so that i get one "mylist" for all instantiations of class B regardless of template parameters?

This is what i have:

template <class T> class A {
    ...
};
template <class T> class B {
    static list<A<T> > mylist;
    ...
};
template <class T> list< A<T> > B<T>::mylist;

Thanks in advance :)

2
  • 7
    You're fundamentally misunderstanding templates. Given template<class T> class Foo;, each instance of Foo<T> for different Ts is a completely different type. Consequently, if Foo<> contains a static data member, each instance of Foo<T> for different Ts will contain a different static data member. To have one data member that can contain different types, look at Boost.Variant if all types are known beforehand, or Boost.Any otherwise. (But really, your design sounds highly questionable in the first place.) Commented Feb 2, 2012 at 21:48
  • Are you after a singleton? infernodevelopment.com/singleton-c Commented Feb 2, 2012 at 21:53

2 Answers 2

4

How can change it so that i have only ONE copy

You can inherit from a common (non-templated) base class to ensure that there isn't an instance for every template instantiation.

... that contains any type?

That depends on your expectations. I'm going to assume from your example that "any type" means "any instantiation of template class A".

Since those types could vary in size, you'll do best with holding pointers to the objects.

This is one example of a solution that would solve both those problems.

class ACommon {
    // Put a common virtual interface here.
};

template <class T> class A : public ACommon {
};

class BCommon {
    // You'll have a single, common static here.

    static list<shared_ptr<ACommon> > mylist;
};

template <class T> class B : public BCommon{

};
Sign up to request clarification or add additional context in comments.

Comments

1

You can not "just" have ANY type in a list, living side by side. Depending on what you expect to do with that list, and the objects in it, there are several things to do.

An alternative to Drew's solution would be: You definitely need BCommon if you want a single list for all instantiations. If you don't want to hide your A types behind an interface, you could use Boost::any or Boost::variant to hold your A objects.

2 Comments

Yes, boost::any and boost::variant would be great use cases here. Nice.
´boost::variant´ is a bit dangerous at the hands of a novice though; since it's a union, it assumes the size of the largest type. A novice, without noticing, could waste a lot of memory, just to store one big object next to a million ´int´s. ´boost::any´ is a different story. Although it won't cause undefined behaviour due to a wrong cast (like a void *), it could make your program crash "in the field" due to an unhandled ´bad_cast_exception´. IMHO, for %90 of the cases, your solution is the way to go.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.