对重载的整数构造函数的不明确调用

时间:2016-01-22 21:02:26

标签: c++ c++11 integer type-conversion integer-promotion

我将提供这两个构造函数。

BigUnsigned(int value)
    :BigUnsigned(static_cast<unsigned long long>(value)){
}
BigUnsigned(unsigned long long value);

问题是某些参数值的调用是不明确的。根据{{​​3}},它引用了C ++ 11标准,

  

整数文字的类型是相应列表的第一个   在表6中,其值可以表示。

表6在这里

int
long int
long long int

因此,在我的例子中,构造函数参数的类型(整数文字),如果它属于范围......

<0, numeric_limits<int>::max()>int

---&GT;调用BigUnsigned(int)

(numeric_limits<int>::max(), numeric_limits<long int>::max()>long int

---&GT;暧昧

(numeric_limits<long int>::max(), too big literal)long long int

---&GT;暧昧的

如何在不声明任何构造函数或显式类型化参数的情况下解决歧义?

integer promotioninteger conversion上的

this answer可能有用。不过,我仍然不知道它们适用于我的情况。

1 个答案:

答案 0 :(得分:3)

这里的一个基本问题是十进制文字永远不会被推断为无符号类型。因此,一个十分小的文字太大而不适合int最终需要在一种情况下进行signed-gt;无符号转换,而在另一种情况下需要long-gt; int转换。这两个都被归类为&#34;积分转换&#34;,因此它们都不被视为&#34;更好&#34;转换,过载是模棱两可的。

至于在没有明确地转换参数或添加更多构造函数的情况下处理此问题的可能方法,我可以看到一对。

至少对于文字,你可以添加一个后缀,指明文字的类型是无符号的:

BigUnsigned a(5000000000U); // unambiguous

另一个(也仅适用于文字)将使用十六进制或八进制文字,(根据问题中未引用的表6的部分)可以推导为签名未签名。这只是一个部分修复 - 它只适用于推导为无符号的值。对于具有32位int,32位长和64位长的典型系统,我相信它会像这样出现:

enter image description here

因此,对于一个足够大的参数,它不符合有符号的长整数,这给出了一个明确的调用,其中十进制常量仍然是模糊的。

对于使用较小类型的人来说,最初看起来似乎从无符号长号到无符号长号的转换有资格作为促销而不是转换,这会使其更受欢迎。事实上,如果(例如)所涉及的类型是unsigned shortunsigned int,那将完全正确 - 但只有转换排名小于int的类型才会给出特殊偏好(基本上转换为:小于int的类型)。

这样就解决了一系列数字的问题,但只有当它们是文字时,并且只有当它们属于一个特定的(尽管是非常大的)范围时才会解决。

对于更一般的情况,唯一真正的解决方法是更改​​界面。删除int的重载,或添加一些ctor重载,特别是unsignedlong long。这些可以像int的现有构造函数一样委托构造函数,如果你决定需要它们(但是最好只有unsigned long long的构造函数并完成它)。