在运行时有条件地实例化模板

4

我有一个模板类


template <class T> 
class myClass
{
    public:
        /* 函数 */
    private:
        typename T::Indices myIndices;  
};
</code> </pre>

<p>现在在我的主代码中,我想根据条件实例化模板类。例如:</p>

<pre><code>
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{}结束时失效。我无法在函数开头声明它,因为我事先不知道将实例化的类型。 我知道我正在尝试在编译时实现运行时操作(使用模板),但仍然想知道是否有更好的方法来解决这个问题。

你似乎有一个术语问题。你需要实例化一个类模板来创建一个类,然后可以创建该类型的对象。在给定的示例中,你想用参数A和B分别实例化myClass 两次,但只创建一个对象。 - MSalters
5个回答

7
创建一个基类
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技术;请参阅教程以了解如何使用它。


这里的问题在于我猜需要"拆箱"才能使用变量中的类。 - jkp

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

0

低技术解决方案。使用具有所需范围的普通指针。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接