Conditionally create a template instance at run time

I have a template class

template <class T> class myClass { public: /* functions */ private: typename T::Indices myIndices; }; 

Now in my main code I want to instantiate a template class depending on the condition. For instance:

 myFunc( int operation) { switch (operation) { case 0: // Instantiate myClass with <A> auto_ptr < myClass <A> > ptr = new myClass<A> (); case 1: // Instantiate myClass with <B> auto_ptr < myClass <B> > ptr = new myClass<B> (); case 2: // Instantiate myClass with <C> .... } // Use ptr here.. } 

Now the problem with this approach is that auto_ptr<> will die at the end of switch{} . And I can not declare it at the beginning of the function, because I do not know the type that will be created earlier.

I know that at compile time (using a template) I try to reach the runtime, but still wanted to know if there is a way to do this better.

+4
source share
5 answers

Create a base class

 class Base { protected: virtual ~Base() {} //... functions }; template <class T> class myClass : Base { //... }; myFunc( int operation){ shared_ptr < Base > ptr; switch (operation) { case 0: // Instantiate myClass with <A> ptr.reset ( new myClass<A> () ); case 1: // Instantiate myClass with <B> ptr.reset ( new myClass<B> () ) ; case 2: // Instantiate myClass with <C> .... } // Use ptr here.. } 
+6
source

You can enter a common myClass base and use it as an auto_ptr parameter. Just remember to declare that the common base destructor is virtual.

+4
source

Boost.Variant should do the trick.

 myFunc( int operation) { boost::variant< myclass<A>, myclass<B> > obj; switch (operation) { case 0: // Instantiate myClass with <A> obj = myClass<A> (); case 1: // Instantiate myClass with <B> obj = myClass<B> (); case 2: // Instantiate myClass with <C> .... } // Use object here.. } 

Using an object is a bit different because the type is dynamically determined. The apply_visitor technique is definitely the way to go; see tutorial for use.

+2
source

You can add a level of indirection to get what you want. You can avoid the base class using virtual methods and perform any other special actions.

For instance:

 template <class T> class MyClass { public: /* functions */ private: typename T::Indices myIndices; }; template<typename T> static void doit() { MyClass<T> t; // Use t here. } void myfunc(int op) { switch (op) { case 0: return doit<A>(); case 1: return doit<B>(); // ... } } 
+1
source

low tech solution. use a regular pointer with the desired area.

0
source

All Articles