values - dato booleano en c++
C++ Bool wrapper seguro (4)
Estoy intentando diseñar una estructura de envoltura bool aplicando el lenguaje bool seguro .
La implementación clásica para resolver esto es bastante trivial: el esqueleto podría ser algo como esto:
struct Bool final
{
Bool() = default;
Bool(bool value)
: _value{value}
{}
explicit operator bool() const {
return _value;
}
private:
bool _value{false};
};
La parte que estoy tratando de mejorar es cómo se construye Bool
.
Por ejemplo, quiero evitar el estrechamiento implícito por diseño:
Bool b1(45); // yields warnings, but it compiles
Bool b2{3}; // not ok by standard
Intenté hacerme daño usando plantillas, pero sin éxito.
¿Cómo podría hacerlo funcionar?
Estoy intentando diseñar una estructura de envoltura bool aplicando el lenguaje bool seguro.
No lo hagas
El lenguaje bool seguro solo es relevante en C ++ 03 y versiones anteriores, donde si expresas que tu tipo es "sincero" al hacer algo como:
struct A {
operator bool() const;
};
Te encontrarías con todo tipo de problemas como:
A{} + 4; // ok?!
A{} < 0; // ok?!
A{} == B{}; // ok if B also has operator bool??!
Así que el lenguaje seguro de bool fue una solución a este problema de conversión implícita accidental, utilizando punteros de función (¡por supuesto, punteros de función!).
En C ++ 11, tenemos una solución mucho mejor :
struct A {
explicit operator bool() const;
};
Que hace exactamente lo que queremos. De hecho, fue diseñado literalmente para resolver este problema. Y mientras que el lenguaje bool seguro es un andamio bastante complicado, explicit operator bool
es super sencillo de usar y simplemente hace lo correcto. No necesita una envoltura para ella; en realidad, es más difícil usar su envoltura que escribir directamente el explicit operator bool
.
Además, su envoltura impone al usuario (a) no derivabilidad porque hizo que Bool
final y (b) un miembro bool
extra, que debe mantener sincronizado, por lo que introduce problemas en lugar de resolverlos. Considere cuánto más trabajo sería para usted implementar:
template <class T>
struct my_unique_ptr : Bool { ... };
vs
template <class T>
struct my_unique_ptr {
T* ptr;
explicit operator bool() const { return ptr; }
};
Agregue, y elimine explícitamente un constructor de plantillas:
template <typename T>
Bool(T) = delete;
Coincide con cualquier otra cosa que no sea bool
real mejor que otros constructores, y así evitará la conversión implícita.
Puedes lograr esto eliminando explícitamente todos los otros constructores.
struct Bool final
{
template<class T>
Bool(T) = delete;
Bool(bool value);
};
Si solo necesitas:
Una variable que solo es "verdadera" o "falsa" y no se puede convertir implícitamente a int / char / pointer, entonces vería usando una clase enum:
enum class Bool {
False,
True,
};