2009-11-27 7 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

Вы, кажется, есть проблема терминологии. Вы создаете шаблон класса для создания класса. Вы можете впоследствии создавать объекты этого типа. В приведенном примере вы хотите ** создать экземпляр ** 'myClass' ** дважды **, с аргументами A и B, но ** создать один ** объект. – MSalters

ответ

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

Проблема здесь в том, что «un-бокс» требуется для использования классов в варианте, который я предполагаю. – jkp

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>(); 
     // ... 
    } 
} 
Смежные вопросы