【问题标题】:how to select a code path for different type in a member template function如何在成员模板函数中选择不同类型的代码路径
【发布时间】:2013-03-19 08:23:12
【问题描述】:

我有一个基于运行时返回特定设备的类。

struct ComponentDc;
struct ComponentIc;

typedef Device<ComponentDc> DevComponentDc;
typedef Device<ComponentIc> DevComponentIc;

template<class Component>
class Device{
 Device<Component>* getDevice() { return this; }
 void exec() { }
};

exec(),如果组件类型是ComponentDc,我想打印“Hello”,如果是ComponentIc,我想打印world。此外,只有这两种类型可以用来创建 Device。

我该怎么做?

【问题讨论】:

    标签: c++ templates


    【解决方案1】:

    你有两种经典的可能性。

    首先,使用两个全局函数重载,一个用于ComponentDc,一个用于ComponentIc

    void globalExec(ComponentDc) { std::cout << "Hello"; }
    void globalExec(ComponentIc) { std::cout << "World"; }
    
    void Device<Component>::exec() { globalExec(Component); }
    

    其次,使用 traits-class:纯模板类,没有字段,有不同的 typedef,只有静态函数作为方法。这个类对不同的可能参数类型有自己的特化。

    template<Component> class DeviceTraits {};
    
    template<> class DeviceTraits<ComponentDc> { 
        static std::string getMessage() { return "Hello"; }
    };
    
    template<> class DeviceTraits<ComponentIc> { 
        static std::string getMessage() { return "World"; }
    };
    
    void Device<Component>::exec() { 
        std::cout << DeviceTraits<Component>::getMessage(); 
    }
    

    使用特质类的好处是你不必用几个函数破坏你的全局命名空间。

    关于部分特化 Device 类本身 - 这并不总是可能的,将任何特定于模板参数的代码移动到特征类中被认为更方便。

    这是 STL 中使用的经典方法。或者,您可以使用boost::enable_ifstd::enable_if(适用于最新的编译器)。

    【讨论】:

    • 恐怕全局函数不是一个选项。我在这里简化了我的问题,所以它必须是会员。你能详细说明特征类吗?谢谢
    【解决方案2】:

    您可以显式实例化模板:

    template<> class Device<ComponentDc> {
        ...
        void exec() { cout << "Hello"; }
    };
    

    Device&lt;ComponentIc&gt; 也是如此。

    另外,如果您想将模板参数限制为特定的集合,您应该考虑继承或组合而不是模板。

    【讨论】:

    • 这个怎么称呼?
    • 和之前一样,DevComponentDc dc; dc.exec();编译器会根据模板参数隐式生成特定的代码。
    【解决方案3】:

    你也可以使用 boost::enable_if

    http://www.boost.org/doc/libs/1_53_0/libs/utility/enable_if.html http://www.boost.org/doc/libs/1_44_0/libs/type_traits/doc/html/boost_typetraits/reference/is_same.html

    void Device<Component>::exec(boost::enable_if< boost::is_same<Component,ComponentDc> >* enabler = 0)
    {
    }
    
    void Device<Component>::exec(boost::enable_if< boost::is_same<Component,ComponentIc> >* enabler = 0)
    {
    }
    

    【讨论】:

    • 是的,当然,你是对的!我总是尝试一下,然后就被它咬了。
    【解决方案4】:
    猜你喜欢
    • 2017-11-03
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-09-11
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多