简体   繁体   English

我可以让三元运算符把我的班级当作布尔吗?

[英]Can I make the ternary operator treat my class like a bool?

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: 现在,我没有使用普通的bool类型作为返回类型,而是使用了此类,这意味着我无法再编译如下内容:

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. 因此,现在我已经完成了重构,并且我很想让此类继续徘徊并继续使用它,因为它为我们提供了内置bool类型无法提供的额外安全性。

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? 还是做我想做的事是不可能的?

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. 这意味着,如果操作数之一是TypesafeBool,则另一个也必须是TypesafeBool。

Now the problem you're really trying to solve has been solved before. 现在,您真正要解决的问题已经解决了。 The trick is not providing a class; 诀窍不是提供课程;而是提供课程。 instead use a typedef. 而是使用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 :) 当然,这有点不合常规,因为我在使用大写字母时避免重复使用保留字:)

      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. 但是要注意,在C ++中,拥有可以强制转换为bool的类真的很危险。 You are warned :-) 警告您:-)

you can read this there, SafeBool 你可以在这里阅读, SafeBool

You should explicitely call TypesafeBool::True() in all your ternary tests. 您应该在所有三元测试中显式调用TypesafeBool :: True()。

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

Is it a possibility to make the constructor of TypesafeBool explicit? 是否可以使TypesafeBool的构造函数明确? 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? 您能否使用将布尔值作为外部参数的赋值运算符,以及将TypesafeBool用作参数的赋值运算符? It might be something to try out... 可能要尝试一下...

不错的尝试,但是如果您的代码库很大,则最好使用PC-Lint之类的静态检查器来代替查找隐式bool <-> int转换。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM