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)
{
...
}