#include <utility>
#include <functional>
#include <iostream>
template<class Is, size_t I>
struct add;
template<class Is, size_t I>
using add_t=typename add<Is,I>::type;
template<size_t...Is, size_t I>
struct add<std::index_sequence<Is...>, I>{
using type=std::index_sequence<(I+Is)...>;
};
template<template<class...>class Z, class Is, class...Ts>
struct partial_apply;
template<template<class...>class Z, class Is, class...Ts>
using partial_apply_t=typename partial_apply<Z,Is,Ts...>::type;
template<template<class...>class Z, size_t...Is, class...Ts>
struct partial_apply<Z,std::index_sequence<Is...>, Ts...> {
using tup = std::tuple<Ts...>;
template<size_t I> using e = std::tuple_element_t<I, tup>;
using type=Z< e<Is>... >;
};
template<template<class...>class Z, class...Ts>
struct split {
using left = partial_apply_t<Z, std::make_index_sequence<sizeof...(Ts)/2>, Ts...>;
using right = partial_apply_t<Z, add_t<
std::make_index_sequence<(1+sizeof...(Ts))/2>,
sizeof...(Ts)/2
>, Ts...>;
};
template<template<class...>class Z, class...Ts>
using right=typename split<Z,Ts...>::right;
template<template<class...>class Z, class...Ts>
using left=typename split<Z,Ts...>::left;
template<class...Sigs>
struct functions_impl;
template<class...Sigs>
using functions = typename functions_impl<Sigs...>::type;
template<class...Sigs>
struct functions_impl:
left<functions, Sigs...>,
right<functions, Sigs...>
{
using type=functions_impl;
using A = left<functions, Sigs...>;
using B = right<functions, Sigs...>;
using A::operator();
using B::operator();
template<class F>
functions_impl(F&& f):
A(f),
B(std::forward<F>(f))
{}
};
template<class Sig>
struct functions_impl<Sig> {
using type=std::function<Sig>;
};
int main()
{
functions<void(int), void(double)> f = [](auto&& x){std::cout << x << '\n';};
f(3.14);
f(3);
}
I2luY2x1ZGUgPHV0aWxpdHk+CiNpbmNsdWRlIDxmdW5jdGlvbmFsPgojaW5jbHVkZSA8aW9zdHJlYW0+CgogICAgdGVtcGxhdGU8Y2xhc3MgSXMsIHNpemVfdCBJPgogICAgc3RydWN0IGFkZDsKICAgIHRlbXBsYXRlPGNsYXNzIElzLCBzaXplX3QgST4KICAgIHVzaW5nIGFkZF90PXR5cGVuYW1lIGFkZDxJcyxJPjo6dHlwZTsKCiAgICB0ZW1wbGF0ZTxzaXplX3QuLi5Jcywgc2l6ZV90IEk+CiAgICBzdHJ1Y3QgYWRkPHN0ZDo6aW5kZXhfc2VxdWVuY2U8SXMuLi4+LCBJPnsKICAgICAgdXNpbmcgdHlwZT1zdGQ6OmluZGV4X3NlcXVlbmNlPChJK0lzKS4uLj47CiAgICB9OwoKICAgIHRlbXBsYXRlPHRlbXBsYXRlPGNsYXNzLi4uPmNsYXNzIFosIGNsYXNzIElzLCBjbGFzcy4uLlRzPgogICAgc3RydWN0IHBhcnRpYWxfYXBwbHk7CiAgICB0ZW1wbGF0ZTx0ZW1wbGF0ZTxjbGFzcy4uLj5jbGFzcyBaLCBjbGFzcyBJcywgY2xhc3MuLi5Ucz4KICAgIHVzaW5nIHBhcnRpYWxfYXBwbHlfdD10eXBlbmFtZSBwYXJ0aWFsX2FwcGx5PFosSXMsVHMuLi4+Ojp0eXBlOwoKICAgIHRlbXBsYXRlPHRlbXBsYXRlPGNsYXNzLi4uPmNsYXNzIFosIHNpemVfdC4uLklzLCBjbGFzcy4uLlRzPgogICAgc3RydWN0IHBhcnRpYWxfYXBwbHk8WixzdGQ6OmluZGV4X3NlcXVlbmNlPElzLi4uPiwgVHMuLi4+IHsKICAgICAgdXNpbmcgdHVwID0gc3RkOjp0dXBsZTxUcy4uLj47CiAgICAgIHRlbXBsYXRlPHNpemVfdCBJPiB1c2luZyBlID0gc3RkOjp0dXBsZV9lbGVtZW50X3Q8SSwgdHVwPjsKCiAgICAgIHVzaW5nIHR5cGU9WjwgZTxJcz4uLi4gPjsKICAgIH07CgogICAgdGVtcGxhdGU8dGVtcGxhdGU8Y2xhc3MuLi4+Y2xhc3MgWiwgY2xhc3MuLi5Ucz4KICAgIHN0cnVjdCBzcGxpdCB7CiAgICAgIHVzaW5nIGxlZnQgPSBwYXJ0aWFsX2FwcGx5X3Q8Wiwgc3RkOjptYWtlX2luZGV4X3NlcXVlbmNlPHNpemVvZi4uLihUcykvMj4sIFRzLi4uPjsKICAgICAgdXNpbmcgcmlnaHQgPSBwYXJ0aWFsX2FwcGx5X3Q8WiwgYWRkX3Q8CiAgICAgICAgc3RkOjptYWtlX2luZGV4X3NlcXVlbmNlPCgxK3NpemVvZi4uLihUcykpLzI+LAogICAgICAgIHNpemVvZi4uLihUcykvMgogICAgICA+LCBUcy4uLj47CiAgICB9OwogICAgdGVtcGxhdGU8dGVtcGxhdGU8Y2xhc3MuLi4+Y2xhc3MgWiwgY2xhc3MuLi5Ucz4KICAgIHVzaW5nIHJpZ2h0PXR5cGVuYW1lIHNwbGl0PFosVHMuLi4+OjpyaWdodDsKICAgIHRlbXBsYXRlPHRlbXBsYXRlPGNsYXNzLi4uPmNsYXNzIFosIGNsYXNzLi4uVHM+CiAgICB1c2luZyBsZWZ0PXR5cGVuYW1lIHNwbGl0PFosVHMuLi4+OjpsZWZ0OwoKICAgIHRlbXBsYXRlPGNsYXNzLi4uU2lncz4KICAgIHN0cnVjdCBmdW5jdGlvbnNfaW1wbDsKCiAgICB0ZW1wbGF0ZTxjbGFzcy4uLlNpZ3M+CiAgICB1c2luZyBmdW5jdGlvbnMgPSB0eXBlbmFtZSBmdW5jdGlvbnNfaW1wbDxTaWdzLi4uPjo6dHlwZTsKCiAgICB0ZW1wbGF0ZTxjbGFzcy4uLlNpZ3M+CiAgICBzdHJ1Y3QgZnVuY3Rpb25zX2ltcGw6CiAgICAgIGxlZnQ8ZnVuY3Rpb25zLCBTaWdzLi4uPiwKICAgICAgcmlnaHQ8ZnVuY3Rpb25zLCBTaWdzLi4uPgogICAgewogICAgICAgdXNpbmcgdHlwZT1mdW5jdGlvbnNfaW1wbDsKICAgICAgIHVzaW5nIEEgPSBsZWZ0PGZ1bmN0aW9ucywgU2lncy4uLj47CiAgICAgICB1c2luZyBCID0gcmlnaHQ8ZnVuY3Rpb25zLCBTaWdzLi4uPjsKICAgICAgIHVzaW5nIEE6Om9wZXJhdG9yKCk7CiAgICAgICB1c2luZyBCOjpvcGVyYXRvcigpOwogICAgICAgdGVtcGxhdGU8Y2xhc3MgRj4KICAgICAgIGZ1bmN0aW9uc19pbXBsKEYmJiBmKToKICAgICAgICAgQShmKSwKICAgICAgICAgQihzdGQ6OmZvcndhcmQ8Rj4oZikpCiAgICAgICB7fQogICAgfTsKICAgIHRlbXBsYXRlPGNsYXNzIFNpZz4KICAgIHN0cnVjdCBmdW5jdGlvbnNfaW1wbDxTaWc+IHsKICAgICAgdXNpbmcgdHlwZT1zdGQ6OmZ1bmN0aW9uPFNpZz47CiAgICB9OwoKaW50IG1haW4oKQp7CglmdW5jdGlvbnM8dm9pZChpbnQpLCB2b2lkKGRvdWJsZSk+IGYgPSBbXShhdXRvJiYgeCl7c3RkOjpjb3V0IDw8IHggPDwgJ1xuJzt9OwoJZigzLjE0KTsKCWYoMyk7Cn0=