#include <cstddef>
template<typename... Ts> struct types {};
template<typename T, typename U>
struct concat;
template<typename... Ts, typename... Us>
struct concat< types<Ts...>, types<Us...> > {
typedef types<Ts..., Us...> result;
};
template<typename Ts, typename Us>
using Concat = typename concat<Ts, Us>::result;
template<std::size_t n, typename Ts>
struct split;
template<std::size_t n, typename... Ts>
struct split<n, types<Ts...>> {
typedef split<n/2, types<Ts...>> one;
typedef split<n-n/2, typename one::right> two;
typedef Concat< typename one::left, typename two::left > left;
typedef typename two::right right;
};
template<typename... Ts>
struct split<0, types<Ts...>> {
typedef types<> left;
typedef types<Ts...> right;
};
template<typename T, typename... Ts>
struct split<1, types<T, Ts...>> {
typedef types<T> left;
typedef types<Ts...> right;
};
template<template<typename, typename>class OP, typename State, typename Ts>
struct fold_helper;
template<template<typename, typename>class OP, typename State, typename... Ts>
struct fold_helper<OP, State, types<Ts...>> {
private:
typedef split<sizeof...(Ts)/2, types<Ts...>> parts;
typedef typename parts::left left;
typedef typename parts::right right;
typedef typename fold_helper<OP, State, left>::result left_result;
public:
typedef typename fold_helper<OP, left_result, right>::result result;
};
template<template<typename, typename>class OP, typename State>
struct fold_helper<OP, State, types<>> {
typedef State result;
};
template<template<typename, typename>class OP, typename State, typename T>
struct fold_helper<OP, State, types<T>> {
typedef typename OP<State,T>::type result;
};
template<template<typename, typename>class OP, typename State, typename... Ts>
struct fold {
typedef typename fold_helper<OP, State, types<Ts...>>::result type;
};
template<template<typename, typename>class OP, typename State, typename... Ts>
using Fold = typename fold<OP, State, Ts...>::type;
template<typename left, typename right>
struct op_test {
typedef int type;
};
template<int n>
struct counter {enum{value=n};};
template<typename left, typename right>
struct sum;
template<int a, int b>
struct sum<counter<a>, counter<b>> {
typedef counter<a+b> type;
};
#include <iostream>
int main() {
Fold< op_test, double, int, char, char*, int* > foo = 8;
std::cout << Fold<sum, counter<0>, counter<5>, counter<9>, counter<-7>>::value << "\n";
}
I2luY2x1ZGUgPGNzdGRkZWY+Cgp0ZW1wbGF0ZTx0eXBlbmFtZS4uLiBUcz4gc3RydWN0IHR5cGVzIHt9Owp0ZW1wbGF0ZTx0eXBlbmFtZSBULCB0eXBlbmFtZSBVPgpzdHJ1Y3QgY29uY2F0Owp0ZW1wbGF0ZTx0eXBlbmFtZS4uLiBUcywgdHlwZW5hbWUuLi4gVXM+CnN0cnVjdCBjb25jYXQ8IHR5cGVzPFRzLi4uPiwgdHlwZXM8VXMuLi4+ID4gewogIHR5cGVkZWYgdHlwZXM8VHMuLi4sIFVzLi4uPiByZXN1bHQ7Cn07CnRlbXBsYXRlPHR5cGVuYW1lIFRzLCB0eXBlbmFtZSBVcz4KdXNpbmcgQ29uY2F0ID0gdHlwZW5hbWUgY29uY2F0PFRzLCBVcz46OnJlc3VsdDsKCnRlbXBsYXRlPHN0ZDo6c2l6ZV90IG4sIHR5cGVuYW1lIFRzPgpzdHJ1Y3Qgc3BsaXQ7CnRlbXBsYXRlPHN0ZDo6c2l6ZV90IG4sIHR5cGVuYW1lLi4uIFRzPgpzdHJ1Y3Qgc3BsaXQ8biwgdHlwZXM8VHMuLi4+PiB7CiAgdHlwZWRlZiBzcGxpdDxuLzIsIHR5cGVzPFRzLi4uPj4gb25lOwogIHR5cGVkZWYgc3BsaXQ8bi1uLzIsIHR5cGVuYW1lIG9uZTo6cmlnaHQ+IHR3bzsKICB0eXBlZGVmIENvbmNhdDwgdHlwZW5hbWUgb25lOjpsZWZ0LCB0eXBlbmFtZSB0d286OmxlZnQgPiBsZWZ0OwogIHR5cGVkZWYgdHlwZW5hbWUgdHdvOjpyaWdodCByaWdodDsKfTsKdGVtcGxhdGU8dHlwZW5hbWUuLi4gVHM+CnN0cnVjdCBzcGxpdDwwLCB0eXBlczxUcy4uLj4+IHsKICB0eXBlZGVmIHR5cGVzPD4gbGVmdDsKICB0eXBlZGVmIHR5cGVzPFRzLi4uPiByaWdodDsKfTsKdGVtcGxhdGU8dHlwZW5hbWUgVCwgdHlwZW5hbWUuLi4gVHM+CnN0cnVjdCBzcGxpdDwxLCB0eXBlczxULCBUcy4uLj4+IHsKICB0eXBlZGVmIHR5cGVzPFQ+IGxlZnQ7CiAgdHlwZWRlZiB0eXBlczxUcy4uLj4gcmlnaHQ7Cn07CnRlbXBsYXRlPHRlbXBsYXRlPHR5cGVuYW1lLCB0eXBlbmFtZT5jbGFzcyBPUCwgdHlwZW5hbWUgU3RhdGUsIHR5cGVuYW1lIFRzPgpzdHJ1Y3QgZm9sZF9oZWxwZXI7CnRlbXBsYXRlPHRlbXBsYXRlPHR5cGVuYW1lLCB0eXBlbmFtZT5jbGFzcyBPUCwgdHlwZW5hbWUgU3RhdGUsIHR5cGVuYW1lLi4uIFRzPgpzdHJ1Y3QgZm9sZF9oZWxwZXI8T1AsIFN0YXRlLCB0eXBlczxUcy4uLj4+IHsKcHJpdmF0ZToKICB0eXBlZGVmIHNwbGl0PHNpemVvZi4uLihUcykvMiwgdHlwZXM8VHMuLi4+PiBwYXJ0czsKICB0eXBlZGVmIHR5cGVuYW1lIHBhcnRzOjpsZWZ0IGxlZnQ7CiAgdHlwZWRlZiB0eXBlbmFtZSBwYXJ0czo6cmlnaHQgcmlnaHQ7CiAgdHlwZWRlZiB0eXBlbmFtZSBmb2xkX2hlbHBlcjxPUCwgU3RhdGUsIGxlZnQ+OjpyZXN1bHQgbGVmdF9yZXN1bHQ7CnB1YmxpYzoKICB0eXBlZGVmIHR5cGVuYW1lIGZvbGRfaGVscGVyPE9QLCBsZWZ0X3Jlc3VsdCwgcmlnaHQ+OjpyZXN1bHQgcmVzdWx0Owp9Owp0ZW1wbGF0ZTx0ZW1wbGF0ZTx0eXBlbmFtZSwgdHlwZW5hbWU+Y2xhc3MgT1AsIHR5cGVuYW1lIFN0YXRlPgpzdHJ1Y3QgZm9sZF9oZWxwZXI8T1AsIFN0YXRlLCB0eXBlczw+PiB7CiAgdHlwZWRlZiBTdGF0ZSByZXN1bHQ7Cn07CnRlbXBsYXRlPHRlbXBsYXRlPHR5cGVuYW1lLCB0eXBlbmFtZT5jbGFzcyBPUCwgdHlwZW5hbWUgU3RhdGUsIHR5cGVuYW1lIFQ+CnN0cnVjdCBmb2xkX2hlbHBlcjxPUCwgU3RhdGUsIHR5cGVzPFQ+PiB7CiAgdHlwZWRlZiB0eXBlbmFtZSBPUDxTdGF0ZSxUPjo6dHlwZSByZXN1bHQ7Cn07CnRlbXBsYXRlPHRlbXBsYXRlPHR5cGVuYW1lLCB0eXBlbmFtZT5jbGFzcyBPUCwgdHlwZW5hbWUgU3RhdGUsIHR5cGVuYW1lLi4uIFRzPgpzdHJ1Y3QgZm9sZCB7CiAgdHlwZWRlZiB0eXBlbmFtZSBmb2xkX2hlbHBlcjxPUCwgU3RhdGUsIHR5cGVzPFRzLi4uPj46OnJlc3VsdCB0eXBlOwp9Owp0ZW1wbGF0ZTx0ZW1wbGF0ZTx0eXBlbmFtZSwgdHlwZW5hbWU+Y2xhc3MgT1AsIHR5cGVuYW1lIFN0YXRlLCB0eXBlbmFtZS4uLiBUcz4KdXNpbmcgRm9sZCA9IHR5cGVuYW1lIGZvbGQ8T1AsIFN0YXRlLCBUcy4uLj46OnR5cGU7Cgp0ZW1wbGF0ZTx0eXBlbmFtZSBsZWZ0LCB0eXBlbmFtZSByaWdodD4Kc3RydWN0IG9wX3Rlc3QgewoJdHlwZWRlZiBpbnQgdHlwZTsKfTsKCnRlbXBsYXRlPGludCBuPgpzdHJ1Y3QgY291bnRlciB7ZW51bXt2YWx1ZT1ufTt9OwoKdGVtcGxhdGU8dHlwZW5hbWUgbGVmdCwgdHlwZW5hbWUgcmlnaHQ+CnN0cnVjdCBzdW07CnRlbXBsYXRlPGludCBhLCBpbnQgYj4Kc3RydWN0IHN1bTxjb3VudGVyPGE+LCBjb3VudGVyPGI+PiB7Cgl0eXBlZGVmIGNvdW50ZXI8YStiPiB0eXBlOwp9OwoKI2luY2x1ZGUgPGlvc3RyZWFtPgoKaW50IG1haW4oKSB7CglGb2xkPCBvcF90ZXN0LCBkb3VibGUsIGludCwgY2hhciwgY2hhciosIGludCogPiBmb28gPSA4OwoJc3RkOjpjb3V0IDw8IEZvbGQ8c3VtLCBjb3VudGVyPDA+LCBjb3VudGVyPDU+LCBjb3VudGVyPDk+LCBjb3VudGVyPC03Pj46OnZhbHVlIDw8ICJcbiI7Cn0KCg==