2013-09-04 2 views
1

Я не могу найти хороший способ определить общие функции более высокого порядка, используя общие функции в качестве аргументов. Например, возьмем эту попытку на одном из самых простых таких функций там:Общие функции, принимающие общие функции как аргументы

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);} 

Это немного уродливо, но теперь, по крайней мере, я могу фактически параметризовать функцию.

Итак, есть ли лучший способ делать общие функции, используя общие функции в качестве аргументов?

+0

Вместо того, чтобы писать 'id ' не могли бы вы вместо этого применить (id '? (вероятно, я не понимаю большую картинку, но решил, что я спрошу). – WhozCraig

ответ

3

Этот «функтор» работает с вашей первой версией приложения.

struct id 
{ 
    template<typename A> 
    A operator()(const A& a) {return a;} 
}; 

позже

int b = apply(id(), a); // with extra parenthesis to construct the struct. 
+0

Спасибо, это кажется мне достаточно хорошим. –

1

В C++ 11 лучшего, что вы можете сделать, это использовать struct с Шаблонным оператором вызова функции:

struct ID { 
    template <typename T> 
    void operator()(T arg) const { 
     ... 
    } 
}; 

Причины этого является preferrable к функция [указатель], поскольку она скорее всего будет встроена. С C++ 14 можно использовать лямбды:

[](auto arg){ ... } 

, который просто милый вариант, чтобы написать struct выше.

Смежные вопросы