#ifndef CK_TUPLE_HPP #define CK_TUPLE_HPP #include "integral_constant.hpp" #include "type.hpp" #include "Sequence.hpp" namespace ck { namespace detail { template struct TupleElementKey { }; template struct TupleElement { __host__ __device__ explicit constexpr TupleElement() : mData() {} 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>... { #if 1 __host__ __device__ explicit constexpr TupleImpl() : TupleElement, Xs>()... { } #endif 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{}); } }; template __host__ __device__ constexpr auto make_tuple(Xs&&... xs) { return Tuple>...>(std::forward(xs)...); } namespace detail { template __host__ __device__ constexpr auto transpose_tuple_impl(X& x, F f, Sequence) { return make_tuple(f(x.At(Number{}))...); } } // namespace detail template __host__ __device__ constexpr auto transpose_tuple(X& x, F f) { return detail::transpose_tuple_impl( x, f, typename arithmetic_sequence_gen<0, X::Size(), 1>::type{}); } } // namespace ck #endif