有全局功能(仅举例):
void func( int i )
{
std::cout << i + 100 << std::endl;
}
我假设用char参数调用这个函数没有任何意义所以我使用delete:
void func(char) = delete;
所以我希望以下呼叫应该是可能的:
func(1);
func(3.1);
func(true);
用char参数调用应该是forbiden:
func('a');
但事实并非如此。致电func('a')
时,我得到了预期的结果:
error: use of deleted function ‘void func(char)’
但在致电func(2.3)
期间,我得到了:
error: call of overloaded ‘func(double)’ is ambiguous
为什么会出现此错误?没有删除带有char参数的函数,double被转换为int并调用了func(int),为什么现在它被禁止?
答案 0 :(得分:12)
致电时
func(2.3)
您将double
传递给该函数。候选人列表包含 func(int)
和func(char)
,因为重载解决方案发生before delete
kicks in:
如果函数重载,首先会发生重载决策,如果选择了删除的函数,程序只会格式错误 Ref:cppreference.com,请参阅{{3} }用于精确的标准报价。
现在double
可以转换为char
和int
,因此含糊不清。
没有删除带有char参数的函数,double被转换为int并调用了func(int),为什么现在它被禁止?
即使没有delete
char
版本,您也会收到歧义错误,请参阅直播Avishai's answer。当然,如果您只定义func(int)
,那么就不会有歧义,因此double
很乐意转换为int
。
答案 1 :(得分:1)
每次为函数参数传入非完全匹配时,都必须进行转换。当您有两个函数时,无论是否删除了一个函数,它们仍然参与重载解析。编译器选择最佳匹配,然后生成对它的调用,或者如果函数不可访问或删除则失败。
为了使重载分辨率起作用,它会使一组候选函数看到哪个具有到参数集的最短转换路径。就规则而言,所有内置数字类型都是“相等”的转换。因此,如果你使用2.5调用,这是一个double,它必须转换并且可以转换为char或者转换为具有相同排名的int,因此调用是不明确的。
答案 2 :(得分:0)
它仍然不明确,因为编译器在检查已删除的函数之前尝试解决重载。参见:
§8.4.3删除定义
除了声明它之外,隐式或显式引用已删除函数的程序是不正确的。 [ 注意: 这包括隐式或显式调用函数并形成指向成员的指针或指针 到功能。它甚至适用于未进行潜在评估的表达式中的引用。如果一个功能 重载,只有在通过重载决策选择函数时才会引用它。 - 结束说明 ]
§13.3.3.1隐式转换序列:
隐式转换序列仅涉及类型,cv资格和值类别 参数以及如何转换它们以匹配参数的相应属性。其他 属性,例如生命周期,存储类,对齐方式,参数的可访问性,是否参数 是一个位字段,是否删除了一个函数(8.4.3),将被忽略。所以,虽然是隐式转换 可以为给定的参数 - 参数对定义序列,从参数到参数的转换 在最终分析中,参数可能仍然不正确。