C ++ - 恢复模板或强制转换为模板

时间:2014-10-23 22:36:24

标签: c++ templates c++11

考虑以下代码清单:

#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);
}

有没有办法打电话给消费者&#39;来自“调解员”的模板功能&#39;功能

3 个答案:

答案 0 :(得分: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);
    }
    // ...
};

答案 1 :(得分:0)

您可以使用dynamic_cast

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

答案 2 :(得分: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;
        }
    }
}

双重发送

改变设计,因为Kerrek SB建议使用double dispatch提供更清晰,可扩展的解决方案。