特定接口的模板功能专用

时间:2010-09-18 22:15:59

标签: c++ templates

我有以下代码:

class ICookable
{
public:
    virtual void CookMe () = 0;
    virtual ~ICookable () {};
};

class Egg : public ICookable
{
public:
    virtual void CookMe () {cout << "Egg cooked!" << endl;}
};

template <class T>
void Cook (T&)
{
    cout << "Item Uncookable!" << endl;
}

template <>
void Cook (ICookable& c)
{
    c.CookMe ();
}

int _tmain(int argc, _TCHAR* argv[])
{
    Egg egg;
    Cook (egg);
    return 0;
}

我希望Cook函数的行为有所不同,具体取决于它的参数是否继承自ICookable接口。 但是在上面的例子中,我得到Egg参数的“Item Uncookable”消息,除非我手动写:

Cook<ICookable> (egg);

有没有办法让编译器自动为ICookable后代选择正确的实现?

1 个答案:

答案 0 :(得分:3)

通过boost::is_base_of编译时调度和类模板部分专业化:

template<class T, class _>
struct CookDetail {
  static void cook(T& obj) {
    cout << "uncookable\n";
  }
};
template<class T>
struct CookDetail<T, boost::true_type> {
  static void cook(ICookable& obj) {
    obj.CookMe();
  }
};

template<class T>
void cook(T& obj) {
  return CookDetail<T, boost::is_base_of<ICookable, T> >::cook(obj);
}

然而,做饭(non_icookable_obj)“工作”对我来说是个错误。我更喜欢尝试烹饪不可烹饪的编译时错误。

请注意,您尝试的操作失败,因为这就是功能解析的工作原理。通过模板(cook&lt; Egg&gt;(Egg&amp;))的精确匹配被认为优于需要转换的(cook(ICookable&amp;))。如果你想要神秘的技术细节,详情请见FCD