문제

I've recently been doing a huge refactoring where I was changing a lot of my code to return booleans instead of an explicit return code. To aid this refactoring I decided to lean on the compiler where possible by getting it to tell me the places where my code needed to be changed. I did this by introducing the following class (see here for the lowdown on how this works):

///
/// 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(); }
};

Now, instead of using a normal bool type as the return type, I used this class which meant that I couldn't compile something like this any more:

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

Great: it has made the refactoring manageable on a huge codebase by letting the compiler do a lot of the hard work for me. So now I've finished my refactoring and I'd quite like to keep this class hanging around and carry on using it since it affords us an extra level of safety that the built-in bool type doesn't.

There is however one "problem" which is preventing me from doing this. At the moment we make heavy use of the ternary operator in our code, and the problem is that it is not compatible with this new class without explicit casts:

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

If I could "solve" this issue so that I could use my class in a seamless manner I would probably carry on using it throughout the codebase. Does anyone know of a solution to this issue? Or is it just impossible to do what I want?

도움이 되었습니까?

해결책

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

but beware, in C++ it is considered really dangerous to have a class that can be casted to bool. You are warned :-)

you can read this there, SafeBool

You should explicitely call TypesafeBool::True() in all your ternary tests.

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

다른 팁

In the context of the conditional operator, the type of the expression is the common type of the last two operands. The complete rules to determine this common type are a bit complex, but your case happens to be trivial: if one of the two possible return values is a class type, the other value must have the same class and the common type is obviously also that class.

That means that if one of the operands is a TypesafeBool, then the other must be as well.

Now the problem you're really trying to solve has been solved before. The trick is not providing a class; instead use a typedef. See for instance safe bool.

I don't know about a seamless manner, the ternary operator has some restrictions on its use...

However, why don't you define two constants ?

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

And then:

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

Of course, it's a bit unorthodox since I play on the capitalization to avoid reusing a reserved word :)

Is it a possibility to make the constructor of TypesafeBool explicit? Of course, now the usage has to be

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

Could you use an assignment operator that takes in a bool as the external argument, as well as one that takes a TypesafeBool? It might be something to try out...

Nice try, but if your code base is large, you are probably better off using a static checker such as PC-Lint to look for implicit bool<->int conversions instead.

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top