Question

J'ai récemment fait un énorme refactoring où je changeais beaucoup de mon code pour booléens de retour au lieu d'un code de retour explicite. Pour aider ce refactoring j'ai décidé de se pencher sur le compilateur, si possible, en obtenant pour me dire les endroits où mon code devait être modifié. Je l'ai fait en introduisant la classe suivante ( voir ici pour la verité sur la façon dont fonctionne ce ) :

///
/// Typesafe boolean class
///
class TypesafeBool
{
private:
    bool m_bValue;
    struct Bool_ { 
        int m_nValue; 
    };
    typedef int Bool_::* bool_;
    inline bool_ True() const { return &Bool_::m_nValue; }
    inline bool_ False() const { return 0; }

public:
    TypesafeBool( const bool bValue ) : m_bValue( bValue ){}
    operator bool_() const { return m_bValue ? True() : False(); }
};

Maintenant, au lieu d'utiliser un type de bool normale que le type de retour, j'ai utilisé cette classe, qui signifiait que je ne pouvais pas compiler quelque chose comme ça plus:

TypesafeBool SomeFunction();
long result = SomeFunction(); // error

Grand: il a fait le refactoring gérable sur une énorme base de code en laissant le compilateur faire beaucoup de travail pour moi. Alors maintenant, j'ai fini mon refactoring et je tout à fait comme de garder cette classe traîner et continuez à l'utiliser, car il nous offre un niveau de sécurité supplémentaire que le type de bool intégré ne fonctionne pas.

Il y a cependant un « problème » qui me empêche de le faire. Actuellement, nous faisons un usage intensif de la ternaire opérateur dans notre code, et le problème est que il n'est pas compatible avec cette nouvelle classe sans moulages explicites:

TypesafeBool result = ( 1 == 2 ? SomeFunction() : false ); // error: different types used
TypesafeBool result = ( 1 == 2 ? SomeFunction() : (TypesafeBool)false );

Si je pouvais « résoudre » ce problème pour que je puisse utiliser ma classe d'une manière transparente, je ne serais probablement continuer à l'utiliser tout au long de la base de code. Est-ce que quelqu'un sait d'une solution à ce problème? Ou est-il tout simplement impossible de faire ce que je veux?

Était-ce utile?

La solution

      class CCastableToBool
      {  
      public:
         // ...
         operator bool() const
         {  
           //...
           {
              return true;
           } 
           //...
           return false;
         }  
      private:
         // ...
      }; 

mais méfiez-vous, en C ++, il est considéré comme très dangereux d'avoir une classe qui peut être casté en bool. Vous êtes avertis: -)

vous pouvez lire là, SafeBool

Vous devriez appeler TypesafeBool :: explicitement True () dans tous vos tests ternaires.

TypesafeBool result = ( 1 == 2 ? SomeFunction().True() : false );

Autres conseils

Dans le contexte de l'opérateur conditionnel, le type de l'expression est type commun des deux derniers opérandes. Les règles complètes pour déterminer ce type commun sont un peu complexe, mais votre cas arrive d'être trivial: si l'une des deux valeurs de retour possibles est un type de classe, l'autre valeur doit avoir la même classe et le type commun est évidemment aussi que classe.

Cela signifie que si l'un des opérandes est un TypesafeBool, l'autre doit être aussi bien.

Maintenant, le problème que vous êtes vraiment essayer de résoudre a été résolu avant. L'astuce ne fournit pas une classe; au lieu d'utiliser un typedef. Voir, par exemple, bool sécurité.

Je ne sais pas d'une manière transparente, l'opérateur ternaire a des restrictions sur son utilisation ...

Cependant, pourquoi ne pas définir deux constantes?

TypesafeBool const True = TypesafeBool(true);
TypesafeBool const False = TypesafeBool(false);

Et puis:

TypesafeBool result = ( 1 == 2 ? SomeFunction() : False );

Bien sûr, il est un peu orthodoxe bits depuis que je joue sur la capitalisation pour éviter la réutilisation d'un mot réservé:)

Est-il possible de faire le constructeur de TypesafeBool explicite? Bien sûr, maintenant l'utilisation doit être

TypesafeBool result( 1 == 2 ? b : false );

Pouvez-vous utiliser un opérateur d'affectation qui prend dans un bool comme argument externe, ainsi que celui qui prend un TypesafeBool? Il est peut-être quelque chose à essayer ...

Bien essayé, mais si votre base de code est grande, vous êtes probablement mieux d'utiliser un correcteur statique tel que PC-Lint pour rechercher bool implicite <->. Conversions int à la place

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top