From b277d605b208daff23f7c126e33e4bba81f1affb Mon Sep 17 00:00:00 2001 From: Tobias Leibner <tobias.leibner@googlemail.com> Date: Fri, 7 Jul 2017 13:48:15 +0200 Subject: [PATCH] [tuple] add tuple_element with template recursion depth of O(log(N)) --- dune/xt/common/tuple.hh | 49 +++++++++++++++++++++++++++++++++++++++-- 1 file changed, 47 insertions(+), 2 deletions(-) diff --git a/dune/xt/common/tuple.hh b/dune/xt/common/tuple.hh index 00942eae1..1af14ee56 100644 --- a/dune/xt/common/tuple.hh +++ b/dune/xt/common/tuple.hh @@ -237,13 +237,17 @@ struct Combine } // namespace TupleProduct -// from https://stackoverflow.com/questions/17424477/implementation-c14-make-integer-sequence/17426611 +//! from https://stackoverflow.com/questions/17424477/implementation-c14-make-integer-sequence/17426611 template <size_t... Is> struct index_sequence { using type = index_sequence; }; + +namespace internal { + + template <class S1, class S2> struct Concat; template <class S1, class S2> @@ -256,6 +260,9 @@ struct Concat<index_sequence<I1...>, index_sequence<I2...>> }; +} // namespace internal + + template <size_t N> struct make_index_sequence; template <size_t N> @@ -264,7 +271,7 @@ using make_index_sequence_t = typename make_index_sequence<N>::type; template <size_t N> struct make_index_sequence { - using type = Concat_t<make_index_sequence_t<N / 2>, make_index_sequence_t<N - N / 2>>; + using type = internal::Concat_t<make_index_sequence_t<N / 2>, make_index_sequence_t<N - N / 2>>; }; // break conditions @@ -298,6 +305,44 @@ struct make_identical_tuple<T, N, index_sequence<Indices...>> } }; +//! implementation of std::tuple_element with O(log(N)) template recursion depth +//! from https://stackoverflow.com/questions/18593057/stdtuple-element-need-deep-template-instantination +namespace internal { +template <std::size_t> +struct Any +{ + Any(...) + { + } +}; + +template <typename T> +struct wrapper +{ + using type = T; +}; + +template <std::size_t... Is> +struct get_nth_helper +{ + template <typename T> + static auto deduce(Any<Is>..., wrapper<T>, ...) -> wrapper<T>; +}; + +template <std::size_t... Is, typename... Ts> +auto deduce_seq(index_sequence<Is...>, wrapper<Ts>... pp) -> decltype(get_nth_helper<Is...>::deduce(pp...)); +} + +template <std::size_t N, class Tuple> +struct tuple_element; + +template <std::size_t N, class... Ts> +struct tuple_element<N, std::tuple<Ts...>> +{ + using wrapped_type = decltype(internal::deduce_seq(make_index_sequence_t<N>{}, internal::wrapper<Ts>()...)); + using type = typename wrapped_type::type; +}; + } // namespace Common } // namespace XT } // namespace Dune -- GitLab