2014-10-23 2 views
0

Рассмотрим следующий список:C++ - Восстановление шаблона или отливать в шаблон

#include <iostream> 
#include <typeinfo> 

class Interface { }; 

template<typename T> 
class Class : public Interface { }; 

template<typename T> 
Interface *producer() { 
    std::cout << "produced " << typeid(T).name(); 
    return new Class<T>(); 
} 

template<typename T> 
void consumer(Class<T> *class_value) { 
    std::cout << "consumed " << typeid(T).name(); 
} 

void mediator(Interface *value) { 
    /* The magic happens here */ 
    consumer(class_value); 
} 

int main() { 
    Interface *value = producer<int>(); 
    mediator(value); 
} 

есть ли возможный способ назвать «потребителя» шаблонную функцию из функции «посредника»?

ответ

0

Прямой ответ

Похоже, что код, который вы опубликовали, был написан для незаконного использования броска, и добавление подходящего случая кажется прямым ответом.

void mediator(Interface *value) { 
    /* The magic happens here */ 
    Class<int> *class_value(static_cast<Class<int> *>(value)); 
    consumer(class_value); 
} 

В этом случае, так как известно, что только версия int прибудет мы можем использовать static_cast.

не масштабируется

Однако этот подход не очень хорошо масштабируется, если Class является специализированным для нескольких типов.

Например, чтобы иметь mediator ручку float, а вы должны попробовать каждый из типов:

void mediator(Interface *value) { 
    /* The magic happens here */ 

    { 
     Class<int> *class_value(dynamic_cast<Class<int> *>(value)); 
     if(class_value) { 
      consumer(class_value); 
      return; 
     } 
    } 

    { 
     Class<float> *class_value(dynamic_cast<Class<float> *>(value)); 
     if(class_value) { 
      consumer(class_value); 
      return; 
     } 
    } 
} 

Double диспетчерских

Изменение конструкции, как Kerrek SB предлагает использовать double dispatch дает гораздо более чистым и масштабируемым решением.

0

Вы можете использовать dynamic_cast:

consumer(dynamic_cast<producer<int>&>(value)); 
1

Если вы немного изменили дизайн, вы могли бы сделать производный класс сделать работу:

class Interface 
{ 
    virtual void consume() = 0; 
    virtual ~Interface() {} 
}; 

void mediator(Interface * value) 
{ 
    value->consume(); 
} 

template <typename T> 
void consumer(Class<T> * class_value) 
{ 
    std::cout << "consumed " << typeid(T).name(); 
} 

template <typename T> class Class : public Interface 
{ 
    virtual void consume() override 
    { 
     consumer<Class>(this); 
    } 
    // ... 
}; 
Смежные вопросы