Skip to content

Instantly share code, notes, and snippets.

@splinterofchaos
Created January 23, 2013 14:21
Show Gist options
  • Save splinterofchaos/4606174 to your computer and use it in GitHub Desktop.
Save splinterofchaos/4606174 to your computer and use it in GitHub Desktop.
N-ary curry.
#include <iostream>
#include <utility>
using namespace std;
template< class F, class X >
struct Part {
F f = F();
X x;
constexpr Part( F f, X x )
: f(move(f)), x(move(x))
{
}
template< class ... Xs >
constexpr auto operator () ( Xs&& ...xs )
-> decltype( f(x,declval<Xs>()...) )
{
return f( x, forward<Xs>(xs)... );
}
};
template< class F, class X >
constexpr Part<F,X> part( F f, X x ) {
return Part<F,X>( move(f), move(x) );
}
template< class F, class X, class Y, class ...Z >
constexpr auto part( F f, X x, Y y, Z ...z )
-> decltype( part( part(move(f),move(x)), move(y), move(z)... ) )
{
return part( part(move(f),move(x)), move(y), move(z)... );
}
template< class F, size_t N >
struct Nary {
F f;
constexpr Nary( F f ) : f(std::move(f)) { }
constexpr Nary() { }
template< class ...X >
constexpr auto operator () ( X&& ...x )
-> typename std::enable_if <
sizeof...(X) < N,
decltype(part(f,std::declval<X>()...))
>::type
{
return part( f, std::forward<X>(x)... );
}
template< class ...X >
constexpr auto operator () ( X&& ...x )
-> typename std::enable_if<
sizeof...(X) == N,
decltype(f(std::declval<X>()...))
>::type
{
return f( std::forward<X>(x)... );
}
};
template< size_t N, class F >
constexpr Nary<F,N> nary( F f ) {
return Nary<F,N>( std::move(f) );
}
auto add3 = nary<3>(
[]( int x, int y, int z ) { return x + y + z; }
);
int main() {
std::cout << "1 + 2 + 3 = " << add3(1,2,3) << std::endl;
auto add2 = add3( 0 );
std::cout << "1 + 2 = " << add2(1,2) << std::endl;
auto echo = add3( 0, 0 );
std::cout << "1 = " << echo(1) << std::endl;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment