2009-11-27 75 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>(); 
     // ... 
    } 
}