#c #safe-bool-idiom
#c #safe-bool-idiom
Вопрос:
Мне указали на «безопасную идиому bool», и после попытки расшифровать, что происходит (объяснение, предоставленное на сайте, было недостаточным, чтобы дать мне понимание того, почему это работает), я решил попытаться разобрать следующий код и попытаться максимально упростить егонасколько это возможно. Сайт предоставил код ниже:
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 ?
amp;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 ?
amp;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 ?
amp;Testable::this_type_does_not_support_comparisons : 0;
}
И превратите его в:
operator void Testable::* () const //Same as bool_type, right?
{
return ok_==true ?
amp;Testable::this_type_does_not_support_comparisons : 0;
}
Это порождает следующие жалобы:
ошибка: ожидаемый идентификатор перед «*»
ошибка токена: «<недопустимый оператор>» объявлен как функция, возвращающая функцию
Таким образом, мои вопросы:
Почему он генерирует эти жалобы, если ‘void (Testable::*) действительно является typedef для bool_type ?
И
Что здесь происходит?
Комментарии:
1. Почему человек ставит один вопрос в заголовок, а затем совсем другой в тексте? Не говоря уже о двух таких очень разных вопросах?
2. В чем вопрос?
bool_type
это указатель на функцию-член, указывающий на функцию типаvoid Testable::some_function() const
. Нет никакой путаницы «из-за брекетинга» (хотя синтаксис объявления C не совсем воплощение красоты).3. Я никогда не говорил слово путаница, я просто сказал, что это нелегко вывести (Testable::* bool_type), на первый взгляд, будет выглядеть как указатель на переменную с именем bool_type . За исключением того, что это не так, учитывая, что typedef подразумевает, что последнее используемое слово — typedef после всего, что предшествует ему. Даже если он заключен в квадратные скобки (что противоречит приоритету).
4. @Alf Вопрос в том, почему замена bool_type не работает? А также я не понимаю, чем она отличается от заголовка (что здесь происходит? = Как работает безопасная идиома bool?; Почему она генерирует эти жалобы = как работает bool_type). Я просто думаю, что ты педантичен.
5. @SSight3: заголовок вопроса касается антишаблона (с использованием злых неявных преобразований при использовании метода, подобного методу Рубе Голдберга, чтобы избежать одной конкретной ошибки), в то время как вопросы в тексте касаются только синтаксиса C .
Ответ №1:
Ваши рассуждения здесь ошибочны
operator void Testable::* () const //Same as bool_type, right?
Это неверно. Тип bool_type, как сообщает нам компилятор в сообщении об ошибке:
‘void (проверяемый::*)()const’
Итак, чтобы заменить его в операторе, вам понадобится что-то вроде
operator (void (Testable::*)() const) () const
если это вообще возможно! Посмотрите, почему даже уродливый typedef является улучшением?
В C 11 у нас также есть новая конструкция explicit operator bool()
, которая избавляет нас от этого уродства.
Комментарии:
1. Позвольте мне угадать, explicit заставляет его работать только для bools? Умная идея. И спасибо, что вы действительно ответили на вопрос.
2.
s/answering the question/making a really good guess at what the question was/