Skip to content

operator bool and safe bool problem

stackoverflow What is the meaning of “operator bool() const”

The safe bool problem

cppreference Implicit conversions # The safe bool problem

Until the introduction of explicit conversion functions in C++11, designing a class that should be usable in boolean contexts (e.g. if(obj) { ... }) presented a problem: given a user-defined conversion function, such as T::operator bool() const;, the implicit conversion sequence allowed one additional standard conversion sequence after that function call, which means the resultant bool could be converted to int, allowing such code as obj << 1; or int i = obj;.

One early solution for this can be seen in std::basic_ios, which defines operator! and operator void*(until C++11), so that the code such as if(std::cin) {...} compiles because void* is convertible to bool, but int n = std::cout; does not compile because void* is not convertible to int. This still allows nonsense code such as delete std::cout; to compile, and many pre-C++11 third party libraries were designed with a more elaborate solution, known as the Safe Bool idiom.

(since C++11)

The explicit bool conversion can also be used to resolve the safe bool problemexplicit operator bool() const { ... }

stackoverflow Is the safe-bool idiom obsolete in C++11?

explicit operator bool() const;

NOTE:

1、simplify C++

A

Yes. This is the example for problems with only having implicit user-defined conversions and explicit user-defined conversion operators were practically invented because of this problem and to replace all the safe-bool stuff with something a lot cleaner and more logical.

stackoverflow Conversion function for error checking considered good?

I'd like to have a simple way of checking for an object to be valid. I thought of a simple conversion function, something like this:

operator bool() const { return is_valid; }

Checking for it to be valid would be very simple now

// is my object invalid?
if (!my_object) std::cerr << "my_object isn't valid" << std::endl;

Is this considered a good practise?

A

In C++03, you need to use the safe bool idiom to avoid evil things:

int x = my_object; // this works

In C++11 you can use an explicit conversion:

explicit operator bool() const
{
    // verify if valid
    return is_valid;
}

This way you need to be explicit about the conversion to bool, so you can no longer do crazy things by accident (in C++ you can always do crazy things on purpose):

int x = my_object; // does not compile because there's no explicit conversion
bool y = bool(my_object); // an explicit conversion does the trick

NOTE:

1、体现了C++的灵活、自由

This still works as normal in places like if and while that require a boolean expression, because the condition of those statements is contextually converted to bool:

// this uses the explicit conversion "implicitly"
if (my_object)
{
    ...
}