#pragma once #include "compat/assert.hpp" #include #include #include namespace floormat::detail_Pack_output { template struct output_bits final { static_assert(N > 0); static_assert(N < sizeof(size_t)*8); static constexpr size_t length = N; }; template struct output { static_assert(std::is_fundamental_v); static_assert(CAPACITY <= sizeof(T)*8); static constexpr size_t Capacity = CAPACITY; T value{0}; template struct next_ { static_assert(N <= sizeof(T)*8); static_assert(N > 0); static_assert(N <= CAPACITY); using type = output; }; template using next = typename next_::type; template constexpr T set(T x, output_bits) const { static_assert(N <= CAPACITY, "data type too small"); static_assert(N > 0); T value_{value}; if constexpr(CAPACITY != sizeof(T)*8) value_ <<= N; auto x_ = T(x & (T{1}< struct output_field { T value; static constexpr size_t Length = LENGTH; }; template struct count_bits; template struct count_bits, Ts...>> { static constexpr size_t length = N + count_bits>::length; static_assert(length <= sizeof(Int)*8); }; template struct count_bits> { static constexpr size_t length = 0; }; template constexpr std::index_sequence reverse_index_sequence(std::index_sequence const&); template using make_reverse_index_sequence = decltype(reverse_index_sequence(std::make_index_sequence{})); template constexpr T write_(output st, std::index_sequence, const Tuple& tuple) { constexpr size_t N = std::tuple_element_t::Length; if constexpr(Left != sizeof(T)*8) st.value <<= N; T x = std::get(tuple).value; T value = st.set(x, output_bits{}); using next = typename output::template next; return write_(next{value}, std::index_sequence{}, tuple); } template constexpr T write_(output st, std::index_sequence<>, const Tuple&) { return st.value; } } // namespace floormat::detail_Pack_output