为什么用整数文字调用重载的 ambig(long) 和 ambig(unsigned long) 是不明确的?
编译时
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
来修复"它,但是为什么/首先这被认为是模棱两可的?>
I know I can 'fix' it by saying -1L
instead of -1
, but why/how exactly is this considered ambiguous in the first place?
推荐答案
您正在将 int
传递给这个重载函数.
You're passing an int
to this overloaded function.
尽管人类直觉认为 ambig(signed long)
应该是首选,因为您的输入是一个负整数(不能用 unsigned long
表示),这两种转换实际上在 C++ 中的优先级"是等价的.
Although human intuition says that ambig(signed long)
ought to be preferred because your input is a negative integer (which cannot be represented as such by an unsigned long
), the two conversions are in fact equivalent in "precedence" in C++.
即转换int
→unsigned long
被认为与 int
一样有效 →signed long
,两者都不是首选.
That is, the conversion int
→ unsigned long
is considered to be just as valid as int
→ signed long
, and neither is preferred to the other.
另一方面,如果您的参数已经是 long
而不是 int
,那么 完全匹配到 signed long
,无需转换.这避免了歧义.
On the other hand, if your parameter were already a long
rather than an int
, then there is an exact match to signed long
, with no conversion necessary. 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]:
("整数转换等级")
每个整数类型都有一个整数转换等级,定义如下:
Every integer type has an integer conversion rank defined as follows:
- [..]
- 有符号整数类型的等级应大于任何较小尺寸的有符号整数类型的等级.
long long int
的rank大于long int
的rank,大于rankint
的等级,应该大于short int
的等级,short int
的等级应该大于signed char 的等级.- 任何无符号整数类型的等级应等于相应有符号整数类型的等级.
- [..]
- [..]
- 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 oflong int
, which shall be greater than the rank ofint
, which shall be greater than the rank ofshort 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.
- [..]
[ 注意: 整数转换等级用于定义整数提升(4.5)和通常的算术转换(第 5 条).―结束注释 ]
[ 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]
中定义;我不会因为在这里引用大部分内容而让您感到厌烦.
Overload resolution is complex, and is defined in [C++11: 13.3]
; I shan't bore you by quoting a majority of it here.
不过,这里有一个亮点:
Here's a highlight, though:
[C++11: 13.3.3.1/8]:
如果不需要转换来匹配参数到参数类型,则隐式转换序列是由标识组成的标准转换序列转换(13.3.3.1.1).
[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]:
如果找不到将参数转换为参数类型的转换序列,或者转换的其他形式不正确,则隐式无法形成转换序列.
[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]:
如果存在多个不同的转换序列,每个序列都将参数转换为参数类型,则定义与参数关联的隐式转换序列将唯一的转换序列指定为不明确的转换序列.为了对 13.3.3.2 中描述的隐式转换序列进行排序,模糊转换序列被视为用户定义的序列,与任何其他用户定义的转换序列没有区别134.如果使用模糊转换序列的函数被选为最佳可行函数,则调用将是格式错误的,因为调用中的一个参数的转换是不明确的.
[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
参数的情况./10
is the case you're experiencing;/8
is the case you use with along
argument.
相关文章