c++ - 为什么用整数文字调用重载的 ambig(long) 和 ambig(unsigned long) 会产生歧义?

标签 c++ visual-c++ ambiguity

编译时

void ambig(  signed long) { }
void ambig(unsigned long) { }

int main(void) { ambig(-1); return 0; }

我明白了

error C2668: 'ambig' : ambiguous call to overloaded function
    could be 'void ambig(unsigned long)'
    or 'void ambig(long)'
while trying to match the argument list '(int)'

我知道我可以通过说 -1L 而不是 -1 来“修复”它,但是为什么/为什么这首先被认为是模棱两可的?

最佳答案

您正在将 int 传递给这个重载函数。

虽然人类的直觉认为 ambig(signed long) 应该是首选,因为您的输入是一个负整数(不能用 unsigned long 表示) ,这两个转换在 C++ 中的“优先级”实际上是等价的。

也就是说,转换 intunsigned long 被认为与 intsigned long 一样有效code>,两者都不如对方好。

另一方面,如果您的参数已经是 long 而不是 int,则 完全匹配 signed long,无需转换。 This avoids the ambiguity .

void ambig(  signed long) { }
void ambig(unsigned long) { }

int main(void) { ambig(static_cast<long>(-1)); return 0; }

“只是其中之一”。


[C++11: 4.13/1]: ("Integer conversion rank")

Every integer type has an integer conversion rank defined as follows:

  • [..]
  • The rank of a signed integer type shall be greater than the rank of any signed integer type with a smaller size.
  • The rank of long long int shall be greater than the rank of long int, which shall be greater than the rank of int, which shall be greater than the rank of short int, which shall be greater than the rank of signed char.
  • The rank of any unsigned integer type shall equal the rank of the corresponding signed integer type.
  • [..]

[ Note: The integer conversion rank is used in the definition of the integral promotions (4.5) and the usual arithmetic conversions (Clause 5). —end note ]

重载决议很复杂,定义在[C++11: 13.3];我不会在这里引用其中的大部分内容来让您感到厌烦。

不过这里有一个亮点:

[C++11: 13.3.3.1/8]: If no conversions are required to match an argument to a parameter type, the implicit conversion sequence is the standard conversion sequence consisting of the identity conversion (13.3.3.1.1).

[C++11: 13.3.3.1/9]: If no sequence of conversions can be found to convert an argument to a parameter type or the conversion is otherwise ill-formed, an implicit conversion sequence cannot be formed.

[C++11: 13.3.3.1/10]: If several different sequences of conversions exist that each convert the argument to the parameter type, the implicit conversion sequence associated with the parameter is defined to be the unique conversion sequence designated the ambiguous conversion sequence. For the purpose of ranking implicit conversion sequences as described in 13.3.3.2, the ambiguous conversion sequence is treated as a user-defined sequence that is indistinguishable from any other user-defined conversion sequence134. If a function that uses the ambiguous conversion sequence is selected as the best viable function, the call will be ill-formed because the conversion of one of the arguments in the call is ambiguous.

  • /10 是您遇到的情况; /8 是您使用 long 参数的情况。

关于c++ - 为什么用整数文字调用重载的 ambig(long) 和 ambig(unsigned long) 会产生歧义?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/31935189/

相关文章:

c++ - pcl_visualizer.cpp 与 2015 构建错误

c++ - 模板函数特化的单独声明和定义 : different behaviour for member and nonmember functions

c# - 以下方法或属性之间的调用不明确 : 'EntitiesLan.EntitiesLan()' and 'EntitiesLan.EntitiesLan()'

C++ 函数重载类似的转换

c++ - 避免过度使用命名空间

c++ - cl.exe 和 ml.exe 的问题

c++ - 这是合法的吗? C++

c++ - 如何使用 msvc10 和 ICU 编译 boost 1.54?

c++ - 模板接口(interface)实现类 C++ 错误

c++ - 试图计算一个字符串