Last active
March 4, 2016 04:31
-
-
Save bryancatanzaro/b4809392ce984fa7ce49 to your computer and use it in GitHub Desktop.
Call a function by expanding a tuple as its arguments.
This file contains 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 <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