#pragma once #include "compat/assert.hpp" #include #include namespace floormat::Pack { template struct Bits_; } // namespace floormat::Pack namespace floormat::detail_Pack { using namespace floormat::Pack; template struct check_size_overflow; template struct check_size_overflow, Xs...> { static_assert(std::is_same_v); static constexpr auto acc = Sum + size_t{N}; using next_check = check_size_overflow; static constexpr auto size = next_check::size; static constexpr bool result = next_check::result; }; template struct check_size_overflow { static constexpr size_t size = Sum; static constexpr bool result = Sum <= sizeof(T)*8; }; template struct Storage { static_assert(Capacity <= sizeof(T)*8); T value; template constexpr T get() { static_assert(N <= sizeof(T)*8); static_assert(N <= Capacity); return T(value & (T(1) << N) - T(1)); } template constexpr T advance() { static_assert(N <= sizeof(T)*8); static_assert(N <= Capacity); return T(value >> N); } template [[maybe_unused]] constexpr bool check_zero() = delete; template using next = Storage; }; template struct Storage { T value; template [[maybe_unused]] constexpr T get() = delete; template [[maybe_unused]] constexpr T advance() = delete; template constexpr inline bool check_zero() { fm_assert(value == T(0)); return true; } template struct next { static_assert(!std::is_same_v, "reading past the end"); static_assert( std::is_same_v, "can't happen!"); }; }; } // namespace floormat::detail_Pack namespace floormat::Pack { template struct Bits_ final { static_assert(std::is_fundamental_v); static_assert(N > 0); static_assert(N < sizeof(T)*8); using type = T; static constexpr auto bits = N; }; } // namespace floormat::Pack