EDIT: я использую карри ниже, но были проинформированы об этом, а не о частичном приложении.
Я пытался выяснить, как написать функцию карри в С++, и я действительно понял это!
#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... ); };
}
И я написал версию для lambdas тоже.
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... ); };
}
Тестирование:
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));
}
Тьфу! Инициализация строки g2 настолько велика, что я мог бы также ее вручную загрузить.
auto g2 = [](int y){ return 2*y; };
Гораздо короче. Но поскольку цель состоит в том, чтобы иметь действительно общую и удобную функцию карри, я мог бы либо (1) написать лучшую функцию, либо (2) каким-то образом моя лямбда неявно построила std:: function? Я боюсь, что текущая версия нарушает правило наименьшего удивления, когда f не является свободной функцией. Особенно раздражает то, что функция make_function или аналогичного типа, о которой я знаю, кажется, существует. Действительно, моим идеальным решением было бы просто вызов std:: bind, но я не уверен, как его использовать с вариативными шаблонами.
PS: Никакого повышения, пожалуйста, но я успокоюсь, если ничего другого.
EDIT: Я уже знаю о std:: bind. Я бы не писал эту функцию, если std:: bind сделал именно то, что я хотел, с лучшим синтаксисом. Это должно быть скорее особым случаем, когда он связывает только первый элемент.
Как я уже сказал, мое идеальное решение должно использовать привязку, но если бы я хотел использовать это, я бы использовал это.