关于模板化类型和类层次结构的c ++函数重载决策

时间:2010-03-07 05:36:24

标签: c++ templates resolution class-hierarchy overloading

  

可能重复:
  Priority when choosing overloaded template functions in C++

模板化功能使我可以方便地操作各种类型:

template<typename T> void destroy(T* obj) {
    delete obj;
}

但是在某些时候我想对类层次结构进行一些专门化:

class Base { virtual void doSomething(); };
class Derived : public Base {};
void destroy(Base* obj) {
    obj->doSomething();
    delete obj;
}

如果我传递确切类型Base*,则调用了预期的专用函数,但是如果我传递{{1},则重载决策的规则似乎更喜欢通用模板化版本而不是执行静态向上转换} Derived*

当然,我可以为所有可能的派生类型创建所有重载函数,但它的可维护性较差。

我使用的是Visual C ++ 2008,有什么方法可以解决上述问题吗?

2 个答案:

答案 0 :(得分:5)

在所有条件相同的情况下,重载解析更喜欢非模板函数来运行模板。但是,在这种情况下,所有事情都不相同。要匹配Base*的重载,必须使用派生到基础的指针转换;不需要转换来匹配功能模板。因此,为Derived*选择了函数模板。

“简单”(虽然可能容易出错)解决方案是在调用函数之前将Derived*强制转换为Base*

至少在理论上你可以像Ben建议的那样采用SFINAE方法,但你必须明确禁用你提供特化的任何类型的泛型函数模板,否则你最终会出现过载模糊。与显式强制转换方法相比,这更难以维护且容易出错。 (虽然,这里有人可能知道另一种解决过载歧义的方法;我当然有兴趣知道是否有)。

答案 1 :(得分:0)

没有Visual C ++ 2009这样的东西。

您可以使用其他模板专门化您的功能,并使用SFINAE仅匹配Base的子类型。但我不知道编译器是否更喜欢第二个版本,通常专业化必须以某种方式“更好”才能被选中。

或者,您可以使用SFINAE和辅助特征类来防止通用版本匹配Base的子类。如果您需要这样的示例,请询问。

当然,您的专业化只会在可见的地方使用。模板化函数始终是内联的,它们和特化需要在调用者包含的头文件中。