44#pragma once
55
66#include < simple_enum/enum_index.hpp>
7+ #include < optional>
78#include " detail/static_call_operator_prolog.h"
89
910namespace simple_enum ::inline v0_9
1011 {
11- template <enum_concept enum_type_t >
12+ template <enum_concept enumeration >
1213struct enum_bitfield_t ;
1314
1415namespace detail
@@ -30,29 +31,23 @@ namespace detail
3031 return uint64_t {};
3132 }
3233
33- template <enum_concept enum_type_t >
34- using select_storage_for_enum_t = decltype (select_storage_type<enum_size_v<enum_type_t >>());
34+ template <enum_concept enumeration>
35+ using select_storage_for_enum_t = decltype (select_storage_type<enum_size_v<enumeration>>());
36+
37+ constexpr bool test_bit (auto bits, size_t ix) noexcept { return ((bits >> ix) & 1u ) != 0 ; }
3538
3639 // /@brief A proxy object to get/set a specific bit in the parent bitfield.
37- template <typename parent_type, enum_concept enum_type_t >
40+ template <typename parent_type, enum_concept enumeration >
3841 struct bit_proxy_t
3942 {
40- using storage_t = typename enum_bitfield_t <enum_type_t >::storage_t ;
43+ using storage_t = typename enum_bitfield_t <enumeration >::storage_t ;
4144
4245 parent_type & parent_;
43- enum_type_t value_;
44-
45- [[nodiscard]]
46- static constexpr auto get_offset (enum_type_t const value) noexcept -> std::size_t
47- {
48- // enum_size_v/select_storage_for_enum_t would not compile for invalid enum so testing for expected is redudant
49- // here
50- return *enum_index (value);
51- }
46+ enumeration value_;
5247
5348 constexpr auto operator =(std::same_as<bool > auto const bit_value) noexcept -> bit_proxy_t &
5449 {
55- auto const offset = get_offset (value_);
50+ auto const offset = * enum_index (value_);
5651 auto const mask = storage_t (1 ) << offset;
5752
5853 if (bit_value)
@@ -66,7 +61,8 @@ namespace detail
6661 [[nodiscard]]
6762 constexpr operator bool () const noexcept
6863 {
69- return ((parent_.bits_ >> get_offset (value_)) & 1u ) != 0 ;
64+ return test_bit (parent_.bits_ , *enum_index (value_));
65+ // return ((parent_.bits_ >> *enum_index(value_)) & 1u) != 0;
7066 }
7167 };
7268
@@ -85,14 +81,118 @@ namespace detail
8581
8682 template <std::unsigned_integral T, std::size_t N>
8783 inline constexpr T bitmask_v = bitmask_t <T, N>::value;
84+
85+ template <enum_concept enumeration>
86+ struct enum_mask_impl_t
87+ {
88+ using mask_type = select_storage_for_enum_t <enumeration>;
89+ static constexpr size_t size{enum_size_v<enumeration>};
90+
91+ template <size_t N>
92+ static consteval auto op (mask_type init) noexcept -> mask_type
93+ {
94+ if constexpr (N != 0 )
95+ {
96+ if constexpr (is_valid_enumeration_index_v<enumeration>(N - 1 ))
97+ init |= mask_type (mask_type (1u ) << (N - 1 ));
98+ init |= op<N - 1 >(init);
99+ }
100+ return init;
101+ }
102+
103+ static constexpr mask_type value{op<size>(0 )};
104+ };
105+
106+ template <enum_concept enumeration>
107+ inline constexpr auto enum_mask_v = enum_mask_impl_t <enumeration>::value;
108+
109+ template <enum_concept enum_type_t >
110+ struct enum_bitfield_traits_t
111+ {
112+ using storage_t = detail::select_storage_for_enum_t <enum_type_t >;
113+ // mask with eanbled bits of all valid mapped enumerations indexes, it does not enable indexes for holes in enum
114+ static constexpr storage_t bits_mask{detail::enum_mask_v<enum_type_t >};
115+ };
116+
117+ template <enum_concept enumeration>
118+ struct enum_bitfield_iterator_t
119+ {
120+ using traits_type = detail::enum_bitfield_traits_t <enumeration>;
121+ using storage_t = traits_type::storage_t ;
122+ static constexpr storage_t bits_mask{traits_type::bits_mask};
123+
124+ using iterator_category = std::forward_iterator_tag;
125+ using value_type = enumeration;
126+ using difference_type = std::ptrdiff_t ;
127+ using pointer = enumeration const *;
128+ using reference = enumeration const &;
129+
130+ storage_t bits_{};
131+ std::optional<enumeration> current_{};
132+
133+ constexpr enum_bitfield_iterator_t () noexcept = default;
134+
135+ constexpr explicit enum_bitfield_iterator_t (storage_t bits) noexcept : bits_{bits}, current_{}
136+ {
137+ // move to first
138+ static constexpr size_t size{enum_size_v<enumeration>};
139+ for (size_t ix{}; ix != size; ++ix)
140+ if (test_bit (bits_, ix)) // no need to test if it is valid as mask will always maintain that
141+ {
142+ current_ = *emum_index_to_enumeration<enumeration>(ix);
143+ break ;
144+ }
145+ }
146+
147+ constexpr auto operator *() const noexcept -> reference { return *current_; }
148+
149+ constexpr auto operator ->() const noexcept -> pointer { return current_->value (); }
150+
151+ constexpr auto operator ++() noexcept -> enum_bitfield_iterator_t &
152+ {
153+ if (current_)
154+ {
155+ static constexpr size_t size{enum_size_v<enumeration>};
156+ size_t ix{*enum_index (*current_)};
157+ current_.reset ();
158+ for (++ix; ix != size; ++ix)
159+ if (test_bit (bits_, ix)) // no need to test if it is valid as mask will always maintain that
160+ {
161+ current_ = *emum_index_to_enumeration<enumeration>(ix);
162+ break ;
163+ }
164+ }
165+ return *this ;
166+ }
167+
168+ constexpr auto operator ++(int ) noexcept -> enum_bitfield_iterator_t
169+ {
170+ enum_bitfield_iterator_t tmp{*this };
171+ ++(*this );
172+ return tmp;
173+ }
174+
175+ constexpr auto operator ==(enum_bitfield_iterator_t const & other) const noexcept -> bool = default ;
176+ };
88177 } // namespace detail
89178
179+ enum struct enum_bitfield_full_e
180+ {
181+ };
182+
90183// / @brief A template struct providing a bitfield with enum indexing.
91- template <enum_concept enum_type_t >
184+ template <enum_concept enumeration >
92185struct enum_bitfield_t
93186 {
94- using storage_t = detail::select_storage_for_enum_t <enum_type_t >;
95- static constexpr storage_t bits_mask{detail::bitmask_v<storage_t , enum_size_v<enum_type_t >>};
187+ using traits_type = detail::enum_bitfield_traits_t <enumeration>;
188+ using storage_t = traits_type::storage_t ;
189+ static constexpr storage_t bits_mask{traits_type::bits_mask};
190+ using iterator = detail::enum_bitfield_iterator_t <enumeration>;
191+
192+ struct sentinel_t
193+ {
194+ constexpr auto operator ==(iterator const & it) const noexcept { return not it.current_ .has_value (); }
195+ };
96196
97197 storage_t bits_{0 };
98198
@@ -102,31 +202,38 @@ struct enum_bitfield_t
102202
103203 explicit constexpr enum_bitfield_t (std::same_as<storage_t > auto bits) noexcept : bits_{bits} {}
104204
105- template <std::same_as<enum_type_t >... Args>
205+ // constructs will full bits enabled
206+ explicit constexpr enum_bitfield_t (enum_bitfield_full_e) noexcept : bits_{bits_mask} {}
207+
208+ template <std::same_as<enumeration>... Args>
106209 constexpr explicit enum_bitfield_t (Args &&... args) noexcept
107210 {
108211 set_values (std::forward<Args>(args)...);
109212 }
110213
214+ constexpr auto begin () const noexcept -> iterator { return iterator{bits_}; }
215+
216+ constexpr auto end () const noexcept -> sentinel_t { return sentinel_t {}; }
217+
111218 /* *
112219 * @brief Accesses a bit corresponding to an index of enumeration value.
113220 * @returns A proxy object to manipulate the bit.
114221 */
115222 template <typename Self>
116223 [[nodiscard]]
117- constexpr auto operator [](this Self && self, enum_type_t const value) noexcept
224+ constexpr auto operator [](this Self && self, enumeration const value) noexcept
118225 {
119226 return detail::bit_proxy_t {self, value};
120227 }
121228
122- template <std::same_as<enum_type_t >... Args>
123- constexpr void set_values (enum_type_t const & arg, Args &&... args) noexcept
229+ template <std::same_as<enumeration >... Args>
230+ constexpr void set_values (enumeration const & arg, Args &&... args) noexcept
124231 {
125232 detail::bit_proxy_t {*this , arg} = true ;
126233 set_values (std::forward<Args>(args)...);
127234 }
128235
129- constexpr void set_values (enum_type_t const & arg) noexcept { detail::bit_proxy_t {*this , arg} = true ; }
236+ constexpr void set_values (enumeration const & arg) noexcept { detail::bit_proxy_t {*this , arg} = true ; }
130237
131238 [[nodiscard]]
132239 constexpr auto operator ==(enum_bitfield_t const &) const noexcept -> bool
@@ -175,11 +282,11 @@ struct enum_bitfield_t
175282 }
176283 };
177284
178- template <enum_concept enum_type_t >
179- enum_bitfield_t (enum_type_t const & arg) -> enum_bitfield_t <enum_type_t >;
285+ template <enum_concept enumeration >
286+ enum_bitfield_t (enumeration const & arg) -> enum_bitfield_t <enumeration >;
180287
181- template <enum_concept enum_type_t , typename ... Args>
182- enum_bitfield_t (enum_type_t const & arg, Args &&... args) -> enum_bitfield_t <enum_type_t >;
288+ template <enum_concept enumeration , typename ... Args>
289+ enum_bitfield_t (enumeration const & arg, Args &&... args) -> enum_bitfield_t <enumeration >;
183290
184291 } // namespace simple_enum::inline v0_9
185292
0 commit comments