我注意到用于区分唯一模板函数的签名与用于区分唯一函数(包括那些从模板函数实例化的函数)的签名之间存在不对称性.
特别是,仅由返回类型不同的模板函数被认为是唯一的,而仅由返回类型不同的函数被认为是冗余的.
因此,我有一个相应的问题,关于如何在实例化之间消除仅由返回类型不同的函数模板之间的歧义:
#include <iostream>
template<typename T>
long foo(T)
{
std::cout << "long" << std::endl;
return 0;
}
template<typename T>
char foo(T)
{
std::cout << "char" << std::endl;
return '\0';
}
int main()
{
double d = 0.0;
long n = foo(d); // <- Ambiguous: How to specify the template function to use?
}
Run Code Online (Sandbox Code Playgroud)
在上面的代码中,模板函数的实例化foo是模糊的,因为我刚才提到的不对称性.两个模板函数定义的存在是合法的,但实例化是非法的,即使返回类型在同一行代码中指定.
我纯粹是出于理论学习的目的而提出这个问题.也许这种代码构造在现实生活中会成为糟糕设计的标志.也许它永远不会出现在现实生活中.此外,我可以通过更改模板定义(或通过进行其他更改)来设想克服此问题的不同方法.
但是,我仍然想知道,如果保持模板定义不变,可以在实例化时消除这两个模板函数之间的歧义.
请注意,以下两个函数具有相同的类型和签名:
void foo1(int t) {} // foo1 has type 'void(*)(int)', and signature '(*)(int)'
void foo2(const int t) {} // Also type 'void(*)(int)', signature '(*)(int)'
Run Code Online (Sandbox Code Playgroud)
(const不属于函数类型或函数签名).类似地,返回类型上的修饰符(const或volatile)不会影响函数类型或函数签名.
但是,在函数定义本身(未显示)中,命名变量t确实保留了const限定条件foo2.
有许多StackOverflow问题讨论为什么函数的返回类型不被视为函数签名的一部分(用于重载解析).
但是,我找不到任何StackOverflow问题,询问为什么参数修饰符(const或volatile)不是函数类型或签名的一部分.另外,我直接查看了C++ 11标准文档,发现很难解开.
参数修饰符(即const和volatile)不是函数类型或签名的一部分这一事实背后的基本原理是什么?
附录为清楚起见,从下面R.MartinhoFernandes的答案,我要澄清,在C++(我认为)的参数调节剂const和volatile,如果他们只是忽略了作为函数类型/签名的一部分顶级改性剂-见下面这个问题的答案.
可能重复:
返回类型是函数签名的一部分吗?
关注一个相关但相切的问题(如何消除仅由返回类型不同的函数模板?),我想问一个与函数的返回类型不被认为是签名的一部分有关的问题一个功能.
请考虑以下代码:
#include <iostream>
int foo()
{
return 0;
}
int main()
{
long n = static_cast<long(&)()>(foo)(); // Error: incorrect return type
int p = static_cast<int(&)()>(foo)(); // Compiles just fine
}
Run Code Online (Sandbox Code Playgroud)
的代码行上面提到编译错误的结果,因为该返回功能类型的类型,其foo被强制转换不匹配返回功能的类型foo.
但我认为函数的返回类型在函数的签名中不起作用!
根据某种思路,由于函数签名long(&)()与签名匹配foo,foo对此类函数的强制转换应该成功.
但是,演员阵容没有成功.推理在哪里出错了?如果演员阵容因功能签名而无法失败,那么为什么演员阵容失败?