Есть ли хитрость для того, чтобы идиома безопасной bool полностью работала без необходимости наследования от класса, который выполняет реальную реализацию?
Под «полностью работающим» я имею в виду класс, имеющий оператор, позволяющий емубыть протестированным, как если бы он был логическим, но безопасным способом:
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;
при использовании этой реализации, например
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 ); }
}
это почти нормально, за исключением того, что a == b все равно будет компилироваться, поскольку указатели членов можно сравнивать.Та же реализация, что и выше, но с указателем на функцию-член вместо указателя на переменную-член имеет точно такую же проблему.
Известные реализации, которые работают идеально (как описано, например, здесь , илиsafe_bool, используемый в boost), требует, чтобы тестируемый класс был производным от класса, обеспечивающего фактическую реализацию оператора.
Я на самом деле думаю, что нет никакого способа обойти это, но я не совсем уверен.Я попробовал что-то, что выглядело немного странно, но я подумал, что это может сработать, но это не компилируется вообще.Почему компилятору не разрешено видеть, что оператор возвращает safe_bool_thing, который, в свою очередь, может быть преобразован в bool () и, следовательно, протестирован?
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