vendredi 24 avril 2020

C++: using class with explicit operator bool overloaded

Context:

I have a class with an internal boolean value that seems like a good candidate for overloading operator bool, like this:

class MyBool{

    private:
    bool value_ = false;

    // Nice API and logic to set the interal value_ to true or false...

    public: 
    explicit operator bool() const {
        return value_;
    };

};

From https://en.cppreference.com/w/cpp/language/implicit_conversion, "Contextual conversions" section, this works in:

  • the controlling expression of if, while, for;
  • the operands of the built-in logical operators !, && and ||;
  • the first operand of the conditional operator ?:;
  • the predicate in a static_assert declaration;
  • the expression in a noexcept specifier;

Which explains why I get errors when trying to use it in other ways, like this:

MyBool x;  
///...
bool y = x; // --> error: cannot convert ‘MyBool’ to ‘bool’ in initialization 
// or:
bool z; 
z = x;      // --> error: cannot convert ‘MyBool’ to ‘bool’ in assignment

// Or returning from a function:
bool func(...){
     MyBool x;
     // ...
     return x; // --> error: cannot convert ‘MyBool’ to ‘bool’ in return
}

// Or in Gtests, like:
MyBool x;
// ...
EXPECT_TRUE(x); // --> error: no matching function for call to ‘testing::AssertionResult::AssertionResult(MyBool)’

If I removed the explicit keyword, some problems cold arise because of implicit conversions (safe bool idiom in pre C++11: http://blog.asymptotic.co.uk/2014/03/the-safe-bool-idiom-in-c/).

In these cases, I could explicitly cast the MyBool variable to bool and it would work, but to me, this non-homogeneous use kind of defeats the purpose of overloading the operator, that is: to be able to naturally use MyBool as a bool. Instead, I could add a member function like this:

bool get_value() const {
    return value_;
}

And use x.get_value() every time I need to "cast" to bool, even in the conditions, loops, etc.

The question is: is there a way to use this class in the cases above, or some of them, with modifications to the class code only (not the calling code), and without removing the explicit keyword? (Preferrably in C++11).

Aucun commentaire:

Enregistrer un commentaire