Browse Source

Merge topic 'enum_set-enhancements'

77ab2446d4 enum_set enhancements, step 2

Acked-by: Kitware Robot <[email protected]>
Acked-by: buildbot <[email protected]>
Merge-request: !10272
Brad King 10 months ago
parent
commit
eacc728729
2 changed files with 106 additions and 114 deletions
  1. 24 34
      Tests/CMakeLib/testCMExtEnumSet.cxx
  2. 82 80
      Utilities/std/cmext/enum_set

+ 24 - 34
Tests/CMakeLib/testCMExtEnumSet.cxx

@@ -68,21 +68,6 @@ void testDeclaration()
       ++failed;
     }
   }
-  {
-    enum class Test : std::uint8_t
-    {
-      A,
-      B,
-      C,
-      D,
-      cm_count = D
-    };
-    cm::enum_set<Test> testSet1;
-
-    if (testSet1.size() != 0 || testSet1.max_size() != 4) {
-      ++failed;
-    }
-  }
 }
 
 void testIteration()
@@ -94,10 +79,9 @@ void testIteration()
     A,
     B,
     C,
-    D,
-    cm_count = D
+    D
   };
-  cm::enum_set<Test> testSet{ Test::A, Test::C, Test::B };
+  cm::enum_set<Test, 4> testSet{ Test::A, Test::C, Test::B };
 
   if (testSet.size() != 3) {
     ++failed;
@@ -134,8 +118,7 @@ void testEdition()
     B,
     C,
     D,
-    E,
-    cm_count = E
+    E
   };
 
   {
@@ -281,32 +264,42 @@ void testEdition()
     }
   }
   {
-    cm::enum_set<Test> testSet1;
-    cm::enum_set<Test> testSet2{ Test::A, Test::C, Test::B };
+    using ESet = cm::enum_set<Test, 5>;
+    ESet testSet1;
+    ESet testSet2{ Test::A, Test::C, Test::B };
 
     testSet1.set();
     if (testSet1.size() != 5 || testSet1.size() != testSet1.max_size()) {
       ++failed;
     }
-    testSet1.flip(Test::D | Test::E);
+    testSet1.flip({ Test::D, Test::E });
     if (testSet1.size() != 3 || testSet1 != testSet2) {
       ++failed;
     }
-    testSet1.flip(Test::D);
-    testSet2 += Test::D;
+    testSet1.flip(Test::D | Test::E);
+    testSet2 += Test::D + Test::E;
+    if (testSet1.size() != 5 || testSet1 != testSet2) {
+      ++failed;
+    }
+    testSet1.flip(Test::E);
+    testSet2 -= Test::E;
     if (testSet1.size() != 4 || testSet1 != testSet2) {
       ++failed;
     }
     testSet1 ^= { Test::A, Test::B, Test::E, Test::D };
-    testSet2 = Test::C + Test::E;
+    testSet2 = { Test::C, Test::E };
     if (testSet1.size() != 2 || testSet1 != testSet2) {
       ++failed;
     }
-    testSet1 ^= Test::A | Test::B | Test::E;
+    testSet1 ^= { Test::A, Test::B, Test::E };
     testSet2 = { Test::A, Test::B, Test::C };
     if (testSet1.size() != 3 || testSet1 != testSet2) {
       ++failed;
     }
+    testSet2 = Test::A | Test::B | Test::C;
+    if (testSet1.size() != 3 || testSet1 != testSet2) {
+      ++failed;
+    }
   }
 }
 
@@ -320,8 +313,7 @@ void testChecks()
       A,
       B,
       C,
-      D,
-      cm_count = D
+      D
     };
 
     cm::enum_set<Test> testSet;
@@ -353,11 +345,10 @@ void testChecks()
       A,
       B,
       C,
-      D,
-      cm_count = D
+      D
     };
 
-    cm::enum_set<Test> testSet;
+    cm::enum_set<Test, 4> testSet;
 
     if (!testSet.none()) {
       ++failed;
@@ -382,8 +373,7 @@ void testChecks()
       A,
       B,
       C,
-      D,
-      cm_count = D
+      D
     };
 
     cm::enum_set<Test> testSet1;

+ 82 - 80
Utilities/std/cmext/enum_set

@@ -31,12 +31,6 @@
 // enum class Example : unsigned { A, B, C, D };
 // using ExampleSet = enum_set<Example, 4>;
 //
-// Another possibility is to add, at the end of the list, the definition
-// 'cm_count' with the value of the precedent definition:
-//
-//   enum class Example : unsigned { A, B, C, D, cm_count = D };
-//   using ExampleSet = enum_set<Example>;
-//
 // To facilitate the usage of the enum_set, operators '+' and '|' can be used
 // as alternate to the 'initializer_list':
 //
@@ -47,21 +41,6 @@
 
 namespace cm {
 
-namespace internals {
-template <typename Enum, typename U = void>
-struct enum_size
-{
-  static constexpr auto value =
-    std::numeric_limits<typename std::underlying_type<Enum>::type>::digits;
-};
-template <typename Enum>
-struct enum_size<Enum, cm::void_t<decltype(Enum::cm_count)>>
-{
-  static constexpr auto value =
-    static_cast<typename std::underlying_type<Enum>::type>(Enum::cm_count) + 1;
-};
-}
-
 template <typename EnumSet>
 class enum_set_iterator
 {
@@ -144,7 +123,9 @@ private:
 };
 
 template <
-  typename Enum, std::size_t Size = internals::enum_size<Enum>::value,
+  typename Enum,
+  std::size_t Size =
+    std::numeric_limits<typename std::underlying_type<Enum>::type>::digits,
   typename cm::enable_if_t<
     cm::is_scoped_enum<Enum>::value &&
       std::is_unsigned<typename std::underlying_type<Enum>::type>::value,
@@ -152,6 +133,8 @@ template <
 class enum_set
 {
 public:
+  static constexpr std::size_t set_size = Size;
+
   using key_type = Enum;
   using value_type = Enum;
   using size_type = typename std::underlying_type<Enum>::type;
@@ -169,6 +152,14 @@ public:
   constexpr enum_set() noexcept = default;
   enum_set(key_type e) { this->insert(e); }
   enum_set(enum_set const& other) noexcept { this->insert(other); }
+  template <typename E,
+            typename cm::enable_if_t<std::is_same<Enum, E>::value, int> = 0>
+  enum_set(enum_set<E> const& other) noexcept
+  {
+    static_assert(Size < enum_set<E>::set_size, "Incompatible sizes");
+
+    this->insert(other.cbegin(), other.cend());
+  }
   enum_set(std::initializer_list<value_type> list) { this->insert(list); }
 
   enum_set& operator=(key_type e)
@@ -446,12 +437,12 @@ public:
   }
 
 private:
-  template <typename E>
-  friend inline bool operator==(enum_set<E> const& lhs,
-                                enum_set<E> const& rhs) noexcept;
+  template <typename E, std::size_t S>
+  friend inline bool operator==(enum_set<E, S> const& lhs,
+                                enum_set<E, S> const& rhs) noexcept;
 
-  template <typename E, typename Predicate>
-  friend inline void erase_if(enum_set<E>& set, Predicate pred);
+  template <typename E, std::size_t S, typename Predicate>
+  friend inline void erase_if(enum_set<E, S>& set, Predicate pred);
 
   friend class enum_set_iterator<enum_set>;
   friend class enum_set_iterator<enum_set const>;
@@ -462,99 +453,104 @@ private:
 };
 
 // non-member functions for enum_set
-template <typename Enum>
-inline enum_set<Enum> operator+(enum_set<Enum> const& lhs, Enum rhs)
+template <typename Enum, std::size_t Size>
+inline enum_set<Enum, Size> operator+(enum_set<Enum, Size> const& lhs,
+                                      Enum rhs)
 {
-  return enum_set<Enum>{ lhs } += rhs;
+  return enum_set<Enum, Size>{ lhs } += rhs;
 }
-template <typename Enum>
-inline enum_set<Enum> operator+(enum_set<Enum> const& lhs,
-                                enum_set<Enum> const& rhs) noexcept
+template <typename Enum, std::size_t Size>
+inline enum_set<Enum, Size> operator+(enum_set<Enum, Size> const& lhs,
+                                      enum_set<Enum, Size> const& rhs) noexcept
 {
-  return enum_set<Enum>{ lhs } += rhs;
+  return enum_set<Enum, Size>{ lhs } += rhs;
 }
-template <typename Enum>
-inline enum_set<Enum> operator+(enum_set<Enum> const& lhs,
-                                std::initializer_list<Enum> const rhs)
+template <typename Enum, std::size_t Size>
+inline enum_set<Enum, Size> operator+(enum_set<Enum, Size> const& lhs,
+                                      std::initializer_list<Enum> const rhs)
 {
-  return enum_set<Enum>{ lhs } += rhs;
+  return enum_set<Enum, Size>{ lhs } += rhs;
 }
 
-template <typename Enum>
-inline cm::enum_set<Enum> operator|(cm::enum_set<Enum> const& lhs, Enum rhs)
+template <typename Enum, std::size_t Size>
+inline cm::enum_set<Enum, Size> operator|(cm::enum_set<Enum, Size> const& lhs,
+                                          Enum rhs)
 {
-  return enum_set<Enum>{ lhs } |= rhs;
+  return enum_set<Enum, Size>{ lhs } |= rhs;
 }
-template <typename Enum>
-inline cm::enum_set<Enum> operator|(Enum lhs, cm::enum_set<Enum> const& rhs)
+template <typename Enum, std::size_t Size>
+inline cm::enum_set<Enum, Size> operator|(Enum lhs,
+                                          cm::enum_set<Enum, Size> const& rhs)
 {
-  return enum_set<Enum>{ lhs } |= rhs;
+  return enum_set<Enum, Size>{ lhs } |= rhs;
 }
-template <typename Enum>
-inline cm::enum_set<Enum> operator|(cm::enum_set<Enum> const& lhs,
-                                    cm::enum_set<Enum> const& rhs)
+template <typename Enum, std::size_t Size>
+inline cm::enum_set<Enum, Size> operator|(cm::enum_set<Enum, Size> const& lhs,
+                                          cm::enum_set<Enum, Size> const& rhs)
 {
-  return enum_set<Enum>{ lhs } |= rhs;
+  return enum_set<Enum, Size>{ lhs } |= rhs;
 }
 
-template <typename Enum>
-inline enum_set<Enum> operator-(enum_set<Enum> const& lhs, Enum rhs)
+template <typename Enum, std::size_t Size>
+inline enum_set<Enum, Size> operator-(enum_set<Enum, Size> const& lhs,
+                                      Enum rhs)
 {
-  return enum_set<Enum>{ lhs } -= rhs;
+  return enum_set<Enum, Size>{ lhs } -= rhs;
 }
-template <typename Enum>
-inline enum_set<Enum> operator-(enum_set<Enum> const& lhs,
-                                enum_set<Enum> const& rhs) noexcept
+template <typename Enum, std::size_t Size>
+inline enum_set<Enum, Size> operator-(enum_set<Enum, Size> const& lhs,
+                                      enum_set<Enum, Size> const& rhs) noexcept
 {
-  return enum_set<Enum>{ lhs } -= rhs;
+  return enum_set<Enum, Size>{ lhs } -= rhs;
 }
-template <typename Enum>
-inline enum_set<Enum> operator-(enum_set<Enum> const& lhs,
-                                std::initializer_list<Enum> const rhs)
+template <typename Enum, std::size_t Size>
+inline enum_set<Enum, Size> operator-(enum_set<Enum, Size> const& lhs,
+                                      std::initializer_list<Enum> const rhs)
 {
-  return enum_set<Enum>{ lhs } -= rhs;
+  return enum_set<Enum, Size>{ lhs } -= rhs;
 }
 
-template <typename Enum>
-inline enum_set<Enum> operator^(enum_set<Enum> const& lhs, Enum rhs)
+template <typename Enum, std::size_t Size>
+inline enum_set<Enum, Size> operator^(enum_set<Enum, Size> const& lhs,
+                                      Enum rhs)
 {
-  return enum_set<Enum>{ lhs } ^= rhs;
+  return enum_set<Enum, Size>{ lhs } ^= rhs;
 }
-template <typename Enum>
-inline enum_set<Enum> operator^(enum_set<Enum> const& lhs,
-                                enum_set<Enum> const& rhs) noexcept
+template <typename Enum, std::size_t Size>
+inline enum_set<Enum, Size> operator^(enum_set<Enum, Size> const& lhs,
+                                      enum_set<Enum, Size> const& rhs) noexcept
 {
-  return enum_set<Enum>{ lhs } ^= rhs;
+  return enum_set<Enum, Size>{ lhs } ^= rhs;
 }
-template <typename Enum>
-inline enum_set<Enum> operator^(enum_set<Enum> const& lhs,
-                                std::initializer_list<Enum> const rhs)
+template <typename Enum, std::size_t Size>
+inline enum_set<Enum, Size> operator^(enum_set<Enum, Size> const& lhs,
+                                      std::initializer_list<Enum> const rhs)
 {
-  return enum_set<Enum>{ lhs } ^= rhs;
+  return enum_set<Enum, Size>{ lhs } ^= rhs;
 }
 
-template <typename Enum>
-inline bool operator==(enum_set<Enum> const& lhs,
-                       enum_set<Enum> const& rhs) noexcept
+template <typename Enum, std::size_t Size>
+inline bool operator==(enum_set<Enum, Size> const& lhs,
+                       enum_set<Enum, Size> const& rhs) noexcept
 {
   return lhs.Set == rhs.Set;
 }
 
-template <typename Enum>
-inline bool operator!=(enum_set<Enum> const& lhs,
-                       enum_set<Enum> const& rhs) noexcept
+template <typename Enum, std::size_t Size>
+inline bool operator!=(enum_set<Enum, Size> const& lhs,
+                       enum_set<Enum, Size> const& rhs) noexcept
 {
   return !(lhs == rhs);
 }
 
-template <typename Enum>
-inline void erase(enum_set<Enum>& set, Enum value)
+template <typename Enum, std::size_t Size>
+inline void erase(enum_set<Enum, Size>& set, Enum value)
 {
   set.erase(value);
 }
 
-template <typename Enum, typename Predicate>
-inline void erase_if(enum_set<Enum>& set, Predicate pred)
+template <typename Enum, std::size_t Size, typename Predicate>
+inline void erase_if(enum_set<Enum, Size>& set, Predicate pred)
 {
   for (std::size_t index = 0; index < set.Set.size(); ++index) {
     if (set.Set.test(index) && pred(static_cast<Enum>(index))) {
@@ -564,6 +560,12 @@ inline void erase_if(enum_set<Enum>& set, Predicate pred)
 }
 } // namespace cm
 
+//
+// WARNING: the following two functions rely on an enum_set without
+// explicit size.
+//
+// TODO: ensure compatibility with any enum_set definitions.
+//
 template <typename Enum,
           typename cm::enable_if_t<cm::is_scoped_enum<Enum>::value, int> = 0>
 inline cm::enum_set<Enum> operator+(Enum lhs, Enum rhs)