#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>... { __host__ __device__ explicit constexpr TupleImpl() : 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 base::GetElementByKey(detail::TupleElementKey{}); } template __host__ __device__ constexpr auto& At(Number) { static_assert(I < base::Size(), "wrong! out of range"); return base::GetElementByKey(detail::TupleElementKey{}); } }; template __host__ __device__ constexpr auto make_tuple(Xs&&... xs) { return Tuple>...>(std::forward(xs)...); } namespace detail { template __host__ __device__ constexpr auto transform_tuples_impl(F f, const X& x, Sequence) { return make_tuple(f(x.At(Number{}))...); } template __host__ __device__ constexpr auto transform_tuples_impl(F f, const X& x, const Y& y, Sequence) { return make_tuple(f(x.At(Number{}), y.At(Number{}))...); } } // namespace detail template __host__ __device__ constexpr auto transform_tuples(F f, const X& x) { return detail::transform_tuples_impl( f, x, typename arithmetic_sequence_gen<0, X::Size(), 1>::type{}); } template __host__ __device__ constexpr auto transform_tuples(F f, const X& x, const Y& y) { return detail::transform_tuples_impl( f, x, y, typename arithmetic_sequence_gen<0, X::Size(), 1>::type{}); } } // namespace ck #endif