Мне было интересно, как правильно проверить std::function
, пуст ли. Рассмотрим этот пример:
class Test {
std::function<void(int a)> eventFunc;
void registerEvent(std::function<void(int a)> e) {
eventFunc = e;
}
void doSomething() {
...
eventFunc(42);
}
};
Этот код отлично компилируется в MSVC, но если я позвоню doSomething()
без инициализации, eventFunc
код явно выйдет из строя. Это ожидалось, но мне было интересно, какова ценность eventFunc
? Отладчик говорит 'empty'
. Поэтому я исправил это, используя простой оператор if:
void doSomething() {
...
if (eventFunc) {
eventFunc(42);
}
}
Это работает, но мне все еще интересно, каково значение неинициализированного std::function
? Я хотел бы написать, if (eventFunc != nullptr)
но std::function
это (очевидно) не указатель.
Почему чистый, если работает? Что за магия стоит за этим? И правильно ли это проверить?
c++
c++11
std-function
НайтЭлфик
источник
источник
eventFunc
это не лямбда; этоstd::function
. Вы можете хранить лямбды вstd::function
s, но это не одно и то же.Ответы:
Вы проверяете не пустую лямбду, а то,
std::function
есть ли в ней вызываемая цель. Проверка четко определена и работает, поэтомуstd::function::operator bool
допускает неявное преобразованиеbool
в контекст, в котором требуются логические значения (например, условное выражение вif
операторе).Кроме того, понятие пустой лямбды не имеет смысла. За кулисами компилятор преобразует лямбда-выражение в
struct
(илиclass
) определение, при этом переменные, которые вы записываете, сохраняются как члены данных этогоstruct
. Также определен оператор вызова публичной функции, который позволяет вам вызывать лямбду. Так что же будет за пустая лямбда?Вы также можете написать,
if(eventFunc != nullptr)
если хотите, это эквивалентно коду, который у вас есть в вопросе.std::function
определяетoperator==
иoperator!=
перегружает для сравнения сnullptr_t
.источник
== nullptr
не то же самое? Похоже, что для==
оператора должна быть перегрузка, из-за которой «пустой»std::function
сравниваетсяtrue
сnullptr
: cplusplus.com/reference/functional/function/operatorsnullptr
будет тоже работать,if(eventFunc != nullptr)
эквивалентноif(eventFunc)
указанному выше вопросу.std::function::operator bool
не позволяет неявное преобразование вbool
. Вexplicit
конце концов, он отмечен , но стандарт делает исключение для определенных языковых конструкций, которые ожидают логические выражения, называя их «контекстно преобразованными в логические». Вы можете найти соответствующий фрагмент стандартного языка и объяснение здесь: chris-sharpe.blogspot.com/2013/07/…explicit
, поэтому я был осторожен, чтобы указать, что позволяет неявное преобразованиеbool
в контекстах, где требуются логические значения . Именно это и происходит в рассматриваемом коде.Проверьте здесь http://www.cplusplus.com/reference/functional/function/operator_bool/
пример
// function::operator bool example #include <iostream> // std::cout #include <functional> // std::function, std::plus int main () { std::function<int(int,int)> foo,bar; foo = std::plus<int>(); foo.swap(bar); std::cout << "foo is " << (foo ? "callable" : "not callable") << ".\n"; std::cout << "bar is " << (bar ? "callable" : "not callable") << ".\n"; return 0; }
Выход
источник
swap()
. Я думал, что результат был обратным, пока не понял это.(Позвольте мне дать четкий ответ.)
Вы можете проверить
std::function
, пуст ли a с помощьюstd::function::operator bool
.пример
#include <iostream> #include <functional> int main () { std::function<int(int,int)> foo = std::plus<int>();//assigned: not empty std::function<int(int,int)> bar;//not assigned: empty std::cout << "foo is " << (foo ? "not empty" : "empty") << ".\n"; std::cout << "bar is " << (bar ? "not empty" : "empty") << ".\n"; return 0; }
Выход
источник