Ответ 1
std::function
является объектом стирания типа. Это означает, что он стирает детали того, как происходят некоторые операции, и предоставляет им единый интерфейс времени выполнения. Для std::function
основными операциями 1 являются копирование/перемещение, уничтожение и "вызов" с помощью operator()
- "оператор вызова как функция".
В менее заумном английском это означает, что std::function
может содержать практически любой объект, который действует как указатель на функцию в том, как вы его вызываете.
Поддерживаемая подпись идет внутри angular скобок: std::function<void()>
принимает нулевые аргументы и ничего не возвращает. std::function< double( int, int ) >
принимает два аргумента int
и возвращает double
. В общем, std::function
поддерживает сохранение любого функционально-подобного объекта, аргументы которого могут быть преобразованы, из его списка аргументов, а возвращаемое значение может быть преобразовано в его возвращаемое значение.
Важно знать, что std::function
и лямбды разные, если совместимы, звери.
Следующая часть строки - лямбда. Это новый синтаксис в С++ 11, добавляющий возможность писать простые функциональные объекты - объекты, которые можно вызывать с помощью ()
. Такие объекты можно стирать по типу и хранить в std::function
за счет некоторых накладных расходов времени выполнения.
[](){ code }
в частности это действительно простая лямбда. Это соответствует этому:
struct some_anonymous_type {
some_anonymous_type() {}
void operator()const{
code
}
};
экземпляр вышеуказанного простого типа псевдо-функции. Фактический класс, подобный описанному выше, "изобретен" компилятором с уникальным именем, определяемым реализацией (часто включая символы, которые не может содержать ни один пользовательский тип) (я не знаю, возможно ли, что вы можете следовать стандарту, не изобретая такой класс, но каждый компилятор, которого я знаю, на самом деле создает класс).
Полный лямбда-синтаксис выглядит следующим образом:
[ capture_list ]( argument_list )
-> return_type optional_mutable
{
code
}
но многие части можно опустить или оставить пустыми. Перехват захвата соответствует как конструктору результирующего анонимного типа, так и его переменным-членам, аргумент аргумента аргумента operator()
и тип возвращаемого значения возвращаемого типа. Конструктор лямбда-экземпляра также вызывается волшебным образом, когда экземпляр создается с помощью capture_list.
[ capture_list ]( argument_list ) -> return_type { code }
в основном становится
struct some_anonymous_type {
// capture_list turned into member variables
some_anonymous_type( /* capture_list turned into arguments */ ):
/* member variables initialized */
{}
return_type operator()( argument_list ) const {
code
}
};
1 Кроме того, RTTI сохраняется (typeid) и включена операция приведения типа к исходному типу.