C++ 按返回类型重载函数模板

C++ 按返回类型重载函数模板,c++,templates,overloading,C++,Templates,Overloading,我无意中发现以下两个模板可能会过载(不要引起名称重定义错误),我认为这是违反直觉的 template<typename T> void func(T) {} template<typename T> int func(T) {return 0;} 模板 void func(T){} 模板 int func(T){返回0;} 在cppreference.com上,有一个相关段落: 当使用类型或非类型模板参数的表达式 出现在函数参数列表或返回类型中 表达式仍然是函数的函

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

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

template<typename T>
int func(T) {return 0;}
模板
void func(T){}
模板
int func(T){返回0;}
在cppreference.com上,有一个相关段落:

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

但是这两个函数的返回类型不包括
t
。谁能为我解释一下

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

不是真的

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

// Try invoking `func`
func(0xFF);
现在,编译器将抛出类似以下内容的错误消息:

error: call to 'func' is ambiguous

你引用的段落无关紧要

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

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

因此,如果存在这样的声明(即使程序不调用它们),那么程序的格式是错误的。但是,此规则既不适用于函数模板,也不适用于根据[over.load]/1为重载解析目的而合成的模板专门化

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

因此,这两个模板可以很好地重载


然而,正如Dean Seo在他的回答中所说,如果您试图调用
func
,由于重载解析的模糊性,程序将是格式错误的。

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