Как правильно проверить, является ли std:: function пустым в С++ 11?
Мне было интересно, как правильно проверить, является ли 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
(очевидно) не является указателем.
Почему чистый, если работает? Какая магия позади? И, правильно ли это проверить?
Ответы
Ответ 1
Вы не проверяете наличие пустой лямбды, но имеет ли std::function
целевую цель, содержащуюся в ней. Проверка корректна и работает из-за std::function::operator bool
, которая допускает неявное преобразование в bool
в контекстах, где требуются логические значения (например, условное выражение в if
).
Кроме того, понятие пустой лямбды на самом деле не имеет смысла. За кулисами компилятор преобразует лямбда-выражение в определение struct
(или class
), а переменные, которые вы записываете, сохраняются как члены данных этого struct
. Также определен оператор вызова публичных функций, который позволяет вам вызывать лямбду. Так что будет пустой лямбдой?
Вы также можете написать if(eventFunc != nullptr)
, если хотите, это эквивалентно коду, который у вас есть в вопросе. std::function
определяет operator==
и operator!=
перегрузки для сравнения с nullptr_t
.
Ответ 2
Отметьте 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;
}
**OUT:**
foo is not callable.
bar is callable
.