返回类型是函数签名的一部分吗?
在 C++ 中,返回类型是否被视为函数签名的一部分?不允许重载,只修改返回类型.
解决方案普通函数的签名中不包括返回类型.
(注意:我已经重写了这个答案,下面的评论不适用于这次修订――详情请参见编辑历史).>
简介
然而,标准中关于函数和函数声明的问题很复杂.有两层必须考虑:
- 声明
- 实体
所谓的函数声明可以声明一个函数实体或一个模板实体.如果声明了一个函数实体,那么您要么必须对函数模板(指定所有参数)进行显式特化,要么必须声明一个普通函数.如果声明了模板实体,则您声明的是主函数模板,或未指定某些参数的显式特化.(这与对象声明"和对象或引用的关系非常相似:前者可以声明一个对象或一个引用.因此对象声明不一定声明一个对象!).
标准在1.3.10
中定义了一个函数的签名,包括以下内容:
其参数的类型,如果函数是类成员,函数本身和声明成员函数的类的 cv- 限定符(如果有).函数模板特化的签名包括其模板参数的类型.(14.5.5.1)
它在这个定义中缺少返回类型,它是函数模板特化签名的一部分(即声明一个函数是模板特化的函数声明),如所指出的14.5.5.1
(最近的 C++0x 工作文件修复了这个问题,也提到了 1.3.10
中的返回类型):
函数模板特化的签名由函数模板的签名和实际的模板参数(无论是明确指定的还是推导的)组成.
函数模板的签名由函数签名、返回类型和模板参数列表组成.
那么签名到底包含什么?
因此,当我们询问函数的签名时,我们必须给出两个答案:
- 对于函数模板的特化函数,签名包括返回类型.
- 对于非特化函数,返回类型不是签名的一部分.
但是请注意,无论如何,返回类型是函数类型的重要组成部分.也就是说,以下内容无效:
void f();int (*pf)() = &f;//不同种类!
如果只有返回类型不同,重载何时无效?
主要编译器目前拒绝以下代码:
int f();双 f();//无效的
但接受以下代码:
templateint f();模板双 f();//无效的?
然而,标准确实禁止只在返回类型上不同的函数声明(定义重载何时有效,何时无效).它没有准确定义仅因返回类型而不同"的内容.意思是,不过.
标准段落引用:
- 何时可以重载函数声明:
13.1
- 什么是函数声明:
7/2
和7/5
- 函数模板/特化的签名是什么:
14.5.5.1
作为参考,这里是最新的 C++0x 草案 n3000 关于签名"的说明.在 1.3.11
中,它对不同类型实体的覆盖要完整得多:
函数的名称和参数类型列表 (8.3.5),以及它所属的类或命名空间.如果函数或函数模板是类成员,则其签名还包括函数或函数模板本身的 cv 限定符(如果有)和 ref 限定符(如果有).函数模板的签名还包括其返回类型和模板参数列表.函数模板特化的签名包括其特化的模板的签名及其模板参数(无论是显式指定还是推导).[ 注意:签名用作名称修改和链接的基础.― 尾注 ]
In C++, is the return type considered part of the function signature? and no overloading is allowed with just return type modified.
解决方案Normal functions do not include the return type in their signature.
(note: i've rewritten this answer, and the comments below don't apply to this revision - see the edit-history for details).
Introduction
However, the matter about functions and function declarations in the Standard is complicated. There are two layers that have to be considered:
- Declarations
- Entities
The so-called function declaration may declare a function entity or a template entity. If a function entity is declared, then you either have to do with an explicit specialization of a function template (with all arguments specified), or a declaration of an ordinary function. If a template entity is declared, then you are declaring a primary function template, or an explicit specialization where some arguments are not specified. (This is very similar to the relation of "object declaration" and objects or references: The former may declare either an object or a reference. So an object declaration may not necessarily declare an object!).
The Standard defines the signature of a function to include the following at 1.3.10
:
The types of its parameters and, if the function is a class member, the cv- qualifiers (if any) on the function itself and the class in which the member function is declared. The signature of a function template specialization includes the types of its template arguments. (14.5.5.1)
It's missing the return type in this definition, which is part of the signature of a function template specialization (i.e a function declaration that declares a function which is a specialization of a template), as pointed out by 14.5.5.1
(recent C++0x working papers fixed that already to mention the return type in 1.3.10
too):
The signature of a function template specialization consists of the signature of the function template and of the actual template arguments (whether explicitly specified or deduced).
The signature of a function template consists of its function signature, its return type and its template parameter list.
So what exactly does a signature contain, again?
So, when we ask about the signature of a function, we have to give two answers:
- For functions that are specializations of function templates, the signature includes the return type.
- For functions that are not specializations, the return type is not part of the signature.
Notice, however, that the return type, in any case, is a significant part of the type of a function. That is, the following is not valid:
void f();
int (*pf)() = &f; // different types!
When is an overload invalid if only the return type differs?
Major compilers currently reject the following code:
int f();
double f(); // invalid
But accept the following code:
template<typename T> int f();
template<typename T> double f(); // invalid?
However, the Standard does forbid a function declaration that only differs in the return type (when defining when an overload is valid, and when not). It does not define precisely what "differs only by return type" means, though.
Standard paragraph references:
- When can a function declaration be overloaded:
13.1
- What is a function declaration:
7/2
and7/5
- What is the signature of a function template/specialization:
14.5.5.1
For reference, here is what the most recent C++0x draft n3000 says about "signature" in 1.3.11
, which is much more complete in its coverage of the different type of entities:
the name and the parameter type list (8.3.5) of a function, as well as the class or namespace of which it is a member. If a function or function template is a class member its signature additionally includes the cv-quali?ers (if any) and the ref-quali?er (if any) on the function or function template itself. The signature of a function template additionally includes its return type and its template parameter list. The signature of a function template specialization includes the signature of the template of which it is a specialization and its template arguments (whether explicitly speci?ed or deduced). [ Note: Signatures are used as a basis for name mangling and linking. ― end note ]
相关文章