Кто-то упомянул указатели на функции (и почему вы должны использовать if
). Что ж, еще лучше: используйте вместо этого функторы, они встроены и обычно имеют ноль накладных расходов . Функтор - это структура (или класс, но обычно первый), который перегружает оператор ()
и экземпляры которого могут использоваться как обычная функция:
template <typename T>
struct add {
operator T ()(T const& a, T const& b) const { return a + b; }
};
int result = add<int>()(1, 2);
Они могут использоваться почти в любом контексте, где может использоваться обычная функция или указатель на функцию. Они обычно происходят от std::unary_function
или std::binary_function
, но это часто не является необходимым (и фактически делается только для наследования некоторых полезных typedef
с).
EDIT Явная квалификация типа <int>
необходима в приведенном выше коде. Вывод типа работает только для вызовов функций, но не для создания экземпляров. Однако его часто можно опустить, используя вспомогательную функцию make
. Это делается в STL за pair
с:
template <typename T1, typename T2>
pair<T1, T2> make_pair(T1 const& first, T2 const& second) {
return pair<T1, T2>(first, second);
}
// Implied types:
pair<int, float> pif = make_pair(1, 1.0f);
Кто-то упомянул в комментариях, что функторы иногда называют «функционоидами». Да иш - но не совсем. На самом деле, «функтор» - это (несколько странное) сокращение от «функциональный объект». Функциональный объект концептуально похож, но реализуется с помощью виртуальных функций (хотя иногда они используются как синонимы). Например, функционал может выглядеть так (вместе с необходимым определением интерфейса):
template <typename T, typename R>
struct UnaryFunctionoid {
virtual R invoke(T const& value) const = 0;
};
struct IsEvenFunction : UnaryFunctionoid<int, bool> {
bool invoke(int const& value) const { return value % 2 == 0; }
};
// call it, somewhat clumsily:
UnaryFunctionoid const& f = IsEvenFunction();
f.invoke(4); // true
Конечно, это теряет любое преимущество в производительности, которое имеет функтор из-за вызова виртуальной функции. Поэтому он используется в другом контексте, который фактически требует полиморфной (с сохранением состояния) функции времени выполнения.
В C ++ FAQ есть больше, чтобы сказать на эту тему.