我需要找到一个安全的bool习语解决方案。你知道这个练习,我使用的是VS 2012,XCode,GCC,LLVM,各种平台,有些支持C ++ 11显式转换运算符,有些则不支持。我需要一些便携的东西。
我找到了几个,但设计得那么简单,我不得不问,我在这里遗漏了什么吗?
背景(简要):
Web的几个例子提供了高度侵入性的方法(基本上是在给定的类中放置所需的所有内容),或者是使用CRTP的通用方法,但大多数是基于指向成员函数的指针(具有极其不可预测的大小和性能)罚分)。
然后我阅读了关于boost::spirit::classic
安全bool,尝试过,检查过它等等。我喜欢精灵的实现是因为它依赖于指向成员数据的指针而不是指向成员函数的指针(使用编译器) “模糊”版本的解决方法。
所以我认为,指向成员的指针的类型是什么并不重要,实现是有效的,因为除其他外,这些是指向除了我们可能使用的对象之外的任何其他成员的指针
所以,我尝试过这种事情(而且我想知道我是否已经离开或者没事了)
首先:
class SafeBool
{ private: SafeBool() : Value( 0 ) { }
public: int Value;
};
SafeBool
接受boost::spirit
的safe_bool模板的工作,而不会增加驱动用户类的负担。
// pointer to member typedef, made widely available
typedef int SafeBool :: * safe_bool;
// more about why this define in a moment
#define EXPLICIT_OPERATOR_BOOL operator safe_bool
// here is an example user class, some smart pointer or something
template< typename T > class SomeSPtr
{
public: ... other class stuff, obviously
EXPLICIT_OPERATOR_BOOL() const
{ if ( get() ) return &SafeBool::Value;
return 0;
}
};
首先,EXPLICIT_OPERATOR_BOOL
是一个定义,可以在符合C ++ 11的编译器上使用“真实”显式运算符bool,而在VS 2012和旧GCC(或者你有什么),它可以就像在这里一样,转换为运营商safe_bool。
甚至可以使用相关的定义来返回...说
SAFE_BOOL_RETURN( get() )
这可以调整返回逻辑,从根本上使代码可以在现代编译器和旧编译器之间切换(也就是说,对于C ++ 11,定义将解析返回get() != 0
)
现在,这与VS 2012上的精神代码具有相同的基本结果。它允许
SomePtr< AType > p, q; // or some such
if ( p ) { } // this works as expected
同时拒绝像
这样的代码if ( p < q ) // compile time error
if ( p > q ) // ""
但它允许这样:
if ( p == q ) // compiles fine
这与我在许多实现中获得的结果相同,但有些实现了类似的结果:
template< typename T > bool operator ==( const safe_bool & , const T & )
{
SafeBool CantCompareThatType;
return false;
}
template< typename T > bool operator ==( const T &, const safe_bool & )
{
SafeBool CantCompareThatType;
return false;
}
或类似的技巧,即在使用运算符之前不会实例化的模板代码,并且由于SafeBool构造函数是私有的,因此在尝试(p == q)
时会生成错误。
显然,要排除的所有其他运算符(!= ....)等都将按要求进行类似处理(模板函数响应任何具有EXPLICIT_OPERATOR_BOOL
创建函数的类型)。
好的,这是问题所在。我在这里欺骗自己吗?其他实现强加了从模板类派生的负担,并在用户的类中放置类似bool的函数 - 或者将整个事物放入用户类。
在我看来,这种方法使用一个类SafeBool
(它永远不会用于实例化)来提供指向成员的指针,以及一个类型(类本身),安全的bool成语可以在其上在用户类中仅强制使用单个函数时实现,该函数本身模仿C ++ 11显式转换运算符,可能在需要此成语的情况下启用更多可向上移植的代码。
如果我对此错了,请有人阻止我!
答案 0 :(得分:2)
您的技术有效,并作为http://www.artima.com/cppsource/safebool.html之一进行讨论。它将它作为可行的选项进行讨论。它被称为“中毒操作员”,道格拉斯格雷戈尔因发明它而受到赞誉。
我认为真正的safe_bool成语因为更加安全而取得了更大进展。特别是,如果你的safe_bool是int T :: *类型,并且指向T的整数成员的唯一指针是private,那么只有那个类可以生成safe_bool的特定变体,所以更容易证明没有人可以产生不安全的模式。由于任何人都可以使用&amp; SafeBool :: Value的地址,因此“安全性较低。”
病理?也许