如何在成员模板函数中选择不同类型的代码路径

时间:2013-03-19 08:23:12

标签: c++ templates

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

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,则打印世界。此外,这些是唯一可以创建设备的两种类型。

我该怎么做?

4 个答案:

答案 0 :(得分:4)

你有两种经典的可能性。

首先,使用两个全局函数重载,一个用于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(); 
}

使用traits类的优点是您不必使用多个函数破坏全局命名空间。

关于部分地专门化Device类本身 - 它并不总是可行的,并且将任何特定于模板参数的代码移动到traits类中被认为更方便。

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

答案 1 :(得分:3)

您可以明确地实例化模板:

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

Device<ComponentIc>同样如此。

此外,如果要将模板参数限制为特定集,则应考虑继承或组合而不是模板。

答案 2 :(得分:1)

您也可以使用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)
{
}

答案 3 :(得分:0)