@@ -144,8 +144,8 @@ struct FlagsHelper final {
144144 {
145145 constexpr std::array<bool , sizeof ...(I)> valid{isValid<static_cast <E>(MinScan + I)>()...};
146146 constexpr auto count{std::count_if (valid.cbegin (), valid.cend (), [](bool v) noexcept { return v; })};
147- static_assert (count > 0 , " Requiring non-empty enum! " );
148- static_assert (count <= MaxUnderScan, " Underlying type of enum has less digits than given expected! " );
147+ static_assert (count > 0 , " EnumFlag requires at least one enum value. Check that your enum has consecutive values starting from 0. " );
148+ static_assert (count <= MaxUnderScan, " Too many enum values for underlying type. Consider using a larger underlying type or fewer enum values. " );
149149 std::array<E, count> values{};
150150 for (size_t idx{}, n{}; n < count; ++idx) {
151151 if (valid[idx]) {
@@ -173,7 +173,7 @@ struct FlagsHelper final {
173173 }
174174 if constexpr (tpeek_v<e>[tp + getSpec<SVal::Start, SType::Enum_t>().size ()] == getSpec<SVal::AnonStart, SType::Enum_t>()) {
175175#if defined __clang__
176- if constexpr (tpeek_v<e>[tp + getSpec<SVal::Start, SType::enum_t >().size () + 1 ] == getSpec<SVal::AnonStart, SType::Enum_t>()) {
176+ if constexpr (tpeek_v<e>[tp + getSpec<SVal::Start, SType::Enum_t >().size () + 1 ] == getSpec<SVal::AnonStart, SType::Enum_t>()) {
177177 return {};
178178 }
179179#endif
@@ -215,7 +215,7 @@ struct FlagsHelper final {
215215 template <E e>
216216 static constexpr auto getNameValue{getName<e>()};
217217
218- template <bool with_scope, std:: size_t ... I>
218+ template <bool with_scope, size_t ... I>
219219 static constexpr auto getNames (std::index_sequence<I...> /* unused*/ )
220220 {
221221 if constexpr (with_scope) {
@@ -248,7 +248,7 @@ struct FlagsHelper final {
248248
249249 static constexpr std::optional<E> fromString (std::string_view str) noexcept
250250 {
251- for (std:: size_t i{0 }; i < count (); ++i) {
251+ for (size_t i{0 }; i < count (); ++i) {
252252 if (Names[i] == str || NamesScoped[i] == str) {
253253 return Values[i];
254254 }
@@ -371,13 +371,18 @@ class EnumFlags
371371 constexpr EnumFlags (const EnumFlags&) = default;
372372 // Move constructor.
373373 constexpr EnumFlags (EnumFlags&&) = default;
374- // Constructor to initialize with the underlyiny type.
374+ // Constructor to initialize with the underlying type.
375375 constexpr explicit EnumFlags (U u) : mBits(u) {}
376376 // Initialize with a list of flags.
377377 constexpr EnumFlags (std::initializer_list<E> flags) noexcept
378378 {
379379 std::for_each (flags.begin (), flags.end (), [this ](const E f) noexcept { mBits |= to_bit (f); });
380380 }
381+ // Init from a string.
382+ EnumFlags (const std::string& str)
383+ {
384+ set (str);
385+ }
381386 // Destructor.
382387 constexpr ~EnumFlags () = default ;
383388
@@ -415,7 +420,7 @@ class EnumFlags
415420 }
416421 }
417422 // Returns the raw bitset value.
418- constexpr auto value () const noexcept
423+ [[nodiscard]] constexpr auto value () const noexcept
419424 {
420425 return mBits ;
421426 }
@@ -442,6 +447,13 @@ class EnumFlags
442447 return (mBits & to_bit (t)) != None;
443448 }
444449
450+ // Tests if all specified flags are set.
451+ template <typename ... Ts>
452+ [[nodiscard]] constexpr bool test (Ts... flags) const noexcept
453+ {
454+ return ((test (flags) && ...));
455+ }
456+
445457 // Sets a specific flag.
446458 template <typename T>
447459 requires std::is_same_v<T, E>
@@ -505,27 +517,27 @@ class EnumFlags
505517 }
506518
507519 // Checks if any flag is set (Boolean context).
508- constexpr explicit operator bool () const noexcept
520+ [[nodiscard]] constexpr explicit operator bool () const noexcept
509521 {
510522 return any ();
511523 }
512524
513525 // Check if given flag is set.
514526 template <typename T>
515527 requires std::is_same_v<T, E>
516- constexpr bool operator [](const T t) noexcept
528+ [[nodiscard]] constexpr bool operator [](const T t) const noexcept
517529 {
518530 return test (t);
519531 }
520532
521533 // Checks if two flag sets are equal.
522- constexpr bool operator ==(const EnumFlags& o) const noexcept
534+ [[nodiscard]] constexpr bool operator ==(const EnumFlags& o) const noexcept
523535 {
524536 return mBits == o.mBits ;
525537 }
526538
527539 // Checks if two flag sets are not equal.
528- constexpr bool operator !=(const EnumFlags& o) const noexcept
540+ [[nodiscard]] constexpr bool operator !=(const EnumFlags& o) const noexcept
529541 {
530542 return mBits != o.mBits ;
531543 }
@@ -584,7 +596,13 @@ class EnumFlags
584596 // Performs a bitwise XOR with another flag set.
585597 constexpr EnumFlags operator ^(const EnumFlags& o) const noexcept
586598 {
587- return Flags (mBits ^ o.mBits );
599+ return EnumFlags (mBits ^ o.mBits );
600+ }
601+
602+ // Performs a bitwise and with another flag set.
603+ constexpr EnumFlags operator &(const EnumFlags& o) const noexcept
604+ {
605+ return EnumFlags (mBits & o.mBits );
588606 }
589607
590608 // Performs a bitwise XOR assignment.
@@ -596,14 +614,14 @@ class EnumFlags
596614
597615 // Checks if all specified flags are set.
598616 template <typename ... Ts>
599- constexpr bool all_of (Ts... flags) const noexcept
617+ [[nodiscard]] constexpr bool all_of (Ts... flags) const noexcept
600618 {
601- return (( test (flags) && ...) );
619+ return test (flags...);
602620 }
603621
604622 // Checks if none of the specified flags are set.
605623 template <typename ... Ts>
606- constexpr bool none_of (Ts... flags) const noexcept
624+ [[nodiscard]] constexpr bool none_of (Ts... flags) const noexcept
607625 {
608626 return (!(test (flags) || ...));
609627 }
@@ -627,35 +645,29 @@ class EnumFlags
627645 // Counts the number of set bits (active flags).
628646 [[nodiscard]] constexpr size_t count () const noexcept
629647 {
630- size_t c{0 };
631- for (size_t i{H::Min_u_v}; i < H::Max_u_v; ++i) {
632- if ((mBits & (U (1 ) << i)) != U (0 )) {
633- ++c;
634- }
635- }
636- return c;
648+ return std::popcount (mBits );
637649 }
638650
639651 // Returns the union of two flag sets.
640- constexpr EnumFlags union_with (const EnumFlags& o) const noexcept
652+ [[nodiscard]] constexpr EnumFlags union_with (const EnumFlags& o) const noexcept
641653 {
642654 return EnumFlags (mBits | o.mBits );
643655 }
644656
645657 // Returns the intersection of two flag sets.
646- constexpr EnumFlags intersection_with (const EnumFlags& o) const noexcept
658+ [[nodiscard]] constexpr EnumFlags intersection_with (const EnumFlags& o) const noexcept
647659 {
648660 return EnumFlags (mBits & o.mBits );
649661 }
650662
651663 // Checks if all flags in another Flags object are present in the current object.
652- constexpr bool contains (const EnumFlags& other) const noexcept
664+ [[nodiscard]] constexpr bool contains (const EnumFlags& other) const noexcept
653665 {
654666 return (mBits & other.mBits ) == other.mBits ;
655667 }
656668
657669 private:
658- // Set implemnetation , bits was zeroed before.
670+ // Set implementation , bits was zeroed before.
659671 void setImpl (const std::string& s, int base = 2 )
660672 {
661673 if (std::all_of (s.begin (), s.end (), [](unsigned char c) { return std::isdigit (c); })) {
@@ -669,15 +681,20 @@ class EnumFlags
669681 throw std::out_of_range (" Values exceeds enum range." );
670682 }
671683 mBits = static_cast <U>(v);
672- } else if (std::all_of (s.begin (), s.end (), [](unsigned char c) { return std::isalnum (c) != 0 || c == ' |' || c == ' ' || c == ' :' || c == ' ,' ; })) {
684+ } else if (std::all_of (s.begin (), s.end (), [](unsigned char c) { return std::isalnum (c) != 0 || c == ' |' || c == ' ' || c == ' :' || c == ' ,' || c == ' ; ' ; })) {
673685 std::string cs{s};
674686 std::transform (cs.begin (), cs.end (), cs.begin (), [](unsigned char c) { return std::tolower (c); });
675687 if (cs == H::All) {
676688 mBits = All;
677689 } else if (cs == H::None) {
678690 mBits = None;
679691 } else {
680- char token = (s.find (' ,' ) != std::string::npos) ? ' ,' : ' |' ;
692+ // accept as delimiter ' ', '|', ';', ','
693+ char token = ' ' ;
694+ std::string::size_type pos = s.find_first_of (" ,|;" );
695+ if (pos != std::string::npos) {
696+ token = s[pos];
697+ }
681698 for (const auto & tok : Str::tokenize (s, token)) {
682699 if (auto e = H::fromString (tok)) {
683700 mBits |= to_bit (*e);
0 commit comments