【问题标题】:Overload function template by return type按返回类型重载函数模板
【发布时间】:2018-03-11 17:02:30
【问题描述】:

我无意中发现以下两个模板可以重载(不要导致名称重定义错误),我认为这是违反直觉的。

template<typename T>
void func(T) {}

template<typename T>
int func(T) {return 0;}

来自cppreference.com,有一段相关的段落:

当表达式使用类型或非类型模板参数时 出现在函数参数列表或返回类型中,即 表达式仍然是函数模板签名的一部分 重载的目的:

但这两个函数的返回类型不包括T。谁能帮我解释一下?

【问题讨论】:

  • 现在尝试实际调用func(),而不会导致过载失败。
  • 模板其实就是宏定义;在扩展模板之前,编译器无法检测到模板中的大多数错误。尝试调用 func。

标签: c++ templates overloading


【解决方案1】:

您引用的段落无关紧要。

有一个特殊规则可以防止仅返回类型不同的非模板函数被重载(来自标准的[over.load]/2.1):

仅在返回类型、异常规范或两者方面不同的函数声明不能​​被重载。

因此,如果存在这样的声明(即使程序没有调用它们),那么程序就是非良构的。然而,这条规则既不适用于函数模板,也不适用于根据 [over.load]/1 为重载决议而合成的模板特化。

并非所有函数声明都可以重载。那些不能重载的都在这里指定。如果一个程序在同一范围内包含两个这样的不可重载声明,则该程序是格式错误的。 [ 注意:此限制适用于范围内的显式声明,以及此类声明和通过 using-declaration 进行的声明之间。它不适用于由于名称查找(例如,由于使用指令)或重载决议(例如,对于运算符函数)而制造的函数集。 — 尾注 ]

所以这两个模板可以很好地重载。

但是,正如 Dean Seo 在他的回答中所说,如果您尝试调用 func,由于重载解析的模糊性,该程序将是不正确的。

【讨论】:

    【解决方案2】:

    以下两个模板可以重载(不会导致名称重定义错误),我认为这是违反直觉的。

    不是真的。

    这两个函数不能重载,但是编译器直到它们被实例化的那一刻才知道它们的存在:

    // Try invoking `func`
    func(0xFF);
    

    现在编译器会抛出类似如下的错误信息:

    error: call to 'func' is ambiguous
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-07-29
      • 1970-01-01
      • 2014-09-06
      • 1970-01-01
      • 2012-06-21
      • 1970-01-01
      相关资源
      最近更新 更多