Częściowa aplikacja z C ++ lambda?
EDYCJA: Używam curry poniżej, ale zostałem poinformowany, że jest to raczej aplikacja częściowa.
Próbowałem dowiedzieć się, jak napisać funkcję curry w C ++, a ja to zrozumiałem!
#include <stdio.h>
#include <functional>
template< class Ret, class Arg1, class ...Args >
auto curry( Ret f(Arg1,Args...), Arg1 arg )
-> std::function< Ret(Args...) >
{
return [=]( Args ...args ) { return f( arg, args... ); };
}
Napisałem też wersję dla lambd.
template< class Ret, class Arg1, class ...Args >
auto curry( const std::function<Ret(Arg1,Args...)>& f, Arg1 arg )
-> std::function< Ret(Args...) >
{
return [=]( Args ...args ) { return f( arg, args... ); };
}
Testy:
int f( int x, int y )
{
return x + y;
}
int main()
{
auto f5 = curry( f, 5 );
auto g2 = curry( std::function<int(int,int)>([](int x, int y){ return x*y; }), 2 );
printf("%d\n",f5(3));
printf("%d\n",g2(3));
}
Fuj! Linia inicjująca g2 jest tak duża, że równie dobrze mogłabym ją wyleczyć ręcznie.
auto g2 = [](int y){ return 2*y; };
Znacznie krótszy. Ale ponieważ intencją jest posiadanie naprawdę ogólnej i wygodnej funkcji curry, czy mógłbym (1) napisać lepszą funkcję lub (2) w jakiś sposób moją lambdę do niejawnego skonstruowania funkcji std ::? Obawiam się, że obecna wersja narusza zasadę najmniejszego zaskoczenia, gdy f nie jest funkcją wolną. Szczególnie denerwujące jest to, że żadna funkcja make_function lub podobnego typu, o której wiem, nie istnieje. Naprawdę, moim idealnym rozwiązaniem byłoby wywołanie std :: bind, ale nie jestem pewien, jak go użyć z różnymi szablonami.
PS: Bez podniecenia, proszę, ale załatwię się, jeśli nic więcej.
EDYCJA: Już wiem o std :: bind. Nie pisałbym tej funkcji, gdyby std :: bind zrobił dokładnie to, co chciałem, z najlepszą składnią. Powinien to być szczególny przypadek, w którym wiąże tylko pierwszy element.
Jak już powiedziałem, moim idealnym rozwiązaniem powinno byćposługiwać się bind, ale jeśli chciałbym to wykorzystać, użyłbym tego.