Created
October 9, 2013 08:30
-
-
Save nsf/6898071 to your computer and use it in GitHub Desktop.
C++ tuple explode
This file contains hidden or 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 <cstdio> | |
#include <tuple> | |
#include <utility> | |
#include <type_traits> | |
template<int ...I> struct index_tuple_type { | |
template<int N> using append = index_tuple_type<I..., N>; | |
}; | |
template<int N> struct make_index_impl { | |
using type = typename make_index_impl<N-1>::type::template append<N-1>; | |
}; | |
template<> struct make_index_impl<0> { using type = index_tuple_type<>; }; | |
template<int N> using index_tuple = typename make_index_impl<N>::type; | |
template <typename I, typename ...Args> | |
struct func_traits; | |
template <typename R, int ...I, typename ...Args> | |
struct func_traits<R, index_tuple_type<I...>, Args...> { | |
template <typename TT, typename FT> | |
static inline R call(TT &&t, FT &&f) { | |
return f(std::get<I>(std::forward<TT>(t))...); | |
} | |
}; | |
#define _explode_variant(_T) \ | |
template <typename FT, typename ...Args, typename R = typename std::result_of<FT(Args&&...)>::type> \ | |
inline R explode(_T t, FT &&f) { \ | |
return func_traits<R, index_tuple<sizeof...(Args)>, Args...> \ | |
::call(std::forward<_T>(t), std::forward<FT>(f)); \ | |
} | |
_explode_variant(const std::tuple<Args...>&) | |
_explode_variant( std::tuple<Args...>&) | |
_explode_variant( std::tuple<Args...>&&) | |
#undef _explode_variant | |
//---------------------------------------------------------------------- | |
void test1(int i, char c) { | |
printf("%d %c\n", i, c); | |
} | |
struct S { | |
int operator()(int, int) { return 5; } | |
double operator()(int) { return 3.14; } | |
}; | |
struct Object { | |
Object() = default; | |
Object(const Object&) { printf("copying\n"); } | |
Object(Object&&) { printf("moving\n"); } | |
}; | |
void test5(Object a, Object b, Object c) { | |
printf("in test5, moving\n"); | |
} | |
void test6(Object a, Object b, Object c) { | |
printf("in test6, copying\n"); | |
} | |
int main() { | |
std::tuple<int, char> t1{57, 'a'}; | |
explode(t1, test1); | |
S s; | |
// test correct return value deduction, based on implicit type conversion | |
std::tuple<float> t2{5}; | |
printf("%f\n", explode(t2, s)); | |
std::tuple<int, int> t3{1, 7}; | |
printf("%d\n", explode(t3, s)); | |
// lambdas | |
auto t4 = std::make_tuple("value: ", 10); | |
explode(std::move(t4), [](const char *prompt, int value) { printf("%s%d\n", prompt, value); }); | |
// move! | |
printf("starting test 5\n"); | |
auto t5 = std::make_tuple(Object{}, Object{}, Object{}); | |
printf("exploding, moving!\n"); | |
explode(std::move(t5), test5); | |
// copy | |
printf("starting test 6\n"); | |
auto t6 = std::make_tuple(Object{}, Object{}, Object{}); | |
printf("exploding, copying!\n"); | |
explode(t6, test6); | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment