РЕДАКТИРОВАТЬ :Я использую карри ниже, но мне сообщили, что это частичное применение.
Я пытался понять, как можно написать функцию карри на C++, и я действительно понял это!
#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... ); };
}
И я также написал версию для лямбда-выражений.
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 )каким-то образом мою лямбду неявно построить стандартную ::функцию? Я боюсь, что текущая версия нарушает правило наименьшего удивления, когда f не является свободной функцией. Особенно раздражает то, что не существует функции make _или аналогичной функции типа -, о которой я знаю. На самом деле, моим идеальным решением был бы просто вызов std ::bind, но я не уверен, как его использовать с вариативными шаблонами.
PS :Буста нет, пожалуйста, но я соглашусь.
РЕДАКТИРОВАТЬ :Я уже знаю о привязке std ::. Я бы не писал эту функцию, если бы std ::bind делал именно то, что я хотел, с лучшим синтаксисом. Это должно быть более частным случаем, когда он связывает только первый элемент.
Как я уже сказал, мое идеальное решение должно использовать связывание, но если бы я хотел использовать это, я бы использовал это.