我有以下代码:
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后代选择正确的实现?
答案 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。