Skip to content

Instantly share code, notes, and snippets.

@matwey
Last active October 20, 2015 08:28
Show Gist options
  • Save matwey/d2985fb9dcb14302ad33 to your computer and use it in GitHub Desktop.
Save matwey/d2985fb9dcb14302ad33 to your computer and use it in GitHub Desktop.
SO-32235855-1
#include <tuple>
#include <iostream>
#include "types.h"
template <class T, T... n>
struct expand {
template <template <class T2, T...> class U> using type = U<T, n...>;
};
template <class T, T S, T N>
struct range {
template <T... Ints> using type =
typename range<T, (S+1), N>::template type<Ints..., S>;
};
template <class T, T N>
struct range<T, N, N> {
template <T... Ints> using type = expand<T, Ints...>;
};
template<class T, T... Ints>
struct integer_sequence {
typedef T value_type;
static constexpr std::size_t size() noexcept { return sizeof...(Ints); }
};
template<std::size_t... Ints>
using index_sequence = integer_sequence<std::size_t, Ints...>;
template<class T, T N>
using make_integer_sequence = typename range<T, static_cast<T>(0), N>::template type<>::template type<integer_sequence>;
template<std::size_t N>
using make_index_sequence = make_integer_sequence<std::size_t, N>;
template<class... Args>
using index_sequence_for = make_index_sequence<sizeof...(Args)>;
//call the function with the tuple element at the given index
template<class Ret, int N, class T, class Func>
auto apply_one(T&& p, Func func) -> Ret {
return func( std::get<N>(std::forward<T>(p)) );
}
//call with runtime index
template<class T, class Func, std::size_t... Is>
auto apply(T&& p, int index, Func func, index_sequence<Is...>) -> typename Func::return_type {
using Ret = typename Func::return_type;
using FT = Ret(T&&, Func);
//build up a constexpr array of function pointers to index
static constexpr FT* arr[] = { &apply_one<Ret, Is, T&&, Func>... };
//call the function pointer at the specified index
return arr[index](std::forward<T>(p), func);
}
//tag dispatcher
template<class T, class Func>
auto apply(T&& p, int index, Func func) -> typename Func::return_type {
return apply(std::forward<T>(p), index, func,
make_index_sequence<std::tuple_size<typename std::decay<T>::type>::value>{});
}
int main(int argc, char** argv) {
long long x=0;
test_tuple t;
size_t ntry = 100000000;
for(size_t i = 0; i < ntry; ++i) {
for(size_t j = 0; j < 10; ++j) {
x += apply(t, j, test_visitor{});
}
if(i % (ntry/10) == 0) {
std::cout << "." << std::endl;;
}
}
std::cout << x << " must be " << 55*ntry << std::endl;
return 0;
}
#ifndef _TYPES_H
#define _TYPES_H
#include <tuple>
template<int N>
struct e {};
struct test_visitor {
typedef int return_type;
int operator()(const e<1>& ) const { return 1; }
int operator()(const e<2>& ) const { return 2; }
int operator()(const e<3>& ) const { return 3; }
int operator()(const e<4>& ) const { return 4; }
int operator()(const e<5>& ) const { return 5; }
int operator()(const e<6>& ) const { return 6; }
int operator()(const e<7>& ) const { return 7; }
int operator()(const e<8>& ) const { return 8; }
int operator()(const e<9>& ) const { return 9; }
int operator()(const e<10>& ) const { return 10; }
};
using test_tuple = std::tuple<e<1>,e<2>,e<3>,e<4>,e<5>,e<6>,e<7>,e<8>,e<9>,e<10>>;
#endif // _TYPES_H
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment