mirror of
https://github.com/Kitware/CMake.git
synced 2025-12-31 10:50:16 -06:00
cmext/enum_set: add various enhancements to increase usability
This commit is contained in:
@@ -3,7 +3,9 @@
|
||||
#include <initializer_list>
|
||||
#include <iostream>
|
||||
#include <iterator>
|
||||
#include <limits>
|
||||
#include <set>
|
||||
#include <type_traits>
|
||||
#include <utility>
|
||||
|
||||
#include <cmext/enum_set>
|
||||
@@ -16,25 +18,70 @@ void testDeclaration()
|
||||
{
|
||||
std::cout << "testDeclaration()" << std::endl;
|
||||
|
||||
enum class Test : std::uint8_t
|
||||
{
|
||||
A,
|
||||
B,
|
||||
C,
|
||||
D
|
||||
};
|
||||
cm::enum_set<Test> testSet1;
|
||||
cm::enum_set<Test> testSet2{ Test::A, Test::C };
|
||||
cm::enum_set<Test> testSet3 = testSet2;
|
||||
enum class Test : std::uint8_t
|
||||
{
|
||||
A,
|
||||
B,
|
||||
C,
|
||||
D
|
||||
};
|
||||
cm::enum_set<Test> testSet1;
|
||||
cm::enum_set<Test> testSet2 = Test::A;
|
||||
cm::enum_set<Test> testSet3 = Test::A | Test::C;
|
||||
cm::enum_set<Test> testSet4 = Test::A + Test::C;
|
||||
cm::enum_set<Test> testSet5{ Test::A, Test::C };
|
||||
cm::enum_set<Test> testSet6 = testSet3;
|
||||
|
||||
if (!testSet1.empty()) {
|
||||
++failed;
|
||||
if (!testSet1.empty()) {
|
||||
++failed;
|
||||
}
|
||||
if (testSet2.size() != 1) {
|
||||
++failed;
|
||||
}
|
||||
if (testSet3.size() != 2 || testSet4.size() != 2 || testSet5.size() != 2 ||
|
||||
testSet6.size() != 2) {
|
||||
++failed;
|
||||
}
|
||||
if (testSet3 != testSet4 || testSet4 != testSet5 || testSet5 != testSet6) {
|
||||
++failed;
|
||||
}
|
||||
}
|
||||
if (testSet2.size() != 2) {
|
||||
++failed;
|
||||
{
|
||||
enum class Test : std::uint8_t
|
||||
{
|
||||
A,
|
||||
B,
|
||||
C,
|
||||
D
|
||||
};
|
||||
cm::enum_set<Test> testSet1;
|
||||
cm::enum_set<Test, 4> testSet2;
|
||||
|
||||
if (testSet1.size() != 0 ||
|
||||
testSet1.max_size() !=
|
||||
std::numeric_limits<
|
||||
typename std::underlying_type<Test>::type>::digits) {
|
||||
++failed;
|
||||
}
|
||||
if (testSet2.size() != 0 || testSet2.max_size() != 4) {
|
||||
++failed;
|
||||
}
|
||||
}
|
||||
if (testSet3.size() != 2) {
|
||||
++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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -47,7 +94,8 @@ void testIteration()
|
||||
A,
|
||||
B,
|
||||
C,
|
||||
D
|
||||
D,
|
||||
cm_count = D
|
||||
};
|
||||
cm::enum_set<Test> testSet{ Test::A, Test::C, Test::B };
|
||||
|
||||
@@ -86,7 +134,8 @@ void testEdition()
|
||||
B,
|
||||
C,
|
||||
D,
|
||||
E
|
||||
E,
|
||||
cm_count = E
|
||||
};
|
||||
|
||||
{
|
||||
@@ -193,12 +242,169 @@ void testEdition()
|
||||
}
|
||||
{
|
||||
cm::enum_set<Test> testSet1;
|
||||
cm::enum_set<Test> testSet2{ Test::A, Test::C, Test::B };
|
||||
auto testSet2 = Test::A + Test::C + Test::B;
|
||||
|
||||
testSet1.set({ Test::A, Test::C, Test::B });
|
||||
if (testSet1.size() != 3 || testSet1 != testSet2) {
|
||||
++failed;
|
||||
}
|
||||
testSet1.reset();
|
||||
testSet1.set(Test::A | Test::C | Test::B);
|
||||
if (testSet1.size() != 3 || testSet1 != testSet2) {
|
||||
++failed;
|
||||
}
|
||||
testSet1.reset();
|
||||
testSet1.set(Test::A + Test::C + Test::B);
|
||||
if (testSet1.size() != 3 || testSet1 != testSet2) {
|
||||
++failed;
|
||||
}
|
||||
testSet1.reset();
|
||||
testSet1 = { Test::A, Test::C, Test::B };
|
||||
if (testSet1.size() != 3 || testSet1 != testSet2) {
|
||||
++failed;
|
||||
}
|
||||
testSet1.reset();
|
||||
testSet1 = Test::A | Test::C | Test::B;
|
||||
if (testSet1.size() != 3 || testSet1 != testSet2) {
|
||||
++failed;
|
||||
}
|
||||
testSet1.clear();
|
||||
testSet1 = Test::A + Test::C + Test::B;
|
||||
if (testSet1.size() != 3 || testSet1 != testSet2) {
|
||||
++failed;
|
||||
}
|
||||
testSet1.clear();
|
||||
testSet1 |= Test::A;
|
||||
testSet1 |= Test::C | Test::B;
|
||||
if (testSet1.size() != 3 || testSet1 != testSet2) {
|
||||
++failed;
|
||||
}
|
||||
}
|
||||
{
|
||||
cm::enum_set<Test> testSet1;
|
||||
cm::enum_set<Test> 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);
|
||||
if (testSet1.size() != 3 || testSet1 != testSet2) {
|
||||
++failed;
|
||||
}
|
||||
testSet1.flip(Test::D);
|
||||
testSet2 += Test::D;
|
||||
if (testSet1.size() != 4 || testSet1 != testSet2) {
|
||||
++failed;
|
||||
}
|
||||
testSet1 ^= { Test::A, Test::B, Test::E, Test::D };
|
||||
testSet2 = Test::C + Test::E;
|
||||
if (testSet1.size() != 2 || testSet1 != testSet2) {
|
||||
++failed;
|
||||
}
|
||||
testSet1 ^= Test::A | Test::B | Test::E;
|
||||
testSet2 = { Test::A, Test::B, Test::C };
|
||||
if (testSet1.size() != 3 || testSet1 != testSet2) {
|
||||
++failed;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void testChecks()
|
||||
{
|
||||
std::cout << "testChecks()" << std::endl;
|
||||
|
||||
{
|
||||
enum class Test : std::uint8_t
|
||||
{
|
||||
A,
|
||||
B,
|
||||
C,
|
||||
D,
|
||||
cm_count = D
|
||||
};
|
||||
|
||||
cm::enum_set<Test> testSet;
|
||||
|
||||
if (!testSet.empty()) {
|
||||
++failed;
|
||||
}
|
||||
|
||||
testSet = Test::A;
|
||||
if (testSet.empty()) {
|
||||
++failed;
|
||||
}
|
||||
if (!testSet) {
|
||||
++failed;
|
||||
}
|
||||
if (!testSet.contains(Test::A)) {
|
||||
++failed;
|
||||
}
|
||||
if (testSet.find(Test::A) == testSet.end()) {
|
||||
++failed;
|
||||
}
|
||||
if (testSet.find(Test::C) != testSet.end()) {
|
||||
++failed;
|
||||
}
|
||||
}
|
||||
{
|
||||
enum class Test : std::uint8_t
|
||||
{
|
||||
A,
|
||||
B,
|
||||
C,
|
||||
D,
|
||||
cm_count = D
|
||||
};
|
||||
|
||||
cm::enum_set<Test> testSet;
|
||||
|
||||
if (!testSet.none()) {
|
||||
++failed;
|
||||
}
|
||||
if (testSet.any() || testSet.all()) {
|
||||
++failed;
|
||||
}
|
||||
|
||||
testSet = Test::A;
|
||||
if (!testSet.any() || testSet.none() || testSet.all()) {
|
||||
++failed;
|
||||
}
|
||||
|
||||
testSet.set();
|
||||
if (!testSet.all() || !testSet.any() || testSet.none()) {
|
||||
++failed;
|
||||
}
|
||||
}
|
||||
{
|
||||
enum class Test : std::uint8_t
|
||||
{
|
||||
A,
|
||||
B,
|
||||
C,
|
||||
D,
|
||||
cm_count = D
|
||||
};
|
||||
|
||||
cm::enum_set<Test> testSet1;
|
||||
cm::enum_set<Test> testSet2{ Test::A, Test::C };
|
||||
|
||||
if (!testSet1.none_of(testSet2) || testSet1.any_of(testSet2) ||
|
||||
testSet1.all_of(testSet2)) {
|
||||
++failed;
|
||||
}
|
||||
|
||||
testSet1 = Test::A | Test::D;
|
||||
if (testSet1.none_of(testSet2) || !testSet1.any_of(testSet2) ||
|
||||
testSet1.all_of(testSet2)) {
|
||||
++failed;
|
||||
}
|
||||
|
||||
testSet1 |= Test::C;
|
||||
if (testSet1.none_of(testSet2) || !testSet1.any_of(testSet2) ||
|
||||
!testSet1.all_of(testSet2)) {
|
||||
++failed;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -208,6 +414,7 @@ int testCMExtEnumSet(int /*unused*/, char* /*unused*/[])
|
||||
testDeclaration();
|
||||
testIteration();
|
||||
testEdition();
|
||||
testChecks();
|
||||
|
||||
return failed;
|
||||
}
|
||||
|
||||
@@ -15,19 +15,53 @@
|
||||
#include <cm/type_traits>
|
||||
|
||||
//
|
||||
// Class enum_set offers the capability to manage a set of enum values
|
||||
// Only 'enum class' with unsigned base type are supported.
|
||||
// Class enum_set offers the capability to manage a set of enum values.
|
||||
// Only the 'enum class' type with unsigned base type is supported. Moreover,
|
||||
// all definitions must be specified without a value.
|
||||
//
|
||||
// The methods offered by 'enum_set' are close as possible to the 'std::set'
|
||||
// container plus some useful methods from 'std::bitset' like 'flip'.
|
||||
// container as well as the methods from 'std::bitset'.
|
||||
//
|
||||
// Internally, this class use 'std::bitset' container to manage the
|
||||
// set of enum. The size of the bitset is deduced from the underlying type of
|
||||
// the enum.
|
||||
// set of enum.
|
||||
//
|
||||
// The size of the bitset is deduced from the underlying type of
|
||||
// the enum or can be set explicitly as template parameter:
|
||||
//
|
||||
// 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':
|
||||
//
|
||||
// auto set1 = Example::A | Example::B | Example::C;
|
||||
// auto set2 = Example::A + Example::B;
|
||||
// set2.set(Example::C | Example::D);
|
||||
//
|
||||
|
||||
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
|
||||
{
|
||||
@@ -110,9 +144,9 @@ private:
|
||||
};
|
||||
|
||||
template <
|
||||
typename Enum,
|
||||
typename Enum, std::size_t Size = internals::enum_size<Enum>::value,
|
||||
typename cm::enable_if_t<
|
||||
std::is_enum<Enum>::value &&
|
||||
cm::is_scoped_enum<Enum>::value &&
|
||||
std::is_unsigned<typename std::underlying_type<Enum>::type>::value,
|
||||
int> = 0>
|
||||
class enum_set
|
||||
@@ -133,9 +167,16 @@ public:
|
||||
using const_reverse_iterator = std::reverse_iterator<const_iterator>;
|
||||
|
||||
constexpr enum_set() noexcept = default;
|
||||
enum_set(key_type e) { this->insert(e); }
|
||||
enum_set(enum_set const& other) noexcept { this->insert(other); }
|
||||
enum_set(std::initializer_list<value_type> list) { this->insert(list); }
|
||||
|
||||
enum_set& operator=(key_type e)
|
||||
{
|
||||
this->Set.reset();
|
||||
this->insert(e);
|
||||
return *this;
|
||||
}
|
||||
enum_set& operator=(enum_set const& other) noexcept
|
||||
{
|
||||
this->Set.reset();
|
||||
@@ -186,41 +227,116 @@ public:
|
||||
size_type max_size() const noexcept { return this->Set.size(); }
|
||||
|
||||
// Modifiers
|
||||
void clear() noexcept { this->Set.reset(); }
|
||||
|
||||
enum_set& operator+=(key_type e)
|
||||
// set all elements
|
||||
enum_set& set()
|
||||
{
|
||||
this->Set.set();
|
||||
return *this;
|
||||
}
|
||||
enum_set& set(key_type e)
|
||||
{
|
||||
this->insert(e);
|
||||
return *this;
|
||||
}
|
||||
enum_set& operator+=(enum_set const& other) noexcept
|
||||
enum_set& set(enum_set const& other) noexcept
|
||||
{
|
||||
this->erase(other);
|
||||
this->insert(other);
|
||||
return *this;
|
||||
}
|
||||
enum_set& operator+=(std::initializer_list<value_type> list)
|
||||
enum_set& set(std::initializer_list<value_type> list)
|
||||
{
|
||||
this->insert(list);
|
||||
return *this;
|
||||
}
|
||||
// alternate syntax for bit set
|
||||
enum_set& operator+=(key_type e) { return this->set(e); }
|
||||
enum_set& operator+=(enum_set const& other) noexcept
|
||||
{
|
||||
return this->set(other);
|
||||
}
|
||||
enum_set& operator+=(std::initializer_list<value_type> list)
|
||||
{
|
||||
return this->set(list);
|
||||
}
|
||||
// alternate syntax for bit set
|
||||
enum_set& operator|=(key_type e) { return this->set(e); }
|
||||
enum_set& operator|=(enum_set const& other) noexcept
|
||||
{
|
||||
return this->set(other);
|
||||
}
|
||||
enum_set& operator|=(std::initializer_list<value_type> list)
|
||||
{
|
||||
return this->set(list);
|
||||
}
|
||||
|
||||
enum_set& operator-=(key_type e)
|
||||
// reset all elements
|
||||
void clear() noexcept { this->Set.reset(); }
|
||||
enum_set& reset()
|
||||
{
|
||||
this->Set.reset();
|
||||
return *this;
|
||||
}
|
||||
enum_set& reset(key_type e)
|
||||
{
|
||||
this->erase(e);
|
||||
return *this;
|
||||
}
|
||||
enum_set& operator-=(enum_set const& other) noexcept
|
||||
enum_set& reset(enum_set const& other) noexcept
|
||||
{
|
||||
this->erase(other);
|
||||
return *this;
|
||||
}
|
||||
enum_set& operator-=(std::initializer_list<value_type> list)
|
||||
enum_set& reset(std::initializer_list<value_type> list)
|
||||
{
|
||||
this->erase(list);
|
||||
return *this;
|
||||
}
|
||||
// alternate syntax for bit reset
|
||||
enum_set& operator-=(key_type e) { return this->reset(e); }
|
||||
enum_set& operator-=(enum_set const& other) noexcept
|
||||
{
|
||||
return this->reset(other);
|
||||
}
|
||||
enum_set& operator-=(std::initializer_list<value_type> list)
|
||||
{
|
||||
return this->reset(list);
|
||||
}
|
||||
|
||||
std::pair<iterator, bool> insert(value_type value)
|
||||
// toggle the specified enum
|
||||
enum_set& flip(key_type e)
|
||||
{
|
||||
this->Set.flip(static_cast<size_type>(e));
|
||||
return *this;
|
||||
}
|
||||
// toggle all the enums stored in the other enum_set
|
||||
enum_set& flip(enum_set const& other) noexcept
|
||||
{
|
||||
this->Set ^= other.Set;
|
||||
return *this;
|
||||
}
|
||||
// toggle all the enums specified in the list
|
||||
enum_set& flip(std::initializer_list<value_type> list)
|
||||
{
|
||||
for (auto e : list) {
|
||||
this->Set.flip(static_cast<size_type>(e));
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
// alternate syntax for bit toggle
|
||||
enum_set& operator^=(key_type key) { return this->flip(key); }
|
||||
// toggle all the enums stored in the other enum_set
|
||||
enum_set& operator^=(enum_set const& other) noexcept
|
||||
{
|
||||
return this->flip(other);
|
||||
}
|
||||
// toggle all the enums specified in the list
|
||||
enum_set& operator^=(std::initializer_list<value_type> list)
|
||||
{
|
||||
return this->flip(list);
|
||||
}
|
||||
|
||||
std::pair<iterator, bool> insert(key_type value)
|
||||
{
|
||||
auto exist = this->contains(value);
|
||||
if (!exist) {
|
||||
@@ -280,18 +396,6 @@ public:
|
||||
other.Set = tmp;
|
||||
}
|
||||
|
||||
// toggle the specified enum
|
||||
void flip(key_type key) { this->Set.flip(static_cast<size_type>(key)); }
|
||||
// toggle all the enums stored in the other enum_set
|
||||
void flip(enum_set const& other) noexcept { this->Set ^= other.Set; }
|
||||
// toggle all the enums specified in the list
|
||||
void flip(std::initializer_list<value_type> list)
|
||||
{
|
||||
for (auto e : list) {
|
||||
this->Set.flip(static_cast<size_type>(e));
|
||||
}
|
||||
}
|
||||
|
||||
// Lookup
|
||||
size_type count(key_type e) const { return this->contains(e) ? 1 : 0; }
|
||||
|
||||
@@ -310,11 +414,37 @@ public:
|
||||
return this->end();
|
||||
}
|
||||
|
||||
// Checks
|
||||
bool contains(key_type e) const
|
||||
{
|
||||
return this->Set.test(static_cast<size_type>(e));
|
||||
}
|
||||
|
||||
bool all() const { return this->Set.all(); }
|
||||
bool any() const { return this->Set.any(); }
|
||||
bool none() const { return this->Set.none(); }
|
||||
// alternate syntax to none()
|
||||
bool operator!() const { return this->Set.none(); }
|
||||
|
||||
bool all_of(enum_set const& set) const
|
||||
{
|
||||
auto result = set;
|
||||
result.Set &= this->Set;
|
||||
return result == set;
|
||||
}
|
||||
bool any_of(enum_set const& set) const
|
||||
{
|
||||
auto result = set;
|
||||
result.Set &= this->Set;
|
||||
return result.any();
|
||||
}
|
||||
bool none_of(enum_set const& set) const
|
||||
{
|
||||
auto result = set;
|
||||
result.Set &= this->Set;
|
||||
return result.none();
|
||||
}
|
||||
|
||||
private:
|
||||
template <typename E>
|
||||
friend inline bool operator==(enum_set<E> const& lhs,
|
||||
@@ -328,44 +458,79 @@ private:
|
||||
|
||||
bool test(size_type pos) const { return this->Set.test(pos); }
|
||||
|
||||
std::bitset<std::numeric_limits<size_type>::digits> Set;
|
||||
std::bitset<Size> Set;
|
||||
};
|
||||
|
||||
// non-member functions for enum_set
|
||||
template <typename Enum>
|
||||
inline enum_set<Enum> operator+(enum_set<Enum> const& lhs, Enum rhs)
|
||||
{
|
||||
return enum_set<Enum>(lhs) += rhs;
|
||||
return enum_set<Enum>{ lhs } += rhs;
|
||||
}
|
||||
template <typename Enum>
|
||||
inline enum_set<Enum> operator+(enum_set<Enum> const& lhs,
|
||||
enum_set<Enum> const& rhs) noexcept
|
||||
{
|
||||
return enum_set<Enum>(lhs) += rhs;
|
||||
return enum_set<Enum>{ lhs } += rhs;
|
||||
}
|
||||
template <typename Enum>
|
||||
inline enum_set<Enum> operator+(enum_set<Enum> const& lhs,
|
||||
std::initializer_list<Enum> const rhs)
|
||||
{
|
||||
return enum_set<Enum>(lhs) += rhs;
|
||||
return enum_set<Enum>{ lhs } += rhs;
|
||||
}
|
||||
|
||||
template <typename Enum>
|
||||
inline cm::enum_set<Enum> operator|(cm::enum_set<Enum> const& lhs, Enum rhs)
|
||||
{
|
||||
return enum_set<Enum>{ lhs } |= rhs;
|
||||
}
|
||||
template <typename Enum>
|
||||
inline cm::enum_set<Enum> operator|(Enum lhs, cm::enum_set<Enum> const& rhs)
|
||||
{
|
||||
return enum_set<Enum>{ lhs } |= rhs;
|
||||
}
|
||||
template <typename Enum>
|
||||
inline cm::enum_set<Enum> operator|(cm::enum_set<Enum> const& lhs,
|
||||
cm::enum_set<Enum> const& rhs)
|
||||
{
|
||||
return enum_set<Enum>{ lhs } |= rhs;
|
||||
}
|
||||
|
||||
template <typename Enum>
|
||||
inline enum_set<Enum> operator-(enum_set<Enum> const& lhs, Enum rhs)
|
||||
{
|
||||
return enum_set<Enum>(lhs) -= rhs;
|
||||
return enum_set<Enum>{ lhs } -= rhs;
|
||||
}
|
||||
template <typename Enum>
|
||||
inline enum_set<Enum> operator-(enum_set<Enum> const& lhs,
|
||||
enum_set<Enum> const& rhs) noexcept
|
||||
{
|
||||
return enum_set<Enum>(lhs) -= rhs;
|
||||
return enum_set<Enum>{ lhs } -= rhs;
|
||||
}
|
||||
template <typename Enum>
|
||||
inline enum_set<Enum> operator-(enum_set<Enum> const& lhs,
|
||||
std::initializer_list<Enum> const rhs)
|
||||
{
|
||||
return enum_set<Enum>(lhs) -= rhs;
|
||||
return enum_set<Enum>{ lhs } -= rhs;
|
||||
}
|
||||
|
||||
template <typename Enum>
|
||||
inline enum_set<Enum> operator^(enum_set<Enum> const& lhs, Enum rhs)
|
||||
{
|
||||
return enum_set<Enum>{ lhs } ^= rhs;
|
||||
}
|
||||
template <typename Enum>
|
||||
inline enum_set<Enum> operator^(enum_set<Enum> const& lhs,
|
||||
enum_set<Enum> const& rhs) noexcept
|
||||
{
|
||||
return enum_set<Enum>{ lhs } ^= rhs;
|
||||
}
|
||||
template <typename Enum>
|
||||
inline enum_set<Enum> operator^(enum_set<Enum> const& lhs,
|
||||
std::initializer_list<Enum> const rhs)
|
||||
{
|
||||
return enum_set<Enum>{ lhs } ^= rhs;
|
||||
}
|
||||
|
||||
template <typename Enum>
|
||||
@@ -398,3 +563,17 @@ inline void erase_if(enum_set<Enum>& set, Predicate pred)
|
||||
}
|
||||
}
|
||||
} // namespace cm
|
||||
|
||||
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)
|
||||
{
|
||||
return cm::enum_set<Enum>{ lhs, rhs };
|
||||
}
|
||||
// Alternate syntax
|
||||
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)
|
||||
{
|
||||
return cm::enum_set<Enum>{ lhs, rhs };
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user