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

Есть ли прецедент для std:: function, который не покрывается указателями на функции, или это просто синтаксический сахар?

Обозначение для std:: function довольно хорошо по сравнению с указателями на функции. Однако, кроме этого, я не могу найти вариант использования, где он не может быть заменен указателями. Так это просто синтаксический сахар для указателей функций?

4b9b3361

Ответ 1

std::function<> дает вам возможность инкапсулировать любой тип вызываемого объекта, чего не может сделать указатель на функцию (хотя верно, что несобранные lambdas могут быть преобразованы в указатели на функции).

Чтобы дать вам представление о гибкости, которую вы можете достичь:

#include <functional>
#include <iostream>
#include <vector>

// A functor... (could even have state!)
struct X
{
    void operator () () { std::cout << "Functor!" << std::endl; }
};

// A regular function...
void bar()
{
    std::cout << "Function" << std::endl;
}

// A regular function with one argument that will be bound...
void foo(int x)
{
    std::cout << "Bound Function " << x << "!" << std::endl;
}

int main()
{
    // Heterogenous collection of callable objects
    std::vector<std::function<void()>> functions;

    // Fill in the container...
    functions.push_back(X());
    functions.push_back(bar);
    functions.push_back(std::bind(foo, 42));

    // And a add a lambda defined in-place as well...
    functions.push_back([] () { std::cout << "Lambda!" << std::endl; });

    // Now call them all!
    for (auto& f : functions)
    {
        f(); // Same interface for all kinds of callable object...
    }
}

Как обычно, смотрите здесь живой пример. Помимо всего прочего, это позволяет реализовать Command Pattern.

Ответ 2

std::function предназначен для представления любого типа вызываемого объекта. Существует много вызываемых объектов, которые никак не могут быть представлены указателем функции.

  • Функтор:

    struct foo {
      bool operator()(int x) { return x > 5; }
    };
    
    bool (*f1)(int) = foo(); // Error
    std::function<bool(int)> f2 = foo(); // Okay
    

    Вы не можете создать экземпляр foo и сохранить его в указателе функции bool(*)(int).

  • Лямбда с лямбда-захватом:

    bool (*f1)(int) = [&](int x) { return x > y; }; // Error
    std::function<bool(int)> f2 = [&](int x) { return x > y; }; // Okay
    

    Однако, лямбда без захвата может быть преобразована в указатель функции:

    Тип замыкания для лямбда-выражения без лямбда-захвата имеет публичную не виртуальную неявную функцию преобразования const, чтобы указатель на функцию, имеющую тот же параметр и возвращаемые типы, что и оператор вызова функции замыкания. Значение, возвращаемое этой функцией преобразования, должно быть адресом функции, которая при вызове имеет тот же эффект, что и при вызове оператора вызова функции закрытия.

  • Реализованные вызываемые возвращаемые значения:

    bool foo(int x, int y) { return x > y; };
    
    bool (*f1)(int) = std::bind(&foo, std::placeholders::_1, 5); // Error (probably)
    std::function<bool(int)> f2 = std::bind(&foo, std::placeholders::_1, 5); // Okay
    

    std::bind Возвращаемое значение - объект, определяемый реализацией. Только то, как этот объект может использоваться, определяется стандартом, а не его типом.