Skip to content

Instantly share code, notes, and snippets.

@splinterofchaos
Last active December 10, 2015 04:28
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
Star You must be signed in to star a gist
Save splinterofchaos/4381376 to your computer and use it in GitHub Desktop.
Generic Lambda fun.
#include <vector>
#include <algorithm>
#include <iostream>
constexpr struct {
// Ignore perfect forwarding. Assume basic types.
template< class X, class Y >
auto operator () ( X x, Y y )
-> decltype(x*y)
{
return x * y;
}
} multObj{};
auto compose =
[]( auto f, auto g )
[=]<class ...X>( X&& ...x )
f( g(std::forward<X>(x)...) );
template< class F > struct Forwarder : F {
constexpr Forwarder( const F& f ) : F(f) { }
};
template< class R, class ...X >
struct Forwarder<R(*)(X...)> {
using type = R(*)(X...);
type f;
constexpr Forwarder( type f ) : f(f) { }
constexpr R operator () ( X... x ) {
return f( std::forward<X>(x)... );
}
};
template< class R, class ...X >
struct Forwarder<R(X...)> : Forwarder<R(*)(X...)>
{
using type = R(*)(X...);
constexpr Forwarder( type f )
: Forwarder<R(*)(X...)>(f)
{
}
};
template< class F, class G >
struct Overloaded : Forwarder<F>, Forwarder<G> {
constexpr Overloaded( const F& f, const G& g )
: Forwarder<F>(f), Forwarder<G>(g)
{
}
};
template< class F > F overload( F&& f ) {
return std::forward<F>(f);
}
template< class F, class G, class ...H,
class O1 = Overloaded<F,G> >
auto overload( const F& f, const G& g, const H& ...h )
-> decltype( overload(O1(f,g),h...) )
{
return overload( O1(f,g), h... );
}
template< class X, class F >
struct UnaryOverload {
F f;
UnaryOverload( const F& f ) : f(f) { }
using result_type = typename std::result_of< F(X) >::type;
result_type operator () ( X x ) const {
return f(x);
}
};
template< class ...X, class F >
auto unary_overload_set( const F& f )
-> decltype( overload(UnaryOverload<X,F>(f)...) )
{
return overload( UnaryOverload<X,F>(f)... );
}
auto cout1 = []( const auto& x ) { std::cout << x; };
struct sequence_tag {};
struct other_tag {};
template< class S > auto get_tag(const S& s) -> decltype( std::begin(s), sequence_tag{} );
template< class S > auto get_tag(...) -> other_tag;
template< class Tag, class F >
struct OverloadTag : F {
constexpr OverloadTag( const F& f ) : F(f) { }
template< class X >
constexpr auto operator () ( X&& x ) const
-> typename std::enable_if <
std::is_same< Tag, decltype(get_tag(x)) >::value,
typename std::result_of< F(X) >::type
>::type
{
return F::operator()( std::forward<X>(x) );
}
operator F() const { return *this; }
};
template< class Tag, class F, class O = OverloadTag<Tag,F> >
O overload_tag( const F& f ) {
return O( f );
}
void print_char( char c ) { std::cout << "'" << c << "'"; }
auto prnt = overload (
// Anything cout is already defined for.
[]( const auto& x )
-> decltype( void(std::cout << x) )
{ std::cout << x; },
// Any STL sequence.
[]<class Sequence>( const Sequence& s )
-> decltype( void(std::begin(s)) )
{
std::cout << "[ ";
for( const auto& x : s )
std::cout << x << ' ';
std::cout << ']';
},
// These are both sequences for which cout is defined.
// Specializing disambiguates this.
unary_overload_set<const char* const,
const std::string&>(
[]( auto&& s ) { std::cout << s; }
)
);
void prnt2_int ( int i ) { std::cout << i; }
void prnt2_char( char c ) { std::cout << c; }
auto prnt2 = overload( prnt2_int, prnt2_char );
auto ycomb_impl = []( auto Y, auto f )
f( [=](auto x) f(x) );
auto ycomb = []( auto f )
ycomb_impl( ycomb_impl, f );
auto fact1 = []( auto f, auto n )
not n ? 1 : f(f,n-1) * n;
auto fact =
[]( int x ) fact1( fact1, x );
//auto factY = ycomb (
// []( auto self )
// [=]( auto n )
// not n ? 1 : self(n-1) * n;
//);
auto fix = []( auto f )
[=]( auto x ) f( f, x );
auto fixed_fact = fix (
[]( auto f, auto n )
not n ? 1 : f(f,n-1) * n
);
auto fixed_fib = fix (
[]( auto f, auto n )
n == 0 ? 0 :
n <= 2 ? 1 :
f(f,n-1) + f(f,n-2)
);
//void f() { fact(4); }
//int twentyFour = fact(4);
//auto twentyFour = fact(4);
using IntToInt = int(*)(int);
IntToInt iToIFact = []( auto x ) not x ? 1 : x * iToIFact(x-1);
#include <tuple>
template< size_t i, class F, class T, class U >
auto zip_tuple_row( const F& f, T&& t, U&& u )
-> decltype( f( std::get<i>(std::forward<T>(t)),
std::get<i>(std::forward<U>(u)) ) )
{
return f( std::get<i>(std::forward<T>(t)),
std::get<i>(std::forward<U>(u)) );
}
template< size_t ...i, class F, class T, class U >
auto zip_tuple( const F& f, T&& t, U&& u )
-> decltype( std::make_tuple( zip_tuple_row<i>(f,std::forward<T>(t),
std::forward<U>(u))... ) )
{
return std::make_tuple( zip_tuple_row<i>(f,std::forward<T>(t),
std::forward<U>(u))... );
}
std::function<bool(unsigned int)> even;
auto odd = []( auto n ) n==0 ? false : even(n-1);
auto even1 = []( auto self, auto odd, auto n )
n == 0 ? true : odd(odd,self,n-1);
auto odd1 = []( auto self, auto even, auto n ) -> bool
n == 0 ? false : even(even,self,n-1);
auto rec_even = []( auto n ) even1( even1, odd1, n );
auto rec_odd = []( auto n ) odd1( odd1, even1, n );
auto surrounder = []( auto pre, auto post )
overload (
[=]( std::string s ) pre + std::move(s) + post
//[=]( char c ) pre + std::string(1,c) + post
);
auto html_start = []( char c ) "<" + std::string(1,c) + ">";
auto html_end = []( char c ) "</" + std::string(1,c) + ">";
auto html_surrounder = []( char c ) surrounder( html_start(c), html_end(c) );
auto html_surround = []( char c, std::string s ) -> std::string
html_surrounder( c )( std::move(s) );
auto bold = []( std::string s ) -> std::string html_surround( 'b', std::move(s) );
auto even_print = []( unsigned n ) void( std::cout << (even(n) ? "It's even!" : "Odd.") << std::endl );
int main () {
even = []( auto n ) n==0 ? true : odd(n-1);
std::cout << "5 is odd : " << odd(5) << std::endl;
std::cout << "5 is odd : " << rec_odd(5) << std::endl;
std::cout << "5 is even : " << even(5) << std::endl;
std::cout << "5 is even : " << rec_even(5) << std::endl;
even_print(5);
std::cout << bold("Hello world") << std::endl;
prnt2(5); prnt2('c'); prnt2('\n');
std::tuple<int,std::string> a{1,"hello "},
b{2,"world!"};
auto r = zip_tuple<0,1>( ([](auto x, auto y) x + y), a, b );
{
int a = 5, b = 5;
auto apply = []( auto f, auto x, auto y ) f(x,y);
int c = apply( ([](auto x, auto y) x + y), a, b );
}
std::cout << "r = { " << std::get<0>(r) << ", "
<< std::get<1>(r) << " }\n";
for( int i : {1,2,3,4} )
std::cout << "fix(" << i << ") = " << fixed_fib(i) << std::endl;
std::cout << std::endl;
std::cout << "Fact 2*3*4 = " << iToIFact(4) << std::endl;
std::cout << "Fact 2*3*4 = " << fact(4) << std::endl;
std::cout << "Fact 2*3*4 = " << fixed_fact(4) << std::endl;
//std::cout << "Fact 2*3*4 = " << factY(4) << std::endl;
std::vector<int> v = {1,2,3,4};
auto prod = std::accumulate (
v.begin(), v.end(), 1,
multObj
);
std::cout << "prod = " << prod << std::endl;
auto add1 = []( auto x ) x + 1;
auto Char = []( auto c ) char(c);
// Prints "a + 1 = b"
std::cout << "a + 1 = " << compose(Char,add1)('a') << std::endl;
prnt(5);
prnt( "a string\n" );
prnt(v);
prnt("\n");
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment