Nel tentativo di rendere i miei enumerazioni più typesafe, ho usato gli operatori macro-generated sovraccarico per non consentire il confronto enumerazioni contro tutt'altro che un identico digitato enum:C++ conversione implicita a bool
#include <boost/static_assert.hpp>
#define MAKE_ENUM_OPERATOR_TYPESAFE(enumtype, op) \
template<typename T> \
inline bool operator op(enumtype lhs, T rhs) \
{ \
BOOST_STATIC_ASSERT(sizeof(T) == 0); \
return false; \
} \
\
template<> \
inline bool operator op(enumtype lhs, enumtype rhs) \
{ \
return static_cast<int>(lhs) op static_cast<int>(rhs); \
}
#define MAKE_ENUM_TYPESAFE(enumtype) \
MAKE_ENUM_OPERATOR_TYPESAFE(enumtype, ==) \
MAKE_ENUM_OPERATOR_TYPESAFE(enumtype, !=) \
MAKE_ENUM_OPERATOR_TYPESAFE(enumtype, >) \
MAKE_ENUM_OPERATOR_TYPESAFE(enumtype, <) \
MAKE_ENUM_OPERATOR_TYPESAFE(enumtype, >=) \
MAKE_ENUM_OPERATOR_TYPESAFE(enumtype, <=)
// Sample usage:
enum ColorType { NO_COLOR, RED, BLUE, GREEN };
MAKE_ENUM_TYPESAFE(ColorType)
Questo è generalmente l'effetto desiderato; confronti del modulo color_variable == RED
funzionano, mentre i confronti del modulo color_variable == 1
generano errori in fase di compilazione grazie a Boost.StaticAssert. (È un approccio decente?)
Tuttavia, il mio compilatore (CodeGear C++ Builder) sta anche tentando di utilizzare questi operatori sovraccaricati per implementare le conversioni implicite bool
. Ad esempio, if (color_variable) { ... }
viene convertito in if (operator!=(color_variable, 0)) { ... }
e sta attivando BOOST_STATIC_ASSERT
e non riesce a compilare.
Sono abbastanza sicuro che questo è un comportamento scorretto da parte del mio compilatore (Comeau e GCC non lo fanno, per esempio), ma mi chiedevo se ci sono avvocati di lingua presenti che potrebbero confermare. Ho provato a cercare lo standard di bozze C++ 0x, ma tutto ciò che ho trovato è stata la seguente dichiarazione nella sezione 4.12:
Un valore zero, un valore di puntatore nullo o un valore di puntatore membro nullo viene convertito in falso; qualsiasi altro valore viene convertito in vero.
senza dettagli su come viene verificato "un valore zero".
Poiché si sta tentando di renderlo più tipicamente, non avrebbe senso non consentire la conversione implicita in bool in ogni caso? – Grizzly
Non avevo deciso se non autorizzare la conversione in bool fosse una buona cosa. Il codice esistente con cui ho a che fare organizza le sue enumerazioni in modo tale che il valore intero 0 sia falso e tutto il resto è vero, quindi le conversioni bool sono legittime e probabilmente migliorano la leggibilità dei condizionali. (La leggibilità e lo stile di programmazione sono probabilmente una domanda a parte). –
(E se decido di non consentire conversioni implicite ai bool, preferirei non farlo in un modo che funziona solo su un compilatore.) –