#pragma once #include #include #include namespace mln { template struct TypeIndex; template struct TypeIndex : std::integral_constant {}; template struct TypeIndex : std::integral_constant::value> {}; template class IndexedTuple; /// A tuple of Ts, where individual members can be accessed via `t.get()` for I ∈ Is. /// /// See /// https://github.com/mapbox/cpp/blob/1bb519ef25edd6169f1d6d8a65414044616590a9/docs/structural-metaprogramming.md /// for motivation. template class IndexedTuple, TypeList> : public std::tuple { public: static_assert(sizeof...(Is) == sizeof...(Ts), "IndexedTuple size mismatch"); template static constexpr std::size_t getIndex() { return TypeIndex::value; } template constexpr auto& get() { return std::get()>(*this); } template constexpr const auto& get() const { return std::get()>(*this); } template constexpr IndexedTuple(Us&&... other) : std::tuple(std::forward(other)...) {} template constexpr IndexedTuple, TypeList> concat( const IndexedTuple, TypeList>& other) const { return IndexedTuple, TypeList>{get()..., other.template get()...}; } // Help out MSVC++ constexpr bool operator==(const IndexedTuple, TypeList>& other) const { return static_cast&>(*this) == static_cast&>(other); } constexpr bool operator!=(const IndexedTuple, TypeList>& other) const { return !(*this == other); } }; template using ExpandToType = T; } // namespace mln