Skip to content

Instantly share code, notes, and snippets.

@langthom
Created February 6, 2018 08:15
Show Gist options
  • Save langthom/30c75e65f23bf5e7a75aa32e34bfce55 to your computer and use it in GitHub Desktop.
Save langthom/30c75e65f23bf5e7a75aa32e34bfce55 to your computer and use it in GitHub Desktop.
Playing around with meta-functions, understanding placeholders as they are defined in boost.
// Playing around with meta-functions, placeholders and stuff. Thomas Lang, 2018.
#include <iostream>
#include <typeinfo>
namespace placeholder_helper {
// Helper utility for finding the N'th argument in a template parameter pack.
template<int Current, int N, typename FirstArg, typename... Args>
struct find_arg {
static_assert(Current < N, "Invalid argument position!");
typedef typename find_arg<Current + 1, N, Args...>::type type;
};
template<int N, typename WantedArg, typename... Args>
struct find_arg<N, N, WantedArg, Args...> {
typedef WantedArg type;
};
} // placeholder_helper
template<int N>
struct int_ {
static constexpr int value = N;
};
namespace type_list {
struct NIL {
typedef NIL Head;
typedef NIL Tail;
};
template<typename H, typename T = NIL>
struct type_list {
typedef H Head;
typedef T Tail;
};
template<int FirstNum, int... Nums>
struct make_integral_list {
typedef type_list<int_<FirstNum>, typename make_integral_list<Nums...>::type> type;
};
template<int Num>
struct make_integral_list<Num> {
typedef type_list<int_<Num>, NIL> type;
};
// foldl :: (a -> b -> a) -> a -> [b] -> a
// foldl _ a [] = a
// foldl f a xs = foldl f (f a (head xs)) (tail xs)
template<typename Function, typename Acc, typename List>
struct foldl {
typedef typename Function::template apply<Acc, typename List::Head>::value NewAcc;
typedef typename foldl<Function, NewAcc, typename List::Tail>::type type;
};
template<typename Function, typename Acc>
struct foldl<Function, Acc, NIL> {
typedef Acc type;
};
} // type_list
// Representation of an argument i.e. an argument type.
template<int N>
struct arg {
template<typename... Args>
struct apply {
typedef typename placeholder_helper::find_arg<0, N, Args...>::type type;
};
};
// Typedef two wildcards, sufficient for our testing purposes.
typedef arg<0> _0;
typedef arg<1> _1;
// Example function: plus_f<int_<X>, int_<Y>> -> int_<X+y>
struct plus_f {
template<typename X, typename Y>
struct apply {
typedef int_<X::value + Y::value> value;
};
};
// -----------------------------------------------------------------------------
template<typename X, typename Y> // X, Y are placeholders.
struct minus_f_ph {
template<typename X1, typename Y1> // X1, Y1 are the real types.
struct apply {
// First, choose the arguments based on the order given through the placeholders.
typedef typename X::template apply<X1, Y1>::type first_arg;
typedef typename Y::template apply<X1, Y1>::type second_arg;
// Then, do the computation on the choosen arguments.
typedef int_<first_arg::value - second_arg::value> value;
};
};
int main(void) {
// Test 1: check if selected type is right.
typedef typename arg<1>::template apply<char, short, int>::type ResultType;
std::cout << "result type: " << typeid(ResultType).name() << std::endl;
// Test 2: foldl (+) 1 [1..3] == 7 ?
typedef type_list::make_integral_list<1, 2, 3>::type onetwothree;
typedef type_list::foldl<plus_f, int_<1>, onetwothree>::type result;
static_assert(result::value == 7, "foldl (+) 1 [1..3] expected to be 7");
std::cout << "foldl (+) 1 [1..3] = " << result::value << std::endl;
// Test 3: placeholder fold. (Note switched arguments)
typedef type_list::foldl<minus_f_ph<_0, _1>, int_<1>, onetwothree>::type result2_1;
static_assert(result2_1::value == -5, "foldl (\\x y -> x-y) 1 [1..3] expected to be -5");
std::cout << "foldl (\\x y -> x-y) 1 [1..3] = " << result2_1::value << std::endl;
typedef type_list::foldl<minus_f_ph<_1, _0>, int_<1>, onetwothree>::type result2_2;
static_assert(result2_2::value == 1, "foldl (\\x y -> y-x) 1 [1..3] expected to be 1");
std::cout << "foldl (\\x y -> y-x) 1 [1..3] = " << result2_2::value << std::endl;
return 0;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment