[英]binary operator overloading, implicit type conversion
class my_bool {
private:
bool value;
public:
my_bool(bool value) : value(value) {}
explicit operator bool() { return value };
friend my_bool operator==(const my_bool & instance_1, const my_bool & instance_2);
friend my_bool operator&&(const my_bool & instance_1, const my_bool & instance_2);
};
void main(){
my_bool a = true;
bool b = false;
if(a == b){
// do something
}
if(a && b){
// do something
}
}
I have just created a similar topic regarding my problem over here binary operator overloading; 我刚刚在这里创建了一个关于我的问题的类似主题二元运算符重载; implicit type conversion .
隐式类型转换 。 It can be deleted I guess because it is not explicit enough about the problem I am encountering.
我可以删除它,因为它对我遇到的问题不够明确。
Why is that operator==
works fine and operator&&
causes ambiguities? 为什么
operator==
正常工作, operator&&
导致歧义? How do I solve this problem? 我该如何解决这个问题? I can surely write down two more overloads of
operator&&
( bool
, my_bool
), ( my_bool
, bool
). 我当然可以写下两个
operator&&
( bool
, my_bool
),( my_bool
, bool
)的my_bool
。 That is a messy solution though 这是一个混乱的解决方案
The builtin operator&&
is a context in which expressions are contextually converted to bool
. 内置
operator&&
是一个上下文,表达式在上下文中转换为bool
。 Other such contexts include for example the condition of if
, for
, while
and the conditional operator ?
其他这样的上下文包括例如
if
, for
, while
和条件运算符的条件?
. 。
Quoting N4296, §4/4 (the latest publicly available draft before C++14): 引用N4296,§4/ 4 (C ++ 14之前的最新公开草案):
Certain language constructs require that an expression be converted to a Boolean value.
某些语言结构要求将表达式转换为布尔值。 An expression
e
appearing in such a context is said to be contextually converted tobool
and is well-formed if and only if the declarationbool t(e);
在这样的上下文中出现的表达式
e
被称为在上下文中被转换为bool
并且当且仅当声明bool t(e);
才是格式良好的bool t(e);
is well-formed, for some invented temporary variablet
(8.5).对于一些发明的临时变量
t
(8.5),其形式良好。
Basically, this means that there is an "impicit explicit conversion to bool
" in these contexts. 基本上,这意味着在这些背景下存在“明显转换为
bool
”。 Or, to illustrate this further, you can think of the following two lines being one and the same: 或者,为了进一步说明这一点,您可以认为以下两行是同一个:
a && b
static_cast<bool>(a) && static_cast<bool>(b)
Therefore, the compiler must consider the explicit operator bool()
when doing overload resolution for operator&&
, but has to ignore it when doing overload resolution for operator==
(since that operator does not force a " bool
context" .. you can also compare numbers, strings, ...). 因此,编译器在为
operator&&
执行重载解析时必须考虑explicit operator bool()
,但在为operator==
执行重载解析时必须忽略它(因为该运算符不强制“ bool
上下文”...您还可以比较数字,字符串,...)。
The solution in your case is IMO to get rid of the operator&&(const my_bool&, const my_bool&)
all together. 您的案例中的解决方案是IMO将所有
operator&&(const my_bool&, const my_bool&)
一起operator&&(const my_bool&, const my_bool&)
。 After all, it does not produce a more meaningful behavior than what would be possible by relying on the builtin operator&&(bool, bool)
. 毕竟,它不会产生比依赖内置
operator&&(bool, bool)
更有意义的行为。 Establishing a second "boolean context" just isn't something the language was designed for (see below). 建立第二个“布尔上下文”并不是该语言的设计 (见下文)。
If you want to keep this operator, say for some side effects, then I see these choices: 如果你想保留这个操作符,比如说有些副作用,那么我会看到这些选择:
Be explicit at the call site. 在呼叫站点明确。 That is:
那是:
if (static_cast<my_bool>(a) && static_cast<my_bool>(b)) { /* ... */ }
Be explicit at the definition site: Provide additional definitions for operator&&(my_bool const &, bool)
, operator&&(bool, my_bool const &)
. 明确定义站点:为
operator&&(my_bool const &, bool)
, operator&&(bool, my_bool const &)
提供其他定义。 These then should rule out both operator&&(my_bool const &, my_bool const &)
as well as operator&&(bool, bool)
because the later are less specific. 然后这些应该排除
operator&&(my_bool const &, my_bool const &)
以及operator&&(bool, bool)
因为后者不太具体。 Adding these definitions to your class should mitigate the issue : 将这些定义添加到您的类应该可以缓解这个问题 :
friend my_bool operator&&(const my_bool & lhs, bool rhs) { // Delegate to operator&&(const my_bool &, const my_bool &) return lhs && my_bool(rhs); } friend my_bool operator&&(bool lhs, const my_bool & rhs) { // Delegate to operator&&(const my_bool &, const my_bool &) return my_bool(lhs) && rhs; }
Turns out one can "establish a boolean context", using CRTP: 事实证明,可以使用CRTP“建立布尔上下文”:
#include <iostream>
using namespace std;
template<typename T>
struct bool_context {
friend T operator&&(T const & lhs, bool rhs) {
return lhs && T(rhs);
}
friend T operator&&(bool lhs, T const & rhs) {
return T(lhs) && rhs;
}
friend T operator||(T const & lhs, bool rhs) {
return lhs || T(rhs);
}
friend T operator||(bool lhs, T const & rhs) {
return T(lhs) || rhs;
}
};
struct my_bool : bool_context<my_bool> {
bool value;
my_bool(bool v) : value(v) {}
explicit operator bool() { return value; };
friend my_bool operator&&(my_bool const & lhs, my_bool const & rhs) {
cout << "my_bool::operator&&" << endl;
return lhs.value && rhs.value;
}
friend my_bool operator||(my_bool const & lhs, my_bool const & rhs) {
cout << "my_bool::operator||" << endl;
return lhs.value || rhs.value;
}
};
int main(int, char**) {
my_bool a = true;
bool b = false;
cout << "a && b => "; a && b; // my_bool::operator&&
cout << "b && a => "; b && a; // my_bool::operator&&
cout << "a && a => "; a && a; // my_bool::operator&&
cout << "b && b => "; b && b; cout << endl;
cout << "a || b => "; a || b; // my_bool::operator||
cout << "b || a => "; b || a; // my_bool::operator||
cout << "a || a => "; a || a; // my_bool::operator||
cout << "b || b => "; b || b; cout << endl;
return 0;
}
My first thought on this is that the arguments to the compiler's built-in operator&&
are (bool, bool)
, so my_bool's explicit bool operator can be invoked - since you are in effect, requesting an explicit conversion. 我的第一个想法是编译器的内置
operator&&
是(bool, bool)
,因此可以调用my_bool的显式bool运算符 - 因为您生效,请求显式转换。
However, I can't find any reference in the standard as to whether a variable appearing on the right hand side of && should invoke an explicit conversion to bool. 但是,我在标准中找不到任何关于出现在&&右侧的变量是否应该调用显式转换为bool的引用。
Here's the complete error output from apple clang (once the source code above is fixed): 这是apple clang的完整错误输出(一旦上面的源代码被修复):
./nod.cpp:45:10: error: use of overloaded operator '&&' is ambiguous (with operand types 'my_bool' and 'bool')
if(a && b){
~ ^ ~
./nod.cpp:33:20: note: candidate function
friend my_bool operator&&(const my_bool & instance_1, const my_bool & instance_2);
^
./nod.cpp:45:10: note: built-in candidate operator&&(_Bool, _Bool)
if(a && b){
^
1 error generated.
So how do I fix it?
那么我该如何解决呢?
Remove the user-defined && operator. 删除用户定义的&&运算符。
class my_bool {
private:
bool value;
public:
my_bool(bool value) : value(value) {}
explicit operator bool() { return value; }
friend my_bool operator==(const my_bool & instance_1, const my_bool & instance_2);
// friend my_bool operator&&(const my_bool & instance_1, const my_bool & instance_2);
};
int main(){
my_bool a = true;
bool b = false;
if(a == b){
// do something
}
if(a && b){
// do something
}
}
The code bellow works in the same manner for both == and &&. 对于==和&&,下面的代码以相同的方式工作。 The class equality is triggered only when are of the same type.
仅当属于同一类型时才会触发类相等性。
#include <stdio.h>
class my_bool {
private:
bool v{false};
public:
my_bool() : v(v) {};
operator bool (){return v;}
friend bool operator==(const my_bool a, my_bool b){
printf("operator==\n");return a.v==b;
}
friend bool operator&&(const my_bool a, my_bool b){
printf("operator&&\n");return a.v&&b;
}
};
int main(int argc, char **argv)
{ printf("Starting\n");
bool a=true,b=true;
my_bool A{},B{},R{};
a==b;a&&b;
a==A;a&&A;
A==b;A&&b;
A==B;A&&B;
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.