我不小心发现以下两个模板可以重载(不会招致名称重新定义错误),我认为这是违反直觉的。
template<typename T>
void func(T) {}
template<typename T>
int func(T) {return 0;}
来自cppreference.com,有一个相关的段落:
当表达式使用类型或非类型模板参数时 出现在函数参数列表或返回类型中 表达式仍然是函数模板签名的一部分 重载的目的:
但这两个函数的返回类型不包括T
。谁能为我解释一下?
答案 0 :(得分:1)
引用的段落无关紧要。
有一个特殊规则可以防止仅在返回类型上有所不同的非模板函数被重载(来自标准[over.load] /2.1):
只能在返回类型,异常规范或两者上有所不同的函数声明不能重载。
如果存在这样的声明(即使程序没有调用它们),程序也是不正确的。但是,此规则既不适用于函数模板,也不适用于根据[over.load] / 1为重载解析而合成的模板特化。
并非所有函数声明都可以重载。这里指定了那些不能重载的东西。如果程序在同一范围内包含两个这样的不可重载声明,则该程序格式不正确。 [注意:此限制适用于范围中的显式声明,以及通过using声明进行的此类声明和声明之间的声明。它不适用于由于名称查找(例如,由于使用指令)或过载分辨率(例如,对于操作员功能)而制造的功能集。 - 结束说明]
所以这两个模板可以很好地重载。
然而,正如Dean Seo在他的回答中所说,如果你试着打电话func
,由于重载决议的模糊性,该程序将会形成错误。
答案 1 :(得分:0)
以下两个模板可以重载(不会导致名称重新定义错误),我认为这是违反直觉的。
不是真的。
这两个函数不能重载,但编译器只是在实例化它们的那一刻才知道它们的存在:
// Try invoking `func`
func(0xFF);
现在编译器将抛出类似于:
的错误消息error: call to 'func' is ambiguous