Skip to content

Instantly share code, notes, and snippets.

@bryancatanzaro
Last active March 4, 2016 04:31
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save bryancatanzaro/b4809392ce984fa7ce49 to your computer and use it in GitHub Desktop.
Save bryancatanzaro/b4809392ce984fa7ce49 to your computer and use it in GitHub Desktop.
Call a function by expanding a tuple as its arguments.
#include <iostream>
#include <tuple>
/******************
* Implementation *
******************/
//If you're using C++14, just use std::integer_sequence
//instead of all this index_seq stuff
template<unsigned... Indices>
struct index_seq {
template<unsigned N>
using append = index_seq<Indices..., N>;
};
template<unsigned Size>
struct make_index_seq {
using type = typename make_index_seq<Size-1>::type
::template append<Size-1>;
};
template<>
struct make_index_seq<0u>
{
using type = index_seq<>;
};
template<typename Fn, typename Tuple, unsigned... I>
auto call_impl(Fn fn, Tuple&& t,
index_seq<I...>) ->
decltype(fn(std::get<I>(t)...))
{
return fn(std::get<I>(t)...);
}
template<typename Tuple>
struct call_indices {
using type = typename
make_index_seq<std::tuple_size<Tuple>::value>::type;
};
/***********************************
* This is the thing that you call *
***********************************/
template<typename Fn, typename Tuple>
auto call(Fn fn, Tuple args) ->
decltype(call_impl(fn, args,
std::declval<typename call_indices<Tuple>::type>()))
{
using indices = typename call_indices<Tuple>::type;
return call_impl(fn, args, indices());
}
/***********
* Testing *
***********/
struct apple {
int val;
};
struct orange {
int val;
};
orange foo(int a, double b, apple c, double d, float e) {
std::cout << a << ' ' << b << ' '
<< c.val << ' ' << d << ' '
<< e << std::endl;
return orange{17};
}
int bar(apple a, apple b, apple c, apple d, apple e) {
return a.val + b.val + c.val + d.val + e.val;
}
int main() {
std::pair<int, double> x = std::make_tuple(1, 2.78);
std::tuple<apple, double, float> y = std::make_tuple(apple{3}, 4.2, 5.25);
auto combined = std::tuple_cat(x, y);
orange result = call(foo, combined);
std::cout << result.val << std::endl;
std::pair<apple, apple> z = std::make_tuple(apple{1}, apple{2});
std::tuple<apple, apple, apple> w =
std::make_tuple(apple{3}, apple{4}, apple{5});
int sum = call(bar, std::tuple_cat(z, w));
std::cout << sum << std::endl;
return 0;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment