18 template <bit_
integral INTEGER_TYPE>
28 static constexpr bool is_const = std::is_const_v<integer_type>;
38 template <
typename INTEGER>
44 [[
nodiscard]]
constexpr value_type operator*()
const
52 return bit_number -
other.bit_number;
54 constexpr base_iterator& operator++()
56 if (bit_number <
bit_view(integers).size())
60 constexpr base_iterator operator++(
int)
66 constexpr base_iterator& operator--()
72 constexpr base_iterator operator--(
int)
78 constexpr base_iterator& operator+=(difference_type
n)
80 bit_number = std::clamp(bit_number +
n, 0,
bit_view(integers).size());
83 constexpr base_iterator& operator-=(difference_type
n)
85 bit_number = std::clamp(bit_number +
n, 0,
bit_view(integers).size());
89 [[
nodiscard]]
constexpr base_iterator operator+(difference_type
n)
const;
90 friend constexpr base_iterator operator+(difference_type, base_iterator);
92 [[
nodiscard]]
constexpr base_iterator operator-(difference_type)
const;
93 [[
nodiscard]]
constexpr value_type operator[](difference_type)
const;
98 return integers.data() ==
other.integers.data() && integers.size() ==
other.integers.size() && bit_number ==
other.bit_number;
101 template <
typename U>
104 return std::tie(integers.data(), integers.size(), bit_number) <=> std::tie(
other.integers.data(),
other.integers.size(),
other.bit_number);
107 base_iterator()
noexcept =
default;
109 base_iterator(base_iterator
const&)
noexcept =
default;
110 base_iterator(base_iterator&&)
noexcept =
default;
111 base_iterator& operator=(base_iterator
const&)
noexcept =
default;
112 base_iterator& operator=(base_iterator&&)
noexcept =
default;
119 [[
nodiscard]]
constexpr INTEGER& integer_at_bit(
size_t bit)
const { return ::ghassanpl::at(integers,
bit / integer_type_bit_count); }
120 [[
nodiscard]]
static constexpr size_t real_bit_at_bit(
size_t bit) {
return bit % integer_type_bit_count; }
122 std::span<INTEGER> integers;
129 static_assert(std::random_access_iterator<iterator>);
131 [[
nodiscard]]
constexpr const_iterator begin()
const {
return const_iterator{ m_integers, 0 }; }
132 [[
nodiscard]]
constexpr const_iterator end()
const {
return const_iterator{ m_integers, size() }; }
133 [[
nodiscard]]
constexpr iterator begin() {
return iterator{ m_integers, 0 }; }
134 [[
nodiscard]]
constexpr iterator end() {
return iterator{ m_integers, size() }; }
135 [[
nodiscard]]
constexpr const_iterator cbegin();
136 [[
nodiscard]]
constexpr const_iterator cend();
158 constexpr void set(
size_t index)
requires (!is_const);
159 constexpr void clear(
size_t index)
requires (!is_const);
160 [[
nodiscard]]
constexpr bool is_set(
size_t index)
const;
162 constexpr void set_all()
requires (!is_const);
163 constexpr void clear_all()
requires (!is_const);
164 constexpr void toggle_all()
requires (!is_const);
166 [[
nodiscard]]
constexpr bool are_all_set()
const;
168 template <
typename U>
171 [[
nodiscard]]
constexpr bool are_any_set()
const;
173 template <
typename U>
176 [[
nodiscard]]
constexpr inline size_t size()
const noexcept {
return size_t(m_integers.size() * integer_type_bit_count); }
178 [[
nodiscard]]
constexpr integer_type& integer_at_bit(
size_t bit) { return ::ghassanpl::at(m_integers,
bit / integer_type_bit_count); }
179 [[
nodiscard]]
constexpr integer_type
const& integer_at_bit(
size_t bit)
const { return ::ghassanpl::at(m_integers,
bit / integer_type_bit_count); }
181 [[
nodiscard]]
static constexpr size_t real_bit_at_bit(
size_t bit) {
return bit % integer_type_bit_count; }
183 [[
nodiscard]]
constexpr auto integers()
const noexcept {
return m_integers; }
187 template <
typename U>
189 template <
typename U>
190 constexpr void and_with(
bit_view<U>&
target)
const requires (!std::is_const_v<U>);
191 template <
typename U>
192 constexpr void or_with(
bit_view<U>&
target)
const requires (!std::is_const_v<U>);
193 template <
typename U>
194 constexpr void xor_with(
bit_view<U>&
target)
const requires (!std::is_const_v<U>);
202 [[
nodiscard]]
constexpr integer_type& integer_at_bit_unsafe(
size_t bit) {
return m_integers[
bit / integer_type_bit_count]; }
203 [[
nodiscard]]
constexpr integer_type
const& integer_at_bit_unsafe(
size_t bit)
const {
return m_integers[
bit / integer_type_bit_count]; }
205 std::span<integer_type> m_integers;
208 static_assert(std::ranges::random_access_range<bit_view<int>>);
210 template <std::ranges::contiguous_range RANGE_TYPE>
211 bit_view(
RANGE_TYPE& T) -> bit_view<std::ranges::range_value_t<std::decay_t<
decltype(T)>>>;
212 template <std::ranges::contiguous_range RANGE_TYPE>
213 bit_view(
RANGE_TYPE const& T) -> bit_view<std::ranges::range_value_t<std::decay_t<
decltype(T)>>
const>;
215 template <std::ranges::contiguous_range RANGE_TYPE>
218 using range_value = std::remove_pointer_t<
typename std::iterator_traits<std::ranges::iterator_t<
decltype(
range)>>::pointer>;
222 template <
size_t BIT_NUM, std::ranges::contiguous_range RANGE_TYPE>
225 using range_value = std::remove_pointer_t<
typename std::iterator_traits<std::ranges::iterator_t<
decltype(
range)>>::pointer>;
229 template <bit_
integral VALUE_TYPE>
230 [[
nodiscard]]
auto make_bit_reference(VALUE_TYPE& value,
size_t bit_num)
235 template <
size_t BIT_NUM, bit_
integral VALUE_TYPE>
236 [[
nodiscard]]
auto make_bit_reference(VALUE_TYPE& value)
245template <ghassanpl::bit_
integral VALUE_TYPE>
246struct std::hash<
ghassanpl::bit_view<VALUE_TYPE>>
250 return hash_range(view.integers());
constexpr auto bit_count
Equal to the number of bits in the type.
std::ranges::range_value_t< std::decay_t< RANGE > > range_value
Helper template to get the value type of a type that decays to a range
Primary namespace for everything in this library.
Models a reference to a specific bit in a variable. Can be a statically-defined bit number (BIT_NUM !...
A view over an integral value allowing for iteration and modification of its individual bits.
constexpr void copy_to(bit_view< U > &target) const
[[nodiscard]] constexpr bit_view<integer_type> subview(size_t starting_at_bit, size_t bit_count) cons...