Jak sprawić, by funkcje C ++ 11 pobierające parametry funkcji <> automatycznie akceptowały lambdy

C ++ 11 ma zarówno funkcje lambda, jak i std :: function <>, ale niestety mają różne typy. Jedną z konsekwencji jest to, że nie można bezpośrednio używać lambda w funkcjach wyższego rzędu, takich jak mapa w seplenieniu. Na przykład w poniższym kodzie

 #include <vector>
 #include <functional>
 using namespace std;

 template <typename A,typename B> 
 vector<B> map(std::function<B (A)> f, vector<A> arr) {
       vector<B> res;
       for (int i=0;i<arr.size();i++) res.push_back(f(arr[i]));
       return res;
}

int main () {
    vector<int> a = {1,2,3};
    map([](int x) -> int { return x;},a); //not OK

    auto id_l = [](int x) -> int { return x;};
    map(id_l,a); //not OK;

    function<int (int)> id_f = id_l;
    map(id_f,a); //OK
return 0;
}

, bezpośrednie użycie lambda jak w linii 2 main () nie zadziała.g++ -std=c++11 testfunc.cpp zwraca `... testfunc.cpp: 14: 37: uwaga: 'main () :: __ lambda0' nie pochodzi od 'std :: function'.

Wnioskowanie typu C ++ 11 również nie powiedzie się, ponieważ można zobaczyć, czy przechowuje się lambdę do zmiennej automatycznej, a następnie jej używa, informacje o typie są nadal tracone, prawdopodobnie z powodu wymazania typu i przyczyn małej kary za wydajność (tak jak ja powiedziano:dlaczego funkcje lambda w c ++ 11 nie mają funkcji typu <>?).

To, co działa, to przechowywanie lambda w zmiennej std: function <> i używanie tej zmiennej. Jest to raczej niewygodne i rodzaj porażki w celu wykorzystania lambda w programowaniu funkcjonalnym w C ++ 11. Na przykład, nie można manipulować lambda na miejscu za pomocą rzeczy takich jak bind czy flip, a zamiast tego musi najpierw zapisać lambdę do zmiennej.

Moje pytanie brzmi, czy jest możliwe (i jak) przezwyciężyć ten problem i uczynić linię # 2 main () legal, np. nadpisując niektóre operatory typowania? (Oczywiście oznacza to, że nie obchodzi mnie mała kara za wydajność związana z używaniem / nie używaniem wymazywania typu.)

z góry dziękuję.

--- EDYTOWAĆ ---

Aby wyjaśnić, powód, z którego korzystamstd::function zamiast ogólnego parametru typu dla parametru funkcjonalnego jest tostd::function ma dokładną informację o typie, podczas gdy typowy parametr typu jak wtemplate <typename F> map(F f, ...) nie zawiera informacji o typie. Ponadto, w końcu odkryłem, że każda lambda jest swoim własnym typem. Wymazywanie typu nie było nawet problemem w niezgodności między lambdą a jej dopasowaniemstd::function obiekt.

---Aktualizacja---

Istnieją już dwie odpowiedzi na temat tego, jak sprawić, by funkcja mapy działała powyżej lub jak je ulepszyć. Żeby się upewnić. Moje pytanie nie dotyczy tego, jak tworzyć mapy. Istnieje wiele innych przypadków użycia związanych z użyciem wpisanych parametrów std :: function <>, które, jak sądzę, mogą przynajmniej zwiększyć czytelność kodu i ułatwiać wnioskowanie o typ. Dotychczasowe odpowiedzi dotyczą tego, jak nie używać std :: function <> jako parametrów. Moje pytanie dotyczyło tego, jak stworzyć taką funkcję (za pomocą wpisanych parametrów std :: function <>) automatycznie akceptować lambdę.

- Aktualizacja 2 ---

W odpowiedzi na komentarze, oto przykład praktycznego przypadku, w którym informacje o typie w std :: function <> MOGĄ być użyteczne. Załóżmy, że chcemy zaimplementować odpowiednik C ++fold_right : ('a -> 'b -> 'b) -> 'a list -> 'b -> 'b w OCaml (http://caml.inria.fr/pub/docs/manual-ocaml/libref/List.html).

Z std :: function <> można to zrobić

 //approach#1
 template <typename A,typename B> 
 B fold_right(std::function<B (A, B)> f, vector<A> arr, B b) {
     ...
 }

Z powyższego jasno wynikaf jest i co może lub nie może przyjąć. Być może można również użyć

 //approach#2
 template <typename A,typename B, typename F> 
 auto fold_right2(F f, vector<A> arr, B b) -> decltype(f(???)) {
      ...
 }

Ale staje się to trochę brzydkie, gdy próbujesz dowiedzieć się, co wstawićdecltype. Co dokładnie robif weź i jaki jest właściwy sposób użyciaf? Z punktu widzenia czytelności, przypuszczam, że czytelnik kodu może tylko dowiedzieć się, co to jest f (funkcja lub skalar) i podpis f przez INTERPRETOWANIE implementacji w ciele funkcji.

Tego nie lubię i skąd pochodzi moje pytanie. Jak sprawić, by podejście nr 1 działało wygodnie. Na przykład, jeślif oznacza dodanie dwóch liczb, podejście nr 1 działa, jeśli najpierw utworzysz obiekt funkcji:

std::function<int (int, int)> add = [](int x, int y) -> int { return x + y; }
fold_right(add,{1,2,3},0);

Pomijając problemy z wydajnością, powyższy kod jest niewygodny BECAUSE std :: function nie może zaakceptować lambda. Więc,

fold_right([](int x, int y) -> int { return x + y; },{1,2,3},0);

nie działa obecnie w C ++ 11. Moje pytanie dotyczy konkretnie, czy możliwe jest wykonywanie takich funkcjifold_right zdefiniowane powyżej zaakceptować lambda bezpośrednio. Może to za dużo, na co mam nadzieję. Mam nadzieję, że to wyjaśni pytanie.

questionAnswers(5)

yourAnswerToTheQuestion