ORNEW

C++でカリー化

Share on Facebook
Pocket

この記事は2015年の記事を移植したものです。


こんな記事を見つけた。

C++ でカリー化関数を書いてみる(2変数限定)

無駄が多い。C++14なら5行で実装できる。

std::functionは不要だ。std::functionはType Erasureされてしまい呼び出しの最適化が効かないのでカリー化には向かない。今回書いたコードは三引数以上も対応している。

template< typename F >
auto curry( F f )
{
  return [ f ]( auto a ){ return [ f, a ]( auto... args ){ return f( a, args... ); }; };
}

使用例

#include <iostream>
int main()
{
  auto f1 = curry( []( int a, int b ){ return a + b; });
  auto f2 = f1( 10 );
  std::cout << f2( 20 ) << std::endl;
  auto f3 = curry( []( int a, int b ){ return a + b; } )( 10 );
  std::cout << f3( 20 ) << std::endl;
  auto f4 = curry( []( int a, int b, int c ){ return a + b + c; } );
  auto f5 = f4( 10 );
  std::cout << f5( 20, 30 ) << std::endl;
  auto f6 = curry( []( int a, int b, int c ){ return a + b + c; } );
  auto f7 = f6( 10 );
  auto f8 = curry( f7 );
  auto f9 = f8( 20 );
  std::cout << f9( 30 ) << std::endl;

  auto sum = curry( []( auto... args ){ return fold_left( args... ); } )( []( auto l, auto r ){ return l + r; } );
  std::cout << sum( 1, 2, 3, 4, 5 ) << std::endl;
}

fold_leftは、以前の記事で実装した畳み込み関数。

C++で畳み込み

PF版。

template< typename F >
auto curry( F&& f ){
  return [ &f ]( auto&&... a ){
      return [ &f, &a... ]( auto&&... args ){
          return f( std::forward<decltype(a)>(a)..., std::forward<decltype(args)>(args)... ); }; };
}