#pragma once #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); static constexpr size_t Capacity = CAPACITY; T value; template constexpr T get() const { static_assert(N <= sizeof(T)*8); static_assert(N <= Capacity); return T(value & (T(1) << N) - T(1)); } template constexpr T advance() const { static_assert(N <= sizeof(T)*8); static_assert(N <= Capacity); return T(value >> N); } constexpr bool operator==(const Storage&) const noexcept = default; constexpr bool check_zero() const = delete; template using next = Storage; }; template struct Storage { static constexpr size_t Capacity = 0; T value; template [[maybe_unused]] constexpr T get() const = delete; template [[maybe_unused]] constexpr T advance() const = delete; constexpr bool operator==(const Storage&) const noexcept = default; [[nodiscard]] constexpr inline bool check_zero() const { return value == T(0); } template struct next { static_assert(!std::is_same_v, "reading past the end"); static_assert( std::is_same_v, "reading past the end"); }; }; } // 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