二元运算符重载,隐式类型转换

时间:2016-04-03 23:36:57

标签: c++

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 
  }
}

我刚刚在binary operator overloading; implicit type conversion创建了一个关于我的问题的类似主题。我可以删除它,因为它对我遇到的问题不够明确。

为什么operator==工作正常,operator&&导致含糊不清?我该如何解决这个问题?我当然可以写下operator&&boolmy_bool),(my_boolbool)的两个重载。这是一个混乱的解决方案

3 个答案:

答案 0 :(得分:5)

内置operator&&是一个上下文,表达式从上下文转换bool。其他此类上下文包括例如ifforwhile和条件运算符?的条件。

引用N4296, §4/4(C ++ 14之前的最新公开草案):

  

某些语言结构要求将表达式转换为布尔值。表达式e   出现在这样的背景中的人被称为在上下文中被转换为bool并且当且仅当如此   对于一些发明的临时变量bool t(e);(8.5),声明t格式正确。

基本上,这意味着有一个"明显转换为bool"在这些情况下。或者,为了进一步说明这一点,您可以认为以下两行是同一个:

a && b
static_cast<bool>(a) && static_cast<bool>(b)

因此,编译器在为explicit operator bool()执行重载解析时必须考虑operator&&,但在对operator==执行重载解析时必须忽略它(因为该运算符不强制执行& #34; bool context&#34; ..你也可以比较数字,字符串......)。

您的案例中的解决方案是IMO一起摆脱operator&&(const my_bool&, const my_bool&)。毕竟,它不会产生比依赖内置operator&&(bool, bool)更有意义的行为。 建立第二个&#34;布尔上下文&#34;只是不是为设计的语言(见下文)。

如果你想保留这个操作符,比如说有些副作用,那么我会看到这些选择:

  • 在呼叫网站上明确说明。那就是:

    if (static_cast<my_bool>(a) && static_cast<my_bool>(b)) { /* ... */ }
    
  • 明确定义网站:为operator&&(my_bool const &, bool)operator&&(bool, my_bool const &)提供其他定义。然后,这些应排除operator&&(my_bool const &, my_bool const &)operator&&(bool, bool),因为后者不太具体。将这些定义添加到您的班级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;
    }
    

结果可以使用CRTP建立一个布尔上下文&#34;

#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;
}

Ideone

答案 1 :(得分:1)

我首先想到的是编译器的内置operator&&的参数是(bool, bool),因此可以调用my_bool的显式bool运算符 - 因为你有效,请求显式转换。

但是,我无法在标准中找到关于变量是否出现在&amp;&amp;的右侧的参考文献。应该调用显式转换为bool。

这是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.
  

那我该如何解决呢?

删除用户定义的&amp;&amp;操作

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
    }
}

答案 2 :(得分:0)

代码bellow对于==和&amp;&amp;同样适用。 仅当类型相同时才会触发类相等。

#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;
}