safe bool idiom

在阅读boost源代码,看到这个词,以前从来没有注意过,使用boost的时候也从来没有留意它,其实它包含了作者的深思熟虑呢。
safe bool idiom的起源来自于这样子的一种用法:if( obj ) { ... },对于obj是built-in类型,那自然行得通,但是对于一个class或者struct就并不总是可以了。当然可以通过这样子的用法来代替:if( obj.is_valid() ){},问题很明显,第一烦琐,第二通用性不够,也许应该使用obj.Valid()或者obj.Empty()之类的,这与template结合起来考虑是尤其是个问题。因此我们希望有一个解决方案是的我们直接可以写下if(obj)这样的语句。
初初一想,这很简单,重载operator bool不就可以了,又或者重载operator void*?是的,这两个方法确确实实使得我们可以使用if(obj)这样的语句了,但是仔细推敲的话就会发现有很多问题。
//---------------------------
//重载operator bool的方法
class Test
{
public:
operator bool()const{return ok_;}
};
但是如果我们写下这样的语句的时候,你可以理解它的行为吗?
Test test;
int tmp = test;
我想你应该发现了一个绝对让所有人抓头的诡异行为。

//----------------------------
//重载operator void*的方法
class Test
{
public:
operator void*()const{ return ok_?this:0;}
};
现在又有一个误用的例子
Test test;
delete test;
看看它会做什么吧。
//----------------------------
//重载operator !的方法
class Test
{
public:
bool operator !()const{return !ok_};
};
现在可以这样来判断了
Test t;
if(!!t){...}
显得有些麻烦,不是吗?

OK,现在我们来看看boost的作法了。
class Test
{
private:
   struct dummy   {void nonnull() {};};
   typedef void (dummy::*safe_bool)();
public:
   operator safe_bool () const{ return (this->empty())? 0 : &dummy::nonnull; }
};
OK,太棒了!我们不能使用delete t;也不能直接写下int tmp = t,除非到int的隐式转换存在;也不需要使用!!t这种c中的技巧(它可以将一个非零的数变成1);看起来几乎是完美了。

但是可能还有一个问题就是似乎你可以写出这样的语句,而且它们是合法的,却没有意义。
Test t1,t2;
if(t1<==t2){....}

下面是另外一种聪明的方法,但是也存在同样的问题
//----------------------------
//一个类似于operator void*的更聪明的方法
class Test
{
private:
class _nested_class{};
public:
operator _nested_class*()const{ reutnr ok_?reinterpret<_nested_class*>this:0;}
};
同样,现在你不可以使用诸如delete test这样的语句了,因为_nested的析构是private

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值