0

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?

SE Does Not Like Dissent
  • 1,767
  • 3
  • 16
  • 36
  • 1
    Why does a person put one question in the title, and then a quite different one in the text? Not to mention *two* such very different questions? – Cheers and hth. - Alf Oct 09 '11 at 15:15
  • What's the question? `bool_type` is a pointer-to-member-function, pointing to a function of type `void Testable::some_function() const`. There's no confusion "due to bracketing" (although the C++ declaration syntax is not exactly the epitome of beauty). – Kerrek SB Oct 09 '11 at 15:16
  • I never said the word confusion, I just said it wasn't easy to deduce (Testable::*bool_type) would, on first glance, appear to be a pointer to a variable called bool_type. Except it's not, given the typedef implies the last word used is typedef after everything preceeding it. Even though it's bracketed (which runs contrary to precedence). – SE Does Not Like Dissent Oct 09 '11 at 15:22
  • @Alf Point is, why is the replacement for bool_type not working? And also, I don't see how it's different from the title (What is going on here? = How does the safe bool idiom work?; Why is it generating those complaints = how does the bool_type work). I just think you're being pedantic. – SE Does Not Like Dissent Oct 09 '11 at 15:24
  • @SSight3: the title question is about an anti-pattern (using evil implicit conversions while using rube goldberg like technique to avoid one particular pitfall), while the questions in the text are concerned with C++ syntax only. – Cheers and hth. - Alf Oct 09 '11 at 16:25
  • @Alf: I wrote the title. Nothing to do with 'anti-patterns' or whatever - just how exactly does it work (in the sense of an incredulous question). Only on stack overflow can I get two seasoned programmers debate syntax of a question rather than answer the question, whilst another one actually answers the question without needing comments... – SE Does Not Like Dissent Oct 09 '11 at 17:34

1 Answers1

3

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.

Bo Persson
  • 90,663
  • 31
  • 146
  • 203