Я не могу найти хороший способ определить универсальные функции высшего порядка, принимающие универсальные функции в качестве аргументов. Например, возьмем эту попытку для одной из самых простых таких функций:
template<typename F, typename A>
auto apply(F f, const A& a) -> decltype(f(a)){return f(a);}
Конечно, это работает как задумано, когда используется с не шаблонными функциями. Но если у меня есть, например
template<typename A>
A id(const A& a){return a;}
затем
int a = 10;
int b = apply(id, a);
не будет работать, так как id
ожидает параметр шаблона. Я мог бы просто написать id<int>
чтобы заставить его работать, но это как бы отрицательно сказывается на цели (как я понимаю, это означает, что если бы я хотел написать «фильтр», мне пришлось бы написать отдельное определение для каждой универсальной функции предиката). С помощью std::function
или указатели на функции не помогли. Кроме того, я попытался сделать версию шаблона шаблона apply
, но я получаю различные ошибки компилятора, когда я пытаюсь использовать его:
template<template<typename> class F, typename A>
auto apply2(F<A> f, const A& a)-> decltype(f(a)){return f(a);}
Лучшее, что я придумал, было следующее:
struct Id{
template<typename A>
static A func(const A& a){return a;}
};
template<typename F, typename A>
auto apply(A a)-> decltype(F::func(a)){return F::func(a);}
Это немного уродливо, но теперь, по крайней мере, я могу на самом деле параметризоваться с помощью функции.
Итак, есть ли лучший способ сделать универсальные функции, принимающие универсальные функции в качестве аргументов?
Этот «функтор» работает с вашей первой версией заявки.
struct id
{
template<typename A>
A operator ()(const A& a) {return a;}
};
потом
int b = apply(id(), a); // with extra parenthesis to construct the struct.
В C ++ 11 лучшее, что вы можете сделать, это использовать struct
с оператором вызова шаблонной функции:
struct ID {
template <typename T>
void operator()(T arg) const {
...
}
};
Причина, по которой это предпочтительнее функции [указатель], потому что она, скорее всего, будет встроенной. С C ++ 14 вы можете использовать лямбды:
[](auto arg){ ... }
это просто милая версия, чтобы написать struct
выше.