2

我最近一直在进行大规模的重构,我正在更改很多代码以返回布尔值而不是显式的返回代码。为了帮助这种重构,我决定尽可能依靠编译器,让它告诉我需要更改代码的地方。我通过引入以下类来做到这一点(有关其工作原理的详细信息,请参见此处)

///
/// 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类型所没有的额外安全级别。

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

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

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

4

6 回答 6

2

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

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

现在你真正想要解决的问题已经解决了。诀窍是不提供课程;而是使用 typedef。参见例如安全 bool

于 2010-08-20T09:41:34.947 回答
1

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

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

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

接着:

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

当然,这有点不正统,因为我使用大写来避免重复使用保留字:)

于 2010-08-20T09:05:17.390 回答
1
      class CCastableToBool
      {  
      public:
         // ...
         operator bool() const
         {  
           //...
           {
              return true;
           } 
           //...
           return false;
         }  
      private:
         // ...
      }; 

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

你可以在那里读到这个,SafeBool

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

TypesafeBool result = ( 1 == 2 ? SomeFunction().True() : false );
于 2010-08-20T09:28:40.757 回答
0

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

于 2011-02-10T00:40:37.383 回答
0

你可以使用一个将 bool 作为外部参数的赋值运算符,以及一个使用 TypesafeBool 的赋值运算符吗?这可能是要尝试的东西......

于 2010-08-20T17:00:09.873 回答
0

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

TypesafeBool result( 1 == 2 ? b : false );
于 2010-08-20T10:20:00.783 回答