1 #pragma once 2 3 #include <mbgl/util/type_list.hpp> 4 #include <mbgl/util/tuple.hpp> 5 6 #include <type_traits> 7 8 namespace mbgl { 9 10 template <class T, class... Ts> 11 struct TypeIndex; 12 13 template <class T, class... Ts> 14 struct TypeIndex<T, T, Ts...> : std::integral_constant<std::size_t, 0> {}; 15 16 template <class T, class U, class... Ts> 17 struct TypeIndex<T, U, Ts...> : std::integral_constant<std::size_t, 1 + TypeIndex<T, Ts...>::value> {}; 18 19 template <class...> class IndexedTuple; 20 21 // A tuple of Ts, where individual members can be accessed via `t.get<I>()` for I ∈ Is. 22 // 23 // See https://github.com/mapbox/cpp/blob/master/C%2B%2B%20Structural%20Metaprogramming.md 24 // for motivation. 25 // 26 template <class... Is, class... Ts> 27 class IndexedTuple<TypeList<Is...>, TypeList<Ts...>> : public tuple_polyfill<Ts...> { 28 public: 29 static_assert(sizeof...(Is) == sizeof...(Ts), "IndexedTuple size mismatch"); 30 31 using tuple_polyfill<Ts...>::tuple; 32 33 template <class I> get()34 auto& get() { 35 return get_polyfill<TypeIndex<I, Is...>::value>(*this); 36 } 37 38 template <class I> get() const39 const auto& get() const { 40 return get_polyfill<TypeIndex<I, Is...>::value>(*this); 41 } 42 43 template <class... Js, class... Us> 44 IndexedTuple<TypeList<Is..., Js...>, TypeList<Ts..., Us...>> concat(const IndexedTuple<TypeList<Js...>,TypeList<Us...>> & other) const45 concat(const IndexedTuple<TypeList<Js...>, TypeList<Us...>>& other) const { 46 return IndexedTuple<TypeList<Is..., Js...>, TypeList<Ts..., Us...>> { 47 get<Is>()..., 48 other.template get<Js>()... 49 }; 50 } 51 }; 52 53 } // namespace mbgl 54