c++ 重载运算符 bool() 使用运算符 + 给出了一个不明确的重载错误
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/5306696/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
c++ Overload operator bool() gives an ambiguous overload error with operator+
提问by Didier A.
I'm compiling some c++ code of a class MegaInt which is a positive decimal type class that allows arithmetic operations on huge numbers.
我正在编译类 MegaInt 的一些 C++ 代码,它是一个正十进制类型类,允许对大量数字进行算术运算。
I want to overload operator bool to allow code like this:
我想重载 operator bool 以允许这样的代码:
MegaInt m(45646578676547676);
if(m)
cout << "YaY!" << endl;
This is what I did:
这就是我所做的:
header:
标题:
class MegaInt
{
public:
...
operator bool() const;
};
const MegaInt operator+(const MegaInt & left, const MegaInt & right);
const MegaInt operator*(const MegaInt & left, const MegaInt & right);
implementation:
执行:
MegaInt::operator bool() const
{
return *this != 0;
}
const MegaInt operator+(const MegaInt & left, const MegaInt & right)
{
MegaInt ret = left;
ret += right;
return ret;
}
Now, the problem is if I do:
现在,问题是如果我这样做:
MegaInt(3424324234234342) + 5;
It gives me this error:
它给了我这个错误:
ambiguous overload for 'operator+' in 'operator+(const MegaInt&, const MegaInt&) note: candidates are: operator+(int, int) | note: const MegaInt operator+(const MegaInt&, const MegaInt&)|
'operator+(const MegaInt&, const MegaInt&) 中'operator+' 的不明确重载注意:候选对象是:operator+(int, int) | 注意:const MegaInt 运算符+(const MegaInt&, const MegaInt&)|
I don't know why. How is the overloaded bool() causing operator+ to become ambiguous??
我不知道为什么。重载的 bool() 是如何导致 operator+ 变得模棱两可的??
Thank You.
谢谢你。
Well, everyone gave me great answers, unfortunately, none of them seem to solve my problem entirely.
好吧,每个人都给了我很好的答案,不幸的是,他们似乎都没有完全解决我的问题。
Both void* or the Safe Bool Idiom works.Except for one tiny problem, I hope has a workaround:
void* 或 Safe Bool Idiom 都有效。除了一个小问题,我希望有一个解决方法:
When comparing with 0 like:
当与 0 比较时,例如:
if (aMegaInt == 0)
The compiler gives an ambiguous overload error again. I understand why: it doesn't know if we're comparing to false or to MegaInt of value 0. None the less, in that case, I'd want it to cast to MegaInt(0). Is there a way to force this?
编译器再次给出了一个不明确的重载错误。我明白为什么:它不知道我们是在与 false 还是与值为 0 的 MegaInt 进行比较。不过,在这种情况下,我希望它转换为 MegaInt(0)。有没有办法强制这个?
Thank You Again.
再次感谢你。
回答by Ken Bloom
The C++ compiler is allowed to automatically convert bool
into int
for you, and that's what it wants to do here.
C ++编译器允许自动转换bool
成int
你的,这就是它想在这里做。
The way to solve this problem is to employ the safe bool idiom.
解决这个问题的方法是使用安全布尔习语。
Technically, creating an operator void*
is notan example of the safe bool idiom, but it's safe enough in practice, because the bool/int problem you're running into is a common error, and messes up some perfectly reasonable and otherwise correct code (as you see from your question), but misuses of the void*
conversion are not so common.
从技术上讲,创建operator void*
是不是安全布尔成语的例子,但它在实践中不够安全,因为你正在运行到布尔/ INT问题是一个常见的错误,并打乱了一些非常合理的,否则正确的代码(如你从您的问题中看到),但滥用void*
转换并不常见。
回答by MSN
The wikipedia entry on explicit conversion operators for C++0xhas a decent summary of why you see this error pre-C++0x. Basically, the bool
conversion operator is an integral conversion type, so it will be used in an integral arithmetic expression. The pre-C++0x fix is to instead use void *
as the conversion operator; void *
can be converted to a boolean expression, but not to an integral expression.
关于 C++0x 的显式转换运算符的维基百科条目有一个不错的总结,说明为什么在 C++0x 之前会看到此错误。基本上,bool
转换运算符是一种整数转换类型,因此它将用于整数算术表达式中。C++0x 之前的修复是改为void *
用作转换运算符;void *
可以转换为布尔表达式,但不能转换为整数表达式。
回答by Jon
As Erik's answer states, the problem here is that by providing an implicitconversion to bool
you are opening the door to expressions that can mean multiple things; in this case the compiler will complain of ambiguity and give your an error.
正如 Erik 的回答所述,这里的问题在于,通过向您提供隐式转换,bool
为可能意味着多种事物的表达式打开了大门;在这种情况下,编译器会抱怨歧义并给你一个错误。
However, note that providing an implicitconversion to void*
will not let you off the hook; it will just change the set of expressions which present a problem.
但是,请注意,提供隐式转换 tovoid*
不会让您摆脱困境;它只会改变出现问题的表达式集。
There are two airtight solutions to this issue:
这个问题有两种密封的解决方案:
- Make the conversion to
bool
explicit (which can be undesirable if the class represents an entity with an intuitive "true/false" value) - Use the safe bool idiom(this really covers all bases, but as many good things in life and C++ is way too complicated -- you pay the price)
- 转换为
bool
显式(如果类表示具有直观“真/假”值的实体,则可能不受欢迎) - 使用安全布尔习语(这确实涵盖了所有基础,但生活中的许多美好事物和 C++ 都太复杂了——你付出了代价)
回答by Omnifarious
The problem is that bool
can freely convert to int
. So the expression MegaInt(3424324234234342) + 5;
can equally validly be interpreted this way:
问题是bool
可以自由转换为int
. 所以这个表达式MegaInt(3424324234234342) + 5;
可以同样有效地解释为:
(bool)(MegaInt(3424324234234342)) + 5;
or:
或者:
MegaInt(3424324234234342) + MegaInt(5);
Each one of those expressions involves one user defined conversion and are equal in the eyes of the compiler. Conversion to bool
is highly problematic for this reason. It would be really nice to have a way to say it should only happen in a context that explicitly requires a bool
, but there isn't. :-/
这些表达式中的每一个都涉及一个用户定义的转换,并且在编译器的眼中是相等的。bool
由于这个原因,转换为非常成问题。有一种方法可以说它应该只发生在明确需要 a 的上下文中bool
,但事实并非如此。:-/
The conversion to void *
that someone else suggests is a workaround, but I think as a workaround it has problems of its own and I wouldn't do it.
转换为void *
其他人建议的方法是一种解决方法,但我认为作为一种解决方法,它有其自身的问题,我不会这样做。
回答by Erik
MegaInt(3424324234234342) + 5;
MegaInt + int;
Should the compiler convert your MegaInt to an integral (bool is an integral type) or the integer to MegaInt (you have an int constructor)?
编译器应该将您的 MegaInt 转换为整数(bool 是整数类型)还是将整数转换为 MegaInt(您有一个 int 构造函数)?
You fix this by creating an operator void *
instead of an operator bool
:
您可以通过创建一个operator void *
而不是一个来解决这个问题operator bool
:
operator void *() const { return (*this != 0) ? ((void *) 1) : ((void *) 0); }
operator void *() const { return (*this != 0) ? ((void *) 1) : ((void *) 0); }
回答by Zack Yezek
Others have mentioned the Safe Bool Idiom. However, for objects like yours it is a bad idea to add all this nasty, special logic when you want full algebra support anyway.
其他人提到了 Safe Bool 习语。然而,对于像你这样的对象,当你想要完全代数支持时,添加所有这些讨厌的、特殊的逻辑是一个坏主意。
You're defining a custom integer type. You get far more for your effort by defining "operator==" and "operator!=", then implementing "operator bool()" as something like:
您正在定义自定义整数类型。通过定义“operator==”和“operator!=”,然后像这样实现“operator bool()”,你会得到更多的回报:
operator bool()
{
return (*this != 0);
}
Just from those 3 functions you get all of the "if" idioms for integers, and they'll behave the same for your custom ints as the built-in ones: "if(a==b)", "if(a!=b)", "if(a)", "if(!a)". Your implicit "bool" rule will also (if you're careful) work intuitively as well.
仅从这 3 个函数中,您就可以获得整数的所有“if”习语,对于您的自定义整数,它们的行为与内置函数相同:“if(a==b)”、“if(a! =b)”、“if(a)”、“if(!a)”。您隐含的“bool”规则也将(如果您小心的话)直观地工作。
Besides, the full "Safe Bool Idiom" is unnecessary. Think about it- the only time you need it is "1) comparison of 2 objects is ill-defined or undefined, 2) cast to (int) or other primitive types needs to be protected and 3) object validity IS well-defined (the actual source of the returned bool)."
此外,不需要完整的“Safe Bool Idiom”。想一想——你唯一需要它的时候是“1)2个对象的比较是不明确或未定义的,2)转换为(int)或其他原始类型需要受到保护,3)对象有效性是明确定义的(返回的 bool 的实际来源)。”
Well, 2) is only a consideration if you actually wish to SUPPORT casting to a numeric type like int or float. But for objects that have NO well-defined notion of equality (# 1), providing such casts unavoidably creates the risk of the very "if(a==b)" logic bombs the idiom supposedly protects you from. Just declare "operator int()" and such private like you do with the copy ctor on non-copyable objects and be done with it:
好吧,2) 只是如果您确实希望支持强制转换为 int 或 float 等数字类型的一个考虑因素。但是对于没有明确定义的平等概念(#1)的对象,提供这样的强制转换不可避免地会产生“if(a==b)”逻辑炸弹的风险,这个习语据说可以保护你免受。只需声明“operator int()”和这样的私有,就像你在不可复制的对象上使用复制构造函数所做的那样,然后完成它:
class MyClass {
private:
MyClass(const MyClass&);
operator int();
operator long();
// float(), double(), etc. ...
public:
// ctor & dtor ..
bool operator==(const MyClass& other) const { //check for equality logic... }
bool operator!=(const MyClass& other) const { return !(*this == other); }
operator bool() { return (*this != 0); }
};