Синтаксис шаблонов С++ с параметрами типа функции
Я использую синтаксис, подобный этому для указателей на функции
int (*pointer_name) (float, char *);
void call_function (void (*)(int), int);
В некоторых функциональных библиотеках С++ 03 я вижу типы, используемые таким образом:
abc::function<void(*)(int,float)> f;
В С++ 11 std::function
Я вижу тип, указанный таким образом
std::function<void(int,float)> f;
Отсутствует (*)
. Почему?
С++ 03 function<T>
имеет T
идентичный тип соответствующему указателю функции. Легко представить себе реализацию.
std::function
в С++ 11 поддерживается усовершенствованиями основного языка. Были ли расширены типы шаблонов шаблонов для размещения возможности вызова?
Ответы
Ответ 1
std::function
(и его вдох, boost::function
) не только сохраняют указатели на функции. Он также может хранить объекты функции. В этом смысле передача сигнатуры функции в качестве параметра шаблона аналогична тому, как интеллектуальный указатель обычно принимает тип указателя в качестве параметра шаблона, а не тип указателя!
Контрастность:
int* p; // indirection to an object of type int
std::unique_ptr<int> q; // indirection to an object of type int
с
typedef void signature_type(); // a function type
// indirection to something callable with signature_type as a signature
// i.e. f() has type void
// only work for freestanding functions however
signature_type* f;
// indirection to something callable with signature_type as a signature
// i.e. g() has type void
// not restricted to function pointers!
std::function<signature_type> g;
Это полезное соглашение.
Ответ 2
Здесь нет ничего волшебного, тип
void(int,float)
- тип функции без имен. Он соответствует функции типа void g(int x, float y)
.
С помощью шаблонов вам не нужно использовать указатели на функции, вы также можете использовать типы функций.
Ответ 3
Как и в случае с другими элементами, функции имеют тип, и вы можете использовать либо тип, либо указатель на тип в разных контекстах. Отсутствующий (*)
, который вы ожидаете, - это просто синтаксис указателя.
int (*pointer_name) (float, char *);
typedef int my_function_type(float,char*);
my_function_type * pointer_name2;
Типы pointer_name
и pointer_name2
одинаковы: указатель на функцию, которая возвращает int
, и принимает два аргумента типов float
и char*
. Обратите внимание, что это точно эквивалентно другим типам, таким как int
, с той разницей, что вы не можете объявить переменную функцией типа, только указателем на функцию.
Интерфейс std::function
(или boost::function
) просто берет подпись функции. Аргумент типа не является указателем на функцию, а скорее типом функции (например, my_function_type
в приведенном выше коде)
Ответ 4
Типы функций не являются новыми в С++ 11 (см. 8.3.5 на С++ 98). IIRC, улучшение по сравнению с тем, что TR1 и boost обеспечивают function
, весьма незначительны.