How does the safe bool idiom bool_type (and the safe bool idiom) work?

☆樱花仙子☆ 提交于 2021-02-17 06:04:47

问题


I was pointed to the 'safe bool idiom', and after trying to decipher what is going on (the explanation supplied on the site was not sufficient enough to grant me understanding of why it works), I decided to try to take the following code apart and make an attempt at simplifying it as much as possible. The site supplied code below:

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;
    }
  };

I decided to analyse the key basis of 'bool_type' given this seems to be what it's centred on. Given the following line:

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

One can (not so easily, due to bracketing) deduce it's a typedef of a type of 'void Testable::*', of which bool_type represents. This can be further demonstrated by making the following modifications and function calls:

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
}

It allows us to see what type bool_type is:

error: cannot convert 'void (Testable::*)()const' to 'int' in initialization

Which shows it is indeed a type of 'void (Testable::*)'.

The issues crops up here:

If we modify the following function:

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

And turn it into:

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

It generates the following complaints:

error: expected identifier before '*' token
error: '< invalid operator >' declared as function returning a function

My questions are thus:

Why is it generating those complaints if 'void (Testable::*) is indeed the typedef for bool_type?

And

What is going on here?


回答1:


Your reasoning goes wrong about here

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

This isn't correct. The type of bool_type is, as the compiler tells us in the error message:

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

So, to replace it in the operator, you would need something like

operator (void (Testable::*)() const) () const

if that is ever possible! See why even the ugly typedef is an improvement?

In C++11 we also have the new construct explicit operator bool() to save us from this ugliness.



来源:https://stackoverflow.com/questions/7704395/how-does-the-safe-bool-idiom-bool-type-and-the-safe-bool-idiom-work

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!