mirror of
https://github.com/Kitware/CMake.git
synced 2026-01-08 14:50:10 -06:00
enum_set enhancements, step 2
* remove support of size computation based on "magic" enum element because Oracle SunPro compilers crash on it. * enhance handling of enum_set with explicit size.
This commit is contained in:
@@ -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;
|
||||
|
||||
@@ -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)
|
||||
|
||||
Reference in New Issue
Block a user