Skip to content

Instantly share code, notes, and snippets.

@nsf
Created October 9, 2013 08:30
Show Gist options
  • Save nsf/6898071 to your computer and use it in GitHub Desktop.
Save nsf/6898071 to your computer and use it in GitHub Desktop.
C++ tuple explode
#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