在C++中,返回类型是否被认为是函数签名的一部分?只修改了返回类型,不允许重载.
普通函数的签名中不包含返回类型.
(注意:我已经重写了这个答案,下面的评论不适用于此修订版 - 有关详细信息,请参阅编辑历史记录).
但是,标准中关于函数和函数声明的问题很复杂.必须考虑两个层次:
声明
实体
所谓的函数声明可以声明函数实体或模板实体.如果声明了一个函数实体,那么您要么必须使用函数模板的显式特化(指定所有参数),要么使用普通函数的声明.如果声明了模板实体,那么您将声明主函数模板,或者未指定某些参数的显式特化.(这与"对象声明"和对象或引用的关系非常相似:前者可以声明对象或引用.因此对象声明可能不一定声明对象!).
标准定义了函数的签名,包括以下内容1.3.10
:
它的参数类型,如果函数是类成员,则函数本身的cv限定符(如果有)和声明成员函数的类.函数模板特化的签名包括其模板参数的类型.(14.5.5.1)
它缺少此定义中的返回类型,它是函数模板特化的签名的一部分(即声明函数是模板特化的函数声明),如14.5.5.1
(最近的C++ 0x工作文件所指出)修复了那里已经提到的返回类型1.3.10
):
函数模板特化的签名包括函数模板的签名和实际模板参数的签名(无论是明确指定还是推导).
函数模板的签名由其函数签名,返回类型和模板参数列表组成.
所以,当我们询问函数的签名时,我们必须给出两个答案:
对于作为函数模板特化的函数,签名包括返回类型.
对于非特化的函数,返回类型不是签名的一部分.
但请注意,返回类型在任何情况下都是函数类型的重要部分.也就是说,以下内容无效:
void f(); int (*pf)() = &f; // different types!
主要编译器目前拒绝以下代码:
int f(); double f(); // invalid
但是接受以下代码:
templateint f(); template double f(); // invalid?
但是,标准确实禁止函数声明,该函数声明仅在返回类型中有所不同(定义何时重载有效,何时不是).但是,它没有准确定义"只有返回类型不同"的含义.
标准段落参考:
何时可以重载函数声明: 13.1
什么是函数声明:7/2
和7/5
功能模板/专业化的签名是什么: 14.5.5.1
作为参考,这里是最新的C++ 0x草案n3000关于"签名"的内容1.3.11
,它在不同类型的实体的覆盖范围内更为完整:
函数的名称和参数类型列表(8.3.5),以及它所属的类或命名空间.如果函数或函数模板是类成员,则其签名还包括函数或函数模板本身的cv-quali firs(如果有)和ref-quali fi er(如果有的话).函数模板的签名还包括其返回类型和模板参数列表.函数模板特化的签名包括作为特化的模板的签名及其模板参数(无论是明确指定还是推导).[注意:签名用作名称修改和链接的基础. - 结束说明]
这取决于函数是否是函数模板.
在C++模板 - 完整指南中,Jusuttis提供了与C++标准中给出的不同的定义,但具有相同的结果:
我们将函数的签名定义为以下信息:
函数的不合格名称
该名称的类或命名空间范围,如果名称具有内部链接,则为声明名称的转换单元
功能的const
,volatile
或const volatile
资格
函数参数的类型
如果函数是从函数模板生成的,则返回类型
的模板的参数和模板参数,如果函数是从一个函数模板生成
正如litb建议的那样,值得澄清为什么返回类型是模板函数签名的一部分.
如果程序具有不同的签名,则它们可以共存于程序中.
.也就是说,如果返回类型是模板参数:
templateT foo(int a) {return T();}
它可以实例化两个仅在返回类型上有所不同的函数:
foo(0); foo (0);
不仅如此:正如litb正确报告的那样,也可以重载两个模板函数,这些函数仅在返回类型上有所不同,即使返回类型不是依赖名称.这是他的例子:
templateint foo(T) {} template bool foo(T) {} // at the instantiation point it is necessary to specify the cast // in order not to face ambiguous overload ((int(*)(char))foo )('a');