#include <array>
#include <iostream>
#include <functional>
#include <tuple>
#include <type_traits>
/* C++17 std::apply */
template <typename Fn, typename Tuple, size_t... Is>
decltype(auto) apply_impl(Fn &&fn, Tuple &&tuple, std::index_sequence<Is...>) {
return std::forward<Fn>(fn)(std::get<Is>(std::forward<Tuple>(tuple))...);
}
template <typename Fn, typename Tuple>
decltype(auto) apply(Fn &&fn, Tuple &&tuple) {
return apply_impl(
std::forward<Fn>(fn),
std::forward<Tuple>(tuple),
std::make_index_sequence<std::tuple_size<std::decay_t<Tuple>>::value>());
}
/* function_arity */
template <typename F>
struct function_arity;
template <typename R, typename... Args>
struct function_arity<R (Args...)>
: std::integral_constant<std::size_t, sizeof...(Args)> {};
template <typename R, typename... Args>
struct function_arity<R (*)(Args...)> : function_arity<R (Args...)> {};
template <typename R, typename... Args>
struct function_arity<R (&)(Args...)> : function_arity<R (Args...)> {};
template <typename R, typename C, typename... Args>
struct function_arity<R (C::*)(Args...) const> : function_arity<R (Args...)> {};
template <typename R, typename C, typename... Args>
struct function_arity<R (C::*)(Args...)> : function_arity<R (Args...)> {};
template <typename C>
struct function_arity : function_arity<decltype(&C::operator())> {};
/* make_integer_range */
template <typename T, typename U, T Begin>
struct make_integer_range_impl;
template <typename T, T... Ints, T Begin>
struct make_integer_range_impl<T, std::integer_sequence<T, Ints...>, Begin> {
using type = std::integer_sequence<T, Begin + Ints...>;
};
template <class T, T Begin, T End>
using make_integer_range =
typename make_integer_range_impl<T,
std::make_integer_sequence<T, End - Begin>,
Begin>::type;
template <std::size_t Begin, std::size_t End>
using make_index_range = make_integer_range<std::size_t, Begin, End>;
/* slice */
template <std::size_t... Is, std::size_t... Js>
constexpr decltype(auto) slice_impl(std::index_sequence<Is...>,
std::index_sequence<Js...>) {
using array_t = std::array<std::size_t, sizeof...(Is)>;
return std::index_sequence<std::get<Js>(array_t{{Is...}})...>();
}
template <std::size_t Begin, std::size_t End, std::size_t... Is>
constexpr decltype(auto) slice(std::index_sequence<Is...> is) {
return slice_impl(is, make_index_range<Begin, End>());
}
/* partial_sum */
template <std::size_t... Is>
struct partial_sum;
template <std::size_t... Is>
using partial_sum_t = typename partial_sum<Is...>::type;
template <>
struct partial_sum<> { using type = std::index_sequence<>; };
template <std::size_t I, std::size_t... Is>
struct partial_sum<I, Is...> {
template <typename Js>
struct impl;
template <std::size_t... Js>
struct impl<std::index_sequence<Js...>> {
using type = std::index_sequence<I, Js + I...>;
};
using type = typename impl<partial_sum_t<Is...>>::type;
};
/* split_and_call */
template <typename... Fns, typename Args, std::size_t... Is, std::size_t... Js>
void split_and_call_impl(Args &&args,
std::index_sequence<Is...>,
std::index_sequence<Js...>) {
int dummy[] = {
(apply_impl(Fns{}, std::forward<Args>(args), make_index_range<Is, Js>{}),
0)...};
(void)dummy;
}
template <typename... Fns, typename... Args>
void split_and_call(Args &&... args) {
auto partial_sums = partial_sum_t<0, function_arity<Fns>{}...>{};
auto is = slice<0, sizeof...(Fns)>(partial_sums);
auto js = slice<1, sizeof...(Fns) + 1>(partial_sums);
split_and_call_impl<Fns...>(
std::forward_as_tuple(std::forward<Args>(args)...), is, js);
}
int main() {
struct F { void operator()(int x, int y) {
std::cout << "F(" << x << ", " << y << ')' << std::endl;
}
};
struct G {
void operator()(int x) { std::cout << "G(" << x << ')' << std::endl; }
};
split_and_call<F, G>(1, 2, 3);
}
I2luY2x1ZGUgPGFycmF5PgojaW5jbHVkZSA8aW9zdHJlYW0+CiNpbmNsdWRlIDxmdW5jdGlvbmFsPgojaW5jbHVkZSA8dHVwbGU+CiNpbmNsdWRlIDx0eXBlX3RyYWl0cz4KCi8qIEMrKzE3IHN0ZDo6YXBwbHkgKi8KCnRlbXBsYXRlIDx0eXBlbmFtZSBGbiwgdHlwZW5hbWUgVHVwbGUsIHNpemVfdC4uLiBJcz4KZGVjbHR5cGUoYXV0bykgYXBwbHlfaW1wbChGbiAmJmZuLCBUdXBsZSAmJnR1cGxlLCBzdGQ6OmluZGV4X3NlcXVlbmNlPElzLi4uPikgewogIHJldHVybiBzdGQ6OmZvcndhcmQ8Rm4+KGZuKShzdGQ6OmdldDxJcz4oc3RkOjpmb3J3YXJkPFR1cGxlPih0dXBsZSkpLi4uKTsKfQoKdGVtcGxhdGUgPHR5cGVuYW1lIEZuLCB0eXBlbmFtZSBUdXBsZT4KZGVjbHR5cGUoYXV0bykgYXBwbHkoRm4gJiZmbiwgVHVwbGUgJiZ0dXBsZSkgewogIHJldHVybiBhcHBseV9pbXBsKAogICAgICBzdGQ6OmZvcndhcmQ8Rm4+KGZuKSwKICAgICAgc3RkOjpmb3J3YXJkPFR1cGxlPih0dXBsZSksCiAgICAgIHN0ZDo6bWFrZV9pbmRleF9zZXF1ZW5jZTxzdGQ6OnR1cGxlX3NpemU8c3RkOjpkZWNheV90PFR1cGxlPj46OnZhbHVlPigpKTsKfQoKLyogZnVuY3Rpb25fYXJpdHkgKi8KCnRlbXBsYXRlIDx0eXBlbmFtZSBGPgpzdHJ1Y3QgZnVuY3Rpb25fYXJpdHk7Cgp0ZW1wbGF0ZSA8dHlwZW5hbWUgUiwgdHlwZW5hbWUuLi4gQXJncz4Kc3RydWN0IGZ1bmN0aW9uX2FyaXR5PFIgKEFyZ3MuLi4pPgogICAgOiBzdGQ6OmludGVncmFsX2NvbnN0YW50PHN0ZDo6c2l6ZV90LCBzaXplb2YuLi4oQXJncyk+IHt9OwoKdGVtcGxhdGUgPHR5cGVuYW1lIFIsIHR5cGVuYW1lLi4uIEFyZ3M+CnN0cnVjdCBmdW5jdGlvbl9hcml0eTxSICgqKShBcmdzLi4uKT4gOiBmdW5jdGlvbl9hcml0eTxSIChBcmdzLi4uKT4ge307Cgp0ZW1wbGF0ZSA8dHlwZW5hbWUgUiwgdHlwZW5hbWUuLi4gQXJncz4Kc3RydWN0IGZ1bmN0aW9uX2FyaXR5PFIgKCYpKEFyZ3MuLi4pPiA6IGZ1bmN0aW9uX2FyaXR5PFIgKEFyZ3MuLi4pPiB7fTsKCnRlbXBsYXRlIDx0eXBlbmFtZSBSLCB0eXBlbmFtZSBDLCB0eXBlbmFtZS4uLiBBcmdzPgpzdHJ1Y3QgZnVuY3Rpb25fYXJpdHk8UiAoQzo6KikoQXJncy4uLikgY29uc3Q+IDogZnVuY3Rpb25fYXJpdHk8UiAoQXJncy4uLik+IHt9OwoKdGVtcGxhdGUgPHR5cGVuYW1lIFIsIHR5cGVuYW1lIEMsIHR5cGVuYW1lLi4uIEFyZ3M+CnN0cnVjdCBmdW5jdGlvbl9hcml0eTxSIChDOjoqKShBcmdzLi4uKT4gOiBmdW5jdGlvbl9hcml0eTxSIChBcmdzLi4uKT4ge307Cgp0ZW1wbGF0ZSA8dHlwZW5hbWUgQz4Kc3RydWN0IGZ1bmN0aW9uX2FyaXR5IDogZnVuY3Rpb25fYXJpdHk8ZGVjbHR5cGUoJkM6Om9wZXJhdG9yKCkpPiB7fTsKCi8qIG1ha2VfaW50ZWdlcl9yYW5nZSAqLwoKdGVtcGxhdGUgPHR5cGVuYW1lIFQsIHR5cGVuYW1lIFUsIFQgQmVnaW4+CnN0cnVjdCBtYWtlX2ludGVnZXJfcmFuZ2VfaW1wbDsKCnRlbXBsYXRlIDx0eXBlbmFtZSBULCBULi4uIEludHMsIFQgQmVnaW4+CnN0cnVjdCBtYWtlX2ludGVnZXJfcmFuZ2VfaW1wbDxULCBzdGQ6OmludGVnZXJfc2VxdWVuY2U8VCwgSW50cy4uLj4sIEJlZ2luPiB7CiAgdXNpbmcgdHlwZSA9IHN0ZDo6aW50ZWdlcl9zZXF1ZW5jZTxULCBCZWdpbiArIEludHMuLi4+Owp9OwoKdGVtcGxhdGUgPGNsYXNzIFQsIFQgQmVnaW4sIFQgRW5kPgp1c2luZyBtYWtlX2ludGVnZXJfcmFuZ2UgPQogICAgdHlwZW5hbWUgbWFrZV9pbnRlZ2VyX3JhbmdlX2ltcGw8VCwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHN0ZDo6bWFrZV9pbnRlZ2VyX3NlcXVlbmNlPFQsIEVuZCAtIEJlZ2luPiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIEJlZ2luPjo6dHlwZTsKCnRlbXBsYXRlIDxzdGQ6OnNpemVfdCBCZWdpbiwgc3RkOjpzaXplX3QgRW5kPgp1c2luZyBtYWtlX2luZGV4X3JhbmdlID0gbWFrZV9pbnRlZ2VyX3JhbmdlPHN0ZDo6c2l6ZV90LCBCZWdpbiwgRW5kPjsKCi8qIHNsaWNlICovCgp0ZW1wbGF0ZSA8c3RkOjpzaXplX3QuLi4gSXMsIHN0ZDo6c2l6ZV90Li4uIEpzPgpjb25zdGV4cHIgZGVjbHR5cGUoYXV0bykgc2xpY2VfaW1wbChzdGQ6OmluZGV4X3NlcXVlbmNlPElzLi4uPiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgc3RkOjppbmRleF9zZXF1ZW5jZTxKcy4uLj4pIHsKICB1c2luZyBhcnJheV90ID0gc3RkOjphcnJheTxzdGQ6OnNpemVfdCwgc2l6ZW9mLi4uKElzKT47CiAgcmV0dXJuIHN0ZDo6aW5kZXhfc2VxdWVuY2U8c3RkOjpnZXQ8SnM+KGFycmF5X3R7e0lzLi4ufX0pLi4uPigpOwp9Cgp0ZW1wbGF0ZSA8c3RkOjpzaXplX3QgQmVnaW4sIHN0ZDo6c2l6ZV90IEVuZCwgc3RkOjpzaXplX3QuLi4gSXM+CmNvbnN0ZXhwciBkZWNsdHlwZShhdXRvKSBzbGljZShzdGQ6OmluZGV4X3NlcXVlbmNlPElzLi4uPiBpcykgewogIHJldHVybiBzbGljZV9pbXBsKGlzLCBtYWtlX2luZGV4X3JhbmdlPEJlZ2luLCBFbmQ+KCkpOwp9CgovKiBwYXJ0aWFsX3N1bSAqLwoKdGVtcGxhdGUgPHN0ZDo6c2l6ZV90Li4uIElzPgpzdHJ1Y3QgcGFydGlhbF9zdW07Cgp0ZW1wbGF0ZSA8c3RkOjpzaXplX3QuLi4gSXM+CnVzaW5nIHBhcnRpYWxfc3VtX3QgPSB0eXBlbmFtZSBwYXJ0aWFsX3N1bTxJcy4uLj46OnR5cGU7Cgp0ZW1wbGF0ZSA8PgpzdHJ1Y3QgcGFydGlhbF9zdW08PiB7IHVzaW5nIHR5cGUgPSBzdGQ6OmluZGV4X3NlcXVlbmNlPD47IH07Cgp0ZW1wbGF0ZSA8c3RkOjpzaXplX3QgSSwgc3RkOjpzaXplX3QuLi4gSXM+CnN0cnVjdCBwYXJ0aWFsX3N1bTxJLCBJcy4uLj4gewoKICB0ZW1wbGF0ZSA8dHlwZW5hbWUgSnM+CiAgc3RydWN0IGltcGw7CgogIHRlbXBsYXRlIDxzdGQ6OnNpemVfdC4uLiBKcz4KICBzdHJ1Y3QgaW1wbDxzdGQ6OmluZGV4X3NlcXVlbmNlPEpzLi4uPj4gewogICAgdXNpbmcgdHlwZSA9IHN0ZDo6aW5kZXhfc2VxdWVuY2U8SSwgSnMgKyBJLi4uPjsKICB9OwoKICB1c2luZyB0eXBlID0gdHlwZW5hbWUgaW1wbDxwYXJ0aWFsX3N1bV90PElzLi4uPj46OnR5cGU7Cn07CgovKiBzcGxpdF9hbmRfY2FsbCAqLwoKdGVtcGxhdGUgPHR5cGVuYW1lLi4uIEZucywgdHlwZW5hbWUgQXJncywgc3RkOjpzaXplX3QuLi4gSXMsIHN0ZDo6c2l6ZV90Li4uIEpzPgp2b2lkIHNwbGl0X2FuZF9jYWxsX2ltcGwoQXJncyAmJmFyZ3MsCiAgICAgICAgICAgICAgICAgICAgICAgICBzdGQ6OmluZGV4X3NlcXVlbmNlPElzLi4uPiwKICAgICAgICAgICAgICAgICAgICAgICAgIHN0ZDo6aW5kZXhfc2VxdWVuY2U8SnMuLi4+KSB7CiAgaW50IGR1bW15W10gPSB7CiAgICAgIChhcHBseV9pbXBsKEZuc3t9LCBzdGQ6OmZvcndhcmQ8QXJncz4oYXJncyksIG1ha2VfaW5kZXhfcmFuZ2U8SXMsIEpzPnt9KSwKICAgICAgIDApLi4ufTsKICAodm9pZClkdW1teTsKfQoKdGVtcGxhdGUgPHR5cGVuYW1lLi4uIEZucywgdHlwZW5hbWUuLi4gQXJncz4Kdm9pZCBzcGxpdF9hbmRfY2FsbChBcmdzICYmLi4uIGFyZ3MpIHsKICBhdXRvIHBhcnRpYWxfc3VtcyA9IHBhcnRpYWxfc3VtX3Q8MCwgZnVuY3Rpb25fYXJpdHk8Rm5zPnt9Li4uPnt9OwogIGF1dG8gaXMgPSBzbGljZTwwLCBzaXplb2YuLi4oRm5zKT4ocGFydGlhbF9zdW1zKTsKICBhdXRvIGpzID0gc2xpY2U8MSwgc2l6ZW9mLi4uKEZucykgKyAxPihwYXJ0aWFsX3N1bXMpOwogIHNwbGl0X2FuZF9jYWxsX2ltcGw8Rm5zLi4uPigKICAgICAgc3RkOjpmb3J3YXJkX2FzX3R1cGxlKHN0ZDo6Zm9yd2FyZDxBcmdzPihhcmdzKS4uLiksIGlzLCBqcyk7Cn0KCmludCBtYWluKCkgewogIHN0cnVjdCBGIHsgdm9pZCBvcGVyYXRvcigpKGludCB4LCBpbnQgeSkgewogICAgICBzdGQ6OmNvdXQgPDwgIkYoIiA8PCB4IDw8ICIsICIgPDwgeSA8PCAnKScgPDwgc3RkOjplbmRsOwogICAgfQogIH07CiAgc3RydWN0IEcgewogICAgdm9pZCBvcGVyYXRvcigpKGludCB4KSB7IHN0ZDo6Y291dCA8PCAiRygiIDw8IHggPDwgJyknIDw8IHN0ZDo6ZW5kbDsgfQogIH07CiAgc3BsaXRfYW5kX2NhbGw8RiwgRz4oMSwgMiwgMyk7Cn0=