Last active
October 20, 2015 08:28
-
-
Save matwey/d2985fb9dcb14302ad33 to your computer and use it in GitHub Desktop.
SO-32235855-1
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 <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; | |
} |
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
#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