Created
July 29, 2014 10:53
-
-
Save cjxgm/54e48d229620af3cc1cb to your computer and use it in GitHub Desktop.
compile-time list in c++11
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include <iostream> | |
#include <utility> | |
using namespace std; | |
namespace list | |
{ | |
using std::pair; | |
using std::make_pair; | |
struct nil {}; | |
#define RETURN(BODY) -> decltype(BODY) { return (BODY); } | |
// cons | |
constexpr auto cons() | |
RETURN(nil{}); | |
template <class Value, class ConsOrNil> | |
constexpr auto cons(Value value, ConsOrNil next) | |
RETURN(make_pair(value, next)); | |
template <class Value> | |
constexpr auto cons(Value value) | |
RETURN(cons(value, cons())); | |
// reverse | |
template <class Cons> | |
constexpr auto reverse(Cons current) | |
RETURN(reverse(current.second, cons(current.first))); | |
constexpr auto reverse(nil) | |
RETURN(nil{}); | |
template <class Cons, class Result> | |
constexpr auto reverse(Cons current, Result result) | |
RETURN(reverse(current.second, cons(current.first, result))); | |
template <class Result> | |
constexpr auto reverse(nil, Result result) | |
RETURN(result); | |
// foldl | |
template <class Cons, class BinOp> | |
constexpr auto foldl(Cons current, BinOp op) | |
RETURN(foldl(current.second, op, current.first)); | |
template <class Init, class Cons, class BinOp> | |
constexpr auto foldl(Cons current, BinOp op, Init init) | |
RETURN(op(current.first, foldl(current.second, op, init))); | |
template <class Init, class BinOp> | |
constexpr auto foldl(nil, BinOp, Init init={}) | |
RETURN(init); | |
// map | |
template <class Cons, class Unary> | |
constexpr auto map(Cons current, Unary op) | |
RETURN(cons(op(current.first), map(current.second, op))); | |
template <class Unary> | |
constexpr auto map(nil, Unary) | |
RETURN(nil{}); | |
// first | |
template <class Cons> | |
constexpr auto first(Cons current) | |
RETURN(cons(current.first)); | |
constexpr auto first(nil) | |
RETURN(nil{}); | |
// last | |
template <class ConsOrNil> | |
constexpr auto last(ConsOrNil current) | |
RETURN(first(reverse(current))); | |
// append | |
template <class ConsOrNil, class Value> | |
constexpr auto append(ConsOrNil current, Value value) | |
RETURN(reverse(cons(value, reverse(current)))); | |
// sum | |
struct add_op | |
{ | |
template <class T, class U> | |
constexpr auto operator()(T t, U u) | |
RETURN(t+u); | |
}; | |
template <class Cons> | |
constexpr auto sum(Cons current) | |
RETURN(foldl(current, add_op{}, 0)); | |
// inc | |
struct inc_op | |
{ | |
template <class T> | |
constexpr auto operator()(T t) | |
RETURN(t+1); | |
}; | |
template <class Cons> | |
constexpr auto inc(Cons current) | |
RETURN(map(current, inc_op{})); | |
struct print_op | |
{ | |
template <class T> | |
constexpr auto operator()(T t) | |
RETURN(bool(cout << t << endl)); | |
}; | |
template <class Cons> | |
constexpr auto print(Cons current) | |
RETURN(map(current, print_op{})); | |
#undef RETURN | |
}; | |
int main() | |
{ | |
using namespace list; | |
constexpr auto lst = cons(1, cons(2, cons(3))); | |
constexpr auto ils = inc(lst); | |
constexpr auto rls = reverse(ils, nil{}); | |
constexpr auto als = append(rls, 10); | |
constexpr auto s = sum(ils); | |
cout << s << endl; | |
print(rls); | |
print(first(rls)); | |
print(last(rls)); | |
cout << endl; | |
print(als); | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment