La expresión idiomática de "bool seguro" es la respuesta técnica a la pregunta "quiero un vehículo que sea tanto deportivo como tractor, y tal vez un barco". La respuesta práctica no es la respuesta técnica & hellip;
Dicho esto, el problema que resuelve es simplemente dar un resultado que es convertible a bool
pero no a mucho más (de lo contrario una instancia de la clase podría pasar como argumento real donde por ejemplo el argumento formal fue int
, decir). Un puntero de datos podría ser convertible a void*
. Un puntero a la función no está, al menos formalmente dentro del estándar de C++ (Posix es otra cosa, también práctica).
El uso de un puntero de función miembro protege contra la llamada accidental de la función, dado el puntero del operador de bool seguro. El const
restringe un poco, pero si el destino ha puesto a alguien en el camino de cometer el mayor número de errores tontos, esa persona aún podría llamar a la función de no hacer nada. En lugar de const
, creo que simplemente dejaría que tenga un argumento de tipo privado, donde otro código no puede proporcionar ese argumento, y entonces ya no tiene que ser un tipo de función tonto.
podría tener este aspecto:
#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!
}
Por supuesto, la respuesta práctica es en cambio algo como esto:
#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!
}
Resumen WRT. preguntas hechas:
- ¿Cómo es que el bool_type (typedef) y this_type_does_not_support_comparisons son const?
Alguien no entendió exactamente lo que codificaron. O tal vez tenían la intención de restringir la capacidad de llamar, un poco. Pero entonces, una medida bastante inútil.
- En realidad, se supone que nadie llama a la función miembro a través del puntero de retorno, ¿verdad?
Derecha.
- ¿Es necesario const aquí?
Nº
- Would bool_type operador (la función miembro) viola const-corrección de otro modo?
No.
Saludos & HTH.,
Mi apuesta es que 'const' no es necesario. Tampoco es un cuerpo para la función, ya que se supone que no debes llamar a la función de todos modos. –
@Alex: Pero una función miembro sin cuerpo no tiene dirección, ¿verdad? No se compila sin un cuerpo en VC10, al menos. – fredoverflow
hmm tienes razón. Acabo de revisar mi plantilla 'safe_bool' Tengo un profundo en mi proyecto actual VS2010 y tiene un cuerpo. Tiene 'const' también. –