Как работает безопасный bool idiom bool_type (и безопасный bool idiom)? - PullRequest
0 голосов
/ 09 октября 2011

Мне указали на «безопасную идиотизму», и после попытки расшифровать происходящее (объяснения , представленного на сайте , было недостаточно, чтобы дать мне понимание почему работает), я решил попытаться разобрать следующий код и попытаться максимально упростить его.Сайт предоставил код ниже:

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;

Можно (не так легко из-за заключения в скобки) вывести это typedef типа 'void Testable :: *', который представляет 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 'to' 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 :: *) действительно является typedef для bool_type?

И

Что здесь происходит?

1 Ответ

3 голосов
/ 09 октября 2011

Ваши рассуждения здесь неверны

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(), чтобы спасти нас от этого уродства.

...