Подобно массивам (см. раздел 6.2.4), нельзя определить параметры типа функции, но можно создать параметр, являющийся указателем на функцию. Как и в случае с массивами, можно создать параметр, который выглядит как тип функции, но обрабатывается как указатель:
//
//
void useBigger(const string &s1, const string &s2,
bool pf(const string&, const string&));
//
//
void useBigger(const string &s1, const string &s2,
bool (*pf)(const string&, const string&));
При передаче функции как аргумента это можно сделать непосредственно. Аргумент будет автоматически преобразован в указатель:
//
//
useBigger(s1, s2, lengthCompare);
Как можно заметить в объявлении функции useBigger()
, написание указателей на тип функций быстро становится утомительным. Псевдонимы типа (см. раздел 2.5.1), а также спецификатор decltype
(см. раздел 2.5.3) позволяют упростить код, который использует указатели на функции:
//
typedef bool Func(const string&, const strings);
typedef decltype(lengthCompare) Func2; //
//
typedef bool(*FuncP)(const string&, const string&);
typedef decltype(lengthCompare) *FuncP2; //
Здесь при определении типов использовано ключевое слово typedef
. И Func
, и Func2
являются типами функций, тогда как FuncP
и FuncP2
— типы указателя. Следует заметить, что спецификатор decltype
возвращает тип функции; автоматического преобразования в указатель не происходит. Поскольку спецификатор decltype
возвращает тип функции, при необходимости получить указатель следует добавить символ *
. Можно повторно объявить функцию useBigger()
, используя любой из этих типов:
//
void useBigger(const string&, const string&, Func);
void useBigger(const string&, const string&, FuncP2);
Оба объявления объявляют ту же функцию. В первом случае компилятор автоматически преобразует тип функции, представленный именем Func
, в указатель.
Подобно массивам (см. раздел 6.3.3), нельзя возвратить тип функции, но можно возвратить указатель на тип функции. Точно так же тип возвращаемого значения следует писать как тип указателя; компилятор не будет автоматически рассматривать тип возвращаемого значения функции как соответствующий тип указателя. Как и при возвращении массива, безусловно, проще всего объявить функцию, которая возвращает указатель на функцию, при помощи псевдонима типа:
using F = int(int*, int); //
using PF = int(*)(int*, int); //
Здесь для определения F
как типа функции и PF
как указателя на тип функции было использовано объявление псевдонима типа (см. раздел 2.5.1). Имейте в виду, что в отличие от параметров, имеющих тип функции, тип возвращаемого значения не преобразуется автоматически в тип указателя. Следует явно определить, что тип возвращаемого значения является типом указателя:
PF f1(int); //
//
F f1(int); //
F *f1(int); //
//
Конечно, функцию f1()
также можно объявить непосредственно:
int (*f1(int))(int*, int);