Is there a trick to get the safe bool idiom completely working without having to derive from a class that does the actual implementation?
With 'completely working', I mean the class having an operator allowing it to be tested as if it were a boolean but in a safe way:
MyTestableClass a;
MyOtherTestableClass b;
//this has to work
if( a );
if( b );
//this must not compile
if( a == b );
if( a < b );
int i = a;
i += b;
when using this implementation for example
struct safe_bool_thing
{
int b;
};
typedef int safe_bool_thing::* bool_type;
safe_bool( const bool b ) { return b ? &safe_bool_thing::b : 0; }
class MyTestableClass
{
operator bool_type () const { return safe_bool( someCondition ); }
}
it's almost fine, except a == b will still compile, since member pointers can be compared. The same implementation as above, but with pointer to member function instead of pointer to member variable has exactly the same problem.
Known implementations that do work perfectly (as described here for example, or the safe_bool used in boost) require that the testable class derive from a class providing the actual operator implementation.
I actually think there is no way around it, but'm not entirely sure. I tried something that looked a bit fischy but I thought it might work, yet is doesn't compile at all. Why is the compiler not allowed to see that the operator returns a safe_bool_thing, which in turn can be converted to bool() and hence be tested?
struct safe_bool_thing
{
explicit safe_bool_thing( const bool bVal ) : b( bVal ) {}
operator bool () const { return b; }
private:
const bool b;
safe_bool_thing& operator = ( const safe_bool_thing& );
bool operator == ( const safe_bool_thing& );
bool operator != ( const safe_bool_thing& );
};
class MyTestableClass
{
operator safe_bool_thing () const { return safe_bool_thing( someCondition ); }
};
MyTestableClass a;
if( a ); //conditional expression of type 'MyTestableClass' is illegal