我可以让三元运算符像bool一样对待我的班级吗?

时间:2010-08-20 08:57:15

标签: c++ type-conversion type-safety

我最近一直在做一个巨大的重构,我正在改变我的很多代码来返回布尔值而不是显式的返回代码。为了帮助这种重构,我决定尽可能地依赖编译器,让它告诉我需要更改代码的地方。我通过介绍以下类(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(); }
};

现在,我没有使用普通的bool类型作为返回类型,而是使用了这个类,这意味着我无法再编译这样的东西:

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

很好:通过让编译器为我做了很多艰苦的工作,它使重构在大量代码库上易于管理。所以现在我已经完成了我的重构,我非常希望保持这个类并且继续使用它,因为它为我们提供了额外的安全级别,内置bool类型没有。

然而,有一个“问题”阻止我这样做。目前我们在代码中大量使用ternary operator,问题是如果没有显式的强制转换,它与这个新类不兼容:

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

如果我可以“解决”这个问题,以便我可以无缝地使用我的类,我可能会继续在整个代码库中使用它。有谁知道这个问题的解决方案?或者只是不可能做我想做的事情?

6 个答案:

答案 0 :(得分:2)

在条件运算符的上下文中,表达式的类型是最后两个操作数的公共类型。确定这种常见类型的完整规则有点复杂,但是你的情况恰好是微不足道的:如果两个可能的返回值中的一个是类类型,则另一个值必须具有相同的类,并且公共类型显然也是类。

这意味着如果其中一个操作数是TypesafeBool,那么另一个操作数也必须是。

现在你真正试图解决的问题已经解决了。诀窍不是提供课程;而是使用typedef。例如,请参阅safe bool

答案 1 :(得分:1)

我不知道无缝的方式,三元运算符对其使用有一些限制......

但是,为什么不定义两个常量?

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

然后:

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

当然,由于我使用大写以避免重复使用保留字,因此它有点不正统:)

答案 2 :(得分:1)

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

但要注意,在C ++中,拥有一个可以转换为bool的类被认为是非常危险的。你被警告: - )

你可以在那里阅读,SafeBool

您应该在所有三元测试中明确地调用TypesafeBool :: True()。

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

答案 3 :(得分:0)

是否可以使TypesafeBool的构造函数显式化?当然,现在必须使用

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

答案 4 :(得分:0)

你能使用一个赋值操作符来接受一个bool作为外部参数,还有一个接受TypesafeBool的操作符?可能需要尝试一下......

答案 5 :(得分:0)

很好的尝试,但是如果您的代码库很大,那么最好使用静态检查程序(如PC-Lint)来查找隐式bool< - > int转换。