Почему std::function неявно не преобразуется в bool в С++ 11?

Рассмотрим следующий код.

#include <functional>

int main(void)
{
    std::function<void()> f1;
    if (f1) { /* ok */
        ...
    }

    bool b = f1; /* compile-error */
    bool B = !f1; /* ok */
    ...
}

std::function<> неявно преобразуется в bool в некоторых случаях, но не во всех. Присвоение его bool-переменной не работает, тогда как результат операции или его использование в if()-операторе в порядке.

Почему это так? Кажется, мы должны выполнить над ним логическую операцию, тогда преобразование сработает.

Что я сделал, чтобы заставить работать линию b = f1, так это старый добрый двойной удар: !!. В таком современном C++-коде это выглядит антиквариатом.

EDIT: это также компилируется:

bool b = f1 || f1; /* OK */

person Patrick B.    schedule 20.09.2016    source источник
comment
Потому что оператор bool помечен как явно заданный. См. en.cppreference.com/w/cpp/utility/functional/function. /   -  person Sebastian Hoffmann    schedule 20.09.2016
comment
@wasthishelpful Это тот же ответ, но не тот же вопрос. ИМХО   -  person Patrick B.    schedule 20.09.2016
comment
Наш ответ здесь лучше.   -  person Patrick B.    schedule 20.09.2016
comment
Обратите внимание, что bool b{f1}; и bool b(f1); работают.   -  person Quentin    schedule 20.09.2016


Ответы (1)


Обратите внимание, что std::function::operator bool — это explicit преобразование функция, неявное преобразование не допускается. Так что bool b = f1; не сработает. (Явное преобразование будет хорошо работать, если вы используете static_cast, например bool b = static_cast<bool>(f1);.)

использование его в if()-операторе допустимо.

При использовании с if, operator! или operator|| вступают в силу контекстные преобразования. , и будет рассмотрена функция явного преобразования.

(начиная с С++ 11)

В следующих пяти контекстах ожидается тип bool, и последовательность неявного преобразования строится, если объявление bool t(e); правильно сформировано. то есть рассматривается явная определяемая пользователем функция преобразования, такая как explicit T::operator bool() const;. Такое выражение e называется контекстно преобразуемым в bool.

  • управляющее выражение if, while, for;
  • логические операторы !, && и ||;
  • условный оператор ?:;
  • static_assert;
  • noexcept.
person songyuanyao    schedule 20.09.2016
comment
Таким образом, существуют неявные, явные и контекстно-неявные преобразования, даже если запрашивается явное. Хорошо знать. - person Patrick B.; 20.09.2016
comment
@ Патрик Б. Из-за ! преобразование bool по-прежнему применяется неявно, хотя оно было объявлено explicit. - person Hatted Rooster; 20.09.2016
comment
Подойдет ли для этого !!f1? - person Goosebumps; 27.02.2020
comment
@ Мурашки по коже Да, !f1 приведет к преобразованию f1 в bool, преобразованное значение применяется для !, а затем результат снова применяется для !. - person songyuanyao; 27.02.2020