Подтвердить что ты не робот

Как правильно проверить, является ли 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 (очевидно) не является указателем.

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

4b9b3361

Ответ 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

.