安全bool成语bool_type(和安全bool成语)如何工作?

时间:2011-10-09 15:03:01

标签: c++ safe-bool-idiom

我被指向'安全bool成语',在尝试破译正在发生的事情之后(解释supplied on the site不足以让我理解为什么它有效),我决定尝试将以下代码分开,尽可能地尝试简化它。该网站提供了以下代码:

class Testable {
    bool ok_;
    typedef void (Testable::*bool_type)() const;
    void this_type_does_not_support_comparisons() const {}
  public:
    explicit Testable(bool b=true):ok_(b) {}

    operator bool_type() const {
      return ok_==true ? 
        &Testable::this_type_does_not_support_comparisons : 0;
    }
  };

我决定分析'bool_type'的关键基础,因为这似乎是它的核心。给出以下一行:

typedef void (Testable::*bool_type)() const;

可以(不是很容易,由于包围)推断它是'void Testable :: *'的typedef,bool_type代表。通过进行以下修改和函数调用可以进一步证明这一点:

class Testable {
    bool ok_;
    typedef void (Testable::*bool_type)() const;
    void this_type_does_not_support_comparisons() const {}
  public:
    explicit Testable(bool b=true):ok_(b) {}

    bool_type Test; //Added this

    operator bool_type() const {
      return ok_==true ?
        &Testable::this_type_does_not_support_comparisons : 0;
    }
  };

int main()
{
    Testable Test;
    int A = Test.Test; //Compiler will give a conversion error, telling us what type .Test is in the process
}

它允许我们查看bool_type的类型:

  

错误:无法在初始化中将'void(Testable :: *)()const'转换为'int'

这表明它确实是一种'void(Testable :: *)'。

问题出现在这里:

如果我们修改以下功能:

    operator bool_type() const {
      return ok_==true ? 
        &Testable::this_type_does_not_support_comparisons : 0;
    }

然后把它变成:

    operator void Testable::* () const //Same as bool_type, right? 
    {
      return ok_==true ? 
        &Testable::this_type_does_not_support_comparisons : 0;
    }

它会产生以下抱怨:

  

错误:'*'标记之前的预期标识符
  错误:'<无效的运算符>'声明为函数返回函数

我的问题是:

如果'void(Testable :: *)确实是bool_type的typedef,为什么会产生这些投诉?

并且

这里发生了什么?

1 个答案:

答案 0 :(得分:3)

你的推理在这里出错了

operator void Testable::* () const //Same as bool_type, right? 

这不正确。 bool_type的类型是,正如编译器在错误消息中告诉我们的那样:

  

'void(Testable :: *)()const'

因此,要在运算符中替换它,您需要类似

的内容
operator (void (Testable::*)() const) () const

如果有可能的话!看看为什么即使是丑陋的typedef也是一种改进?

在C ++ 11中,我们还有了新的构造explicit operator bool(),以免我们摆脱这种丑陋。