For classes which have both 'explicit operator bool()' and 'operator void*()' (or any other pointer type) the latter is preferred if operator || is involved in the if condition.
The following code is written in a way that makes sure operator bool() will return true but void* will give nullptr so that if (p) is only true if operator bool was called
#include <iostream>
class ptr {
void* v = nullptr;
public:
operator void*() const { return v; }
explicit operator bool() const { return v == nullptr; }
};
int main()
{
ptr p;
if (p || p != nullptr)
std::cout << "bool operator was called for ||\n";
else
std::cout << "bool operator ignored for ||\n";
if (p)
std::cout << "bool operator was called for simple if\n";
else
std::cout << "bool operator was ignored for simple if\n";
return 0;
}
The output from this program is
bool operator ignored for ||
bool operator was called for simple if
Seems like a bug, as mentioned by Implicit conversions - cppreference.com
In the following five contexts, the type bool is expected and the implicit conversion sequence is built if the declaration bool t(e); is well-formed. that is, the explicit user-defined conversion function such as explicit T::operator bool() const;
is considered. Such expression e
is said to be contextually convertible to bool.
- controlling expression of
if
, while
, for
; - the logical operators
!
, &&
and ||
; - the conditional operator
?:
; static_assert
;noexcept
.