Обозначение для std:: function довольно хорошо по сравнению с указателями на функции. Однако, кроме этого, я не могу найти вариант использования, где он не может быть заменен указателями. Так это просто синтаксический сахар для указателей функций?
Есть ли прецедент для std:: function, который не покрывается указателями на функции, или это просто синтаксический сахар?
Ответ 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
Возвращаемое значение - объект, определяемый реализацией. Только то, как этот объект может использоваться, определяется стандартом, а не его типом.