Могут ли функторы всегда заменять обратные вызовы - PullRequest
0 голосов
/ 29 мая 2020

В C ++ могут ли функторы всегда заменять обратные вызовы? Или бывают случаи, когда нужны "обычные" обратные вызовы? Т.е. каждая функция, которая принимает указатель на функцию, принимает вместо этого функтор, имеющий те же аргументы и возвращаемое значение, что и указатель функции?

1 Ответ

1 голос
/ 29 мая 2020

Традиционные C указатели на функции не могут быть заменены с помощью любого функтора. Таким образом, структуры с перегрузками operator() или лямбда-выражения с переменными захвата работать не будут. См. Следующий код:

#include <functional>

// this function takes a void() function pointer
void run_callback(void(*callback)()) {
    callback();
}

// this function takes a std::function
void run_function(std::function<void()> fun) {
    fun();
}

struct Callable {
    void operator()();
};

int main() {
    int x;
    run_callback([](){});     // OK
    run_callback([x](){});    // ERROR, we are not allowed to capture x
    run_callback(Callable{}); // ERROR, can't convert Callable to function pointer

    run_function([](){});     // OK
    run_function([x](){});    // ALSO OK
    run_function(Callable{}); // ALSO OK
}

Если вам нужно решение, которое работает для чего угодно, от указателей на функции до лямбда-выражений / функторов, используйте std::function.

C указатели на функции необходимо при вызове C API из C ++.

C указатели на функции также лучше подходят для приложений, критичных к производительности. std::function может принимать что угодно, потому что внутри он обертывает указатели на функции и функторы в класс-оболочку polymorphi c. Для этого требуется вызов виртуальной функции, а это означает, что std::function необходимо разыменовать указатель, прежде чем он узнает, что вызывать. Также std::function может быть пустым. В результате ему необходимо проверять каждый вызов, является ли он пустым, и выдает std::bad_function_call, если это так.

...