【问题标题】:c++ function overload resolution regarding templated type and class hierarchy [duplicate]关于模板类型和类层次结构的c ++函数重载解决方案[重复]
【发布时间】:2011-01-24 14:49:05
【问题描述】:

可能重复:
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*,则确实调用了预期的专用函数,但是如果我将Derived* 传递给@987654327,重载决议的规则似乎更喜欢通用模板版本而不是执行静态向上转换@。

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

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

【问题讨论】:

  • 刚刚在堆栈溢出中找到了相同问题的简洁答案:Priority when choosing overloaded template functions in C++
  • 但是你的销毁函数有问题。它也将被调用为一维数组类型,您可以执行“删除”而不是“删除 []”,这是未定义的行为。
  • Op 承认这个 Q 应该作为副本关闭。

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


【解决方案1】:

在所有条件相同的情况下,重载决议更喜欢非模板函数而不是函数模板。但是,在这种情况下,并非所有事物都是平等的。为了匹配Base* 的重载,需要进行派生到基址的指针转换;无需转换即可匹配功能模板。因此,函数模板被选择为Derived*

“简单”的解决方案是在调用函数之前将 Derived* 转换为 Base*

至少从理论上讲,您可以按照 Ben 的建议采用 SFINAE 方法,但您必须明确禁用您为其提供专门化的任何类型的通用函数模板,否则您最终会遇到重载歧义。这比显式转换方法更不可维护且更容易出错。 (不过,这里的某个人可能知道另一种解决过载歧义的方法;如果有的话,我当然很想知道)。

【讨论】:

    【解决方案2】:

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

    您可以使用另一个模板专门化您的函数,并使用 SFINAE 仅匹配 Base 的子类型。但我不知道编译器更喜欢第二个版本的任何原因,通常一个专业化必须以某种方式“更好”才能被选择。

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

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

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-05-21
      • 2012-10-25
      • 1970-01-01
      • 2010-09-09
      • 1970-01-01
      • 2011-06-22
      相关资源
      最近更新 更多