2009-11-27 81 views
4

有条件实例化一个模板,我有一个模板类在运行时


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

现在我主要的代码,我要实例根据条件的模板类。像:


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.. 
} 

现在,这种方法的问题是,auto_ptr<>将在switch{}末死亡。 而且我不能在函数的开始处声明它,因为我不知道将会事先实例化的类型。

我知道我试图在编译时(使用模板)实现运行时的事情,但仍然想知道是否有一些更好的方法来做到这一点。

+0

你似乎有一个术语问题。您_instantiate_类模板来创建一个类。随后可以创建该类型的对象。在给出的例子中,你希望**实例化** myClass ** **两次**,使用参数A和B,但是**创建一个**对象。 – MSalters 2009-11-27 11:45:04

回答

6

创建一个基类

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.. 
} 
4

您可以将一个通用基底引入myClass,并将其用作auto_ptr的参数。只要不要忘记声明这个通用基础的析构函数是虚拟的。

2

Boost.Variant应该做的伎俩。

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.. 
} 

使用该对象有点不同,因为类型是动态确定的。 apply_visitor技术绝对是您的选择。请参阅tutorial了解如何使用它。

+0

这里的问题是使用我猜想的变体中的类所需的“取消装箱”。 – jkp 2009-11-27 08:35:31

0

低技术的解决方案。在你想要的范围内使用常规指针。

1

您可以添加一个间接级别来获得你想要的。你可以通过虚拟方法避免一个基类并做其他特殊的事情。

例如:

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>(); 
     // ... 
    } 
}