«Безопасная идиома» - это технический ответ на вопрос «я хочу автомобиль, который будет как спортивным, так и тракторным, и, возможно, лодкой». Практический ответ - это не технический ответ & hellip;
Тем не менее, проблема, которую он решает, состоит в том, чтобы просто дать результат, который можно преобразовать в bool
, но не во что-либо еще (в противном случае экземпляр класса может быть передан в качестве фактического аргумента, например, формальным аргументом был int
, скажем). Указатель данных может быть преобразован в void*
. Указатель на функцию не является, по крайней мере, формально в стандарте C ++ (Posix - это нечто иное, также практикуйтесь).
Использование указателя на функцию-член защищает от случайного вызова функции, учитывая указатель от оператора безопасной bool. const
немного ограничивает его, но если судьба поставила кого-то на путь совершения максимального количества глупых ошибок, этому человеку все равно удастся вызвать функцию "ничего не делать". Вместо const
я думаю, я бы просто позволил ему иметь аргумент закрытого типа, где другой код не может предоставить такой аргумент, и тогда он больше не должен быть глупым типом функции-члена.
Может выглядеть так:
#include <stdio.h>
class Foo
{
private:
enum PrivateArg {};
typedef void (*SafeBool)( PrivateArg );
static void safeTrue( PrivateArg ) {}
bool state_;
public:
Foo( bool state ): state_( state ) {}
operator SafeBool () const
{ return (state_? &safeTrue : 0); }
};
int main()
{
if( Foo( true ) ) { printf( "true\n" ); }
if( Foo( false ) ) { printf( "false\n" ); } // No output.
//int const x1 = Foo( false ); // No compilado!
//void* const x2 = Foo( false ); // No compilado!
}
Конечно, практический ответ - что-то вроде этого:
#include <stdio.h>
class Foo
{
private:
bool isEmpty_;
public:
Foo( bool asInitiallyEmpty )
: isEmpty_( asInitiallyEmpty )
{}
bool isEmpty() const { return isEmpty_; }
};
int main()
{
if( Foo( true ).isEmpty() ) { printf( "true\n" ); }
if( Foo( false ).isEmpty() ) { printf( "false\n" ); } // No output.
//bool const x0 = Foo( false ); // No compilado!
//int const x1 = Foo( false ); // No compilado!
//void* const x2 = Foo( false ); // No compilado!
}
Резюме по отношению к задаваемые вопросы:
- Почему константные сравнения типа bool_type (typedef) и this_type_does_not_support_const?
Кто-то не совсем понял, что они закодировали. Или возможно они намеревались немного ограничить возможность звонить. Но тогда, довольно бесполезная мера.
- Никто не должен фактически вызывать функцию-член через указатель возврата, верно?
правый.
- Требуется ли здесь const?
номер
- В противном случае оператор bool_type (функция-член) нарушил бы правильность const?
номер
Приветствия и hth.,