#ifndef CK_TUPLE_HPP #define CK_TUPLE_HPP #include "integral_constant.hpp" #include "Sequence.hpp" namespace ck { namespace detail { template struct TupleElementKey { }; template struct TupleElement { template __host__ __device__ explicit constexpr TupleElement(T&& v) : mData(static_cast(v)) { } Data mData; }; template __host__ __device__ constexpr const Data& get_tuple_element(const TupleElement& x) { return x.mData; } template __host__ __device__ constexpr Data& get_tuple_element(TupleElement& x) { return x.mData; } template __host__ __device__ constexpr Data&& get_tuple_element(TupleElement&& x) { return static_cast(x.mData); } template struct TupleImpl; template struct TupleImpl, Xs...> : TupleElement, Xs>... { template __host__ __device__ explicit constexpr TupleImpl(Ys&&... ys) : TupleElement, Xs>(static_cast(ys))... { } __host__ __device__ static constexpr index_t Size() { return sizeof...(Xs); } template __host__ __device__ constexpr const auto& GetElementByKey(TupleElementKey) const { return get_tuple_element>(*this); } template __host__ __device__ constexpr auto& GetElementByKey(TupleElementKey) { return get_tuple_element>(*this); } }; } // namespace detail template struct Tuple : detail::TupleImpl::type, Xs...> { using base = detail::TupleImpl::type, Xs...>; template __host__ __device__ explicit constexpr Tuple(Ys&&... ys) : base(static_cast(ys)...) { } template __host__ __device__ constexpr const auto& At(Number) const { static_assert(I < base::Size(), "wrong! out of range"); return GetElementByKey(detail::TupleElementKey{}); } template __host__ __device__ constexpr auto& At(Number) { static_assert(I < base::Size(), "wrong! out of range"); return GetElementByKey(detail::TupleElementKey{}); } }; } // namespace ck #endif