Merge topic 'enum_set-enhancements'
4d48958965
enum_set enhancements, step 3
Acked-by: Kitware Robot <kwrobot@kitware.com>
Merge-request: !10335
This commit is contained in:
commit
f9e51b61cd
@ -14,24 +14,44 @@ namespace {
|
||||
|
||||
int failed = 0;
|
||||
|
||||
enum class Test : std::uint8_t
|
||||
{
|
||||
A,
|
||||
B,
|
||||
C,
|
||||
D,
|
||||
E
|
||||
};
|
||||
|
||||
using EnumSetTest = cm::enum_set<Test>;
|
||||
|
||||
enum class Test2 : std::uint8_t
|
||||
{
|
||||
A,
|
||||
B,
|
||||
C,
|
||||
D,
|
||||
E
|
||||
};
|
||||
|
||||
using EnumSetTest2 = cm::enum_set<Test2, 5>;
|
||||
}
|
||||
|
||||
CM_ENUM_SET_TRAITS(EnumSetTest)
|
||||
CM_ENUM_SET_TRAITS(EnumSetTest2)
|
||||
|
||||
namespace {
|
||||
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;
|
||||
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;
|
||||
EnumSetTest testSet1;
|
||||
EnumSetTest testSet2 = Test::A;
|
||||
EnumSetTest testSet3 = Test::A | Test::C;
|
||||
EnumSetTest testSet4 = Test::A + Test::C;
|
||||
EnumSetTest testSet5{ Test::A, Test::C };
|
||||
EnumSetTest testSet6 = testSet3;
|
||||
|
||||
if (!testSet1.empty()) {
|
||||
++failed;
|
||||
@ -48,15 +68,50 @@ void testDeclaration()
|
||||
}
|
||||
}
|
||||
{
|
||||
enum class Test : std::uint8_t
|
||||
{
|
||||
A,
|
||||
B,
|
||||
C,
|
||||
D
|
||||
};
|
||||
cm::enum_set<Test> testSet1;
|
||||
cm::enum_set<Test, 4> testSet2;
|
||||
EnumSetTest2 testSet1;
|
||||
EnumSetTest2 testSet2 = Test2::A;
|
||||
EnumSetTest2 testSet3 = Test2::A | Test2::C;
|
||||
EnumSetTest2 testSet4 = Test2::A + Test2::C;
|
||||
EnumSetTest2 testSet5{ Test2::A, Test2::C };
|
||||
EnumSetTest2 testSet6 = testSet3;
|
||||
|
||||
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;
|
||||
}
|
||||
}
|
||||
{
|
||||
using LocalEnumSetTest = cm::enum_set<Test>;
|
||||
LocalEnumSetTest testSet1;
|
||||
LocalEnumSetTest testSet2 = Test::A;
|
||||
LocalEnumSetTest testSet3{ Test::A, Test::C };
|
||||
LocalEnumSetTest testSet4 = testSet3;
|
||||
|
||||
if (!testSet1.empty()) {
|
||||
++failed;
|
||||
}
|
||||
if (testSet2.size() != 1) {
|
||||
++failed;
|
||||
}
|
||||
if (testSet3.size() != 2 || testSet4.size() != 2) {
|
||||
++failed;
|
||||
}
|
||||
if (testSet3 != testSet4) {
|
||||
++failed;
|
||||
}
|
||||
}
|
||||
{
|
||||
EnumSetTest testSet1;
|
||||
EnumSetTest2 testSet2;
|
||||
|
||||
if (testSet1.size() != 0 ||
|
||||
testSet1.max_size() !=
|
||||
@ -64,7 +119,7 @@ void testDeclaration()
|
||||
typename std::underlying_type<Test>::type>::digits) {
|
||||
++failed;
|
||||
}
|
||||
if (testSet2.size() != 0 || testSet2.max_size() != 4) {
|
||||
if (testSet2.size() != 0 || testSet2.max_size() != 5) {
|
||||
++failed;
|
||||
}
|
||||
}
|
||||
@ -74,14 +129,7 @@ void testIteration()
|
||||
{
|
||||
std::cout << "testIteration()" << std::endl;
|
||||
|
||||
enum class Test : std::uint8_t
|
||||
{
|
||||
A,
|
||||
B,
|
||||
C,
|
||||
D
|
||||
};
|
||||
cm::enum_set<Test, 4> testSet{ Test::A, Test::C, Test::B };
|
||||
EnumSetTest2 testSet{ Test2::A, Test2::C, Test2::B };
|
||||
|
||||
if (testSet.size() != 3) {
|
||||
++failed;
|
||||
@ -112,17 +160,8 @@ void testEdition()
|
||||
{
|
||||
std::cout << "testEdition()" << std::endl;
|
||||
|
||||
enum class Test : std::uint8_t
|
||||
{
|
||||
A,
|
||||
B,
|
||||
C,
|
||||
D,
|
||||
E
|
||||
};
|
||||
|
||||
{
|
||||
cm::enum_set<Test> testSet{ Test::A, Test::C, Test::B };
|
||||
EnumSetTest testSet{ Test::A, Test::C, Test::B };
|
||||
|
||||
auto pos = testSet.insert(Test::E);
|
||||
if (!pos.second || testSet.size() != 4 || *(pos.first) != Test::E ||
|
||||
@ -144,7 +183,7 @@ void testEdition()
|
||||
}
|
||||
}
|
||||
{
|
||||
cm::enum_set<Test> testSet{ Test::A, Test::C, Test::B };
|
||||
EnumSetTest testSet{ Test::A, Test::C, Test::B };
|
||||
|
||||
testSet += { Test::D, Test::E };
|
||||
|
||||
@ -173,8 +212,8 @@ void testEdition()
|
||||
}
|
||||
}
|
||||
{
|
||||
cm::enum_set<Test> testSet1{ Test::A, Test::C, Test::B };
|
||||
cm::enum_set<Test> testSet2{ Test::A, Test::D, Test::E };
|
||||
EnumSetTest testSet1{ Test::A, Test::C, Test::B };
|
||||
EnumSetTest testSet2{ Test::A, Test::D, Test::E };
|
||||
testSet1.insert(testSet2.cbegin(), testSet2.cend());
|
||||
|
||||
std::set<std::uint8_t> reference{ static_cast<std::uint8_t>(Test::A),
|
||||
@ -204,8 +243,8 @@ void testEdition()
|
||||
}
|
||||
}
|
||||
{
|
||||
cm::enum_set<Test> testSet1{ Test::A, Test::C, Test::B };
|
||||
cm::enum_set<Test> testSet2{ Test::C, Test::E };
|
||||
EnumSetTest testSet1{ Test::A, Test::C, Test::B };
|
||||
EnumSetTest testSet2{ Test::C, Test::E };
|
||||
|
||||
testSet1.flip(Test::A);
|
||||
if (testSet1.size() != 2 || testSet1.contains(Test::A)) {
|
||||
@ -224,7 +263,7 @@ void testEdition()
|
||||
}
|
||||
}
|
||||
{
|
||||
cm::enum_set<Test> testSet1;
|
||||
EnumSetTest testSet1;
|
||||
auto testSet2 = Test::A + Test::C + Test::B;
|
||||
|
||||
testSet1.set({ Test::A, Test::C, Test::B });
|
||||
@ -264,39 +303,38 @@ void testEdition()
|
||||
}
|
||||
}
|
||||
{
|
||||
using ESet = cm::enum_set<Test, 5>;
|
||||
ESet testSet1;
|
||||
ESet testSet2{ Test::A, Test::C, Test::B };
|
||||
EnumSetTest2 testSet1;
|
||||
EnumSetTest2 testSet2{ Test2::A, Test2::C, Test2::B };
|
||||
|
||||
testSet1.set();
|
||||
if (testSet1.size() != 5 || testSet1.size() != testSet1.max_size()) {
|
||||
++failed;
|
||||
}
|
||||
testSet1.flip({ Test::D, Test::E });
|
||||
testSet1.flip({ Test2::D, Test2::E });
|
||||
if (testSet1.size() != 3 || testSet1 != testSet2) {
|
||||
++failed;
|
||||
}
|
||||
testSet1.flip(Test::D | Test::E);
|
||||
testSet2 += Test::D + Test::E;
|
||||
testSet1.flip(Test2::D | Test2::E);
|
||||
testSet2 += Test2::D + Test2::E;
|
||||
if (testSet1.size() != 5 || testSet1 != testSet2) {
|
||||
++failed;
|
||||
}
|
||||
testSet1.flip(Test::E);
|
||||
testSet2 -= Test::E;
|
||||
testSet1.flip(Test2::E);
|
||||
testSet2 -= Test2::E;
|
||||
if (testSet1.size() != 4 || testSet1 != testSet2) {
|
||||
++failed;
|
||||
}
|
||||
testSet1 ^= { Test::A, Test::B, Test::E, Test::D };
|
||||
testSet2 = { Test::C, Test::E };
|
||||
testSet1 ^= { Test2::A, Test2::B, Test2::E, Test2::D };
|
||||
testSet2 = { Test2::C, Test2::E };
|
||||
if (testSet1.size() != 2 || testSet1 != testSet2) {
|
||||
++failed;
|
||||
}
|
||||
testSet1 ^= { Test::A, Test::B, Test::E };
|
||||
testSet2 = { Test::A, Test::B, Test::C };
|
||||
testSet1 ^= { Test2::A, Test2::B, Test2::E };
|
||||
testSet2 = { Test2::A, Test2::B, Test2::C };
|
||||
if (testSet1.size() != 3 || testSet1 != testSet2) {
|
||||
++failed;
|
||||
}
|
||||
testSet2 = Test::A | Test::B | Test::C;
|
||||
testSet2 = Test2::A | Test2::B | Test2::C;
|
||||
if (testSet1.size() != 3 || testSet1 != testSet2) {
|
||||
++failed;
|
||||
}
|
||||
@ -308,15 +346,7 @@ void testChecks()
|
||||
std::cout << "testChecks()" << std::endl;
|
||||
|
||||
{
|
||||
enum class Test : std::uint8_t
|
||||
{
|
||||
A,
|
||||
B,
|
||||
C,
|
||||
D
|
||||
};
|
||||
|
||||
cm::enum_set<Test> testSet;
|
||||
EnumSetTest testSet;
|
||||
|
||||
if (!testSet.empty()) {
|
||||
++failed;
|
||||
@ -340,15 +370,7 @@ void testChecks()
|
||||
}
|
||||
}
|
||||
{
|
||||
enum class Test : std::uint8_t
|
||||
{
|
||||
A,
|
||||
B,
|
||||
C,
|
||||
D
|
||||
};
|
||||
|
||||
cm::enum_set<Test, 4> testSet;
|
||||
EnumSetTest2 testSet;
|
||||
|
||||
if (!testSet.none()) {
|
||||
++failed;
|
||||
@ -357,7 +379,7 @@ void testChecks()
|
||||
++failed;
|
||||
}
|
||||
|
||||
testSet = Test::A;
|
||||
testSet = Test2::A;
|
||||
if (!testSet.any() || testSet.none() || testSet.all()) {
|
||||
++failed;
|
||||
}
|
||||
@ -368,16 +390,8 @@ void testChecks()
|
||||
}
|
||||
}
|
||||
{
|
||||
enum class Test : std::uint8_t
|
||||
{
|
||||
A,
|
||||
B,
|
||||
C,
|
||||
D
|
||||
};
|
||||
|
||||
cm::enum_set<Test> testSet1;
|
||||
cm::enum_set<Test> testSet2{ Test::A, Test::C };
|
||||
EnumSetTest testSet1;
|
||||
EnumSetTest testSet2{ Test::A, Test::C };
|
||||
|
||||
if (!testSet1.none_of(testSet2) || testSet1.any_of(testSet2) ||
|
||||
testSet1.all_of(testSet2)) {
|
||||
|
@ -561,21 +561,79 @@ inline void erase_if(enum_set<Enum, Size>& set, Predicate pred)
|
||||
} // namespace cm
|
||||
|
||||
//
|
||||
// WARNING: the following two functions rely on an enum_set without
|
||||
// explicit size.
|
||||
// WARNING: the following two operators rely on the enum_set_traits<Enum>
|
||||
// struct definition.
|
||||
// The macro CM_ENUM_SET_TRAITS(EnumSet) can be used to define this structure.
|
||||
//
|
||||
// TODO: ensure compatibility with any enum_set definitions.
|
||||
// Notes:
|
||||
// When CM_ENUM_SET_TRAITS is used, the following restrictions applies:
|
||||
// * Due to language constraints, the enum_set_traits specialization must
|
||||
// occur outside of any namespace or function definition.
|
||||
// * Only one enum_set instantiation is supported per enum class type.
|
||||
//
|
||||
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)
|
||||
|
||||
template <typename Enum>
|
||||
struct cm_enum_set_traits
|
||||
{
|
||||
return cm::enum_set<Enum>{ lhs, rhs };
|
||||
};
|
||||
|
||||
namespace cm {
|
||||
template <typename Enum, typename = cm::void_t<>>
|
||||
struct is_enum_set : std::false_type
|
||||
{
|
||||
};
|
||||
template <typename Enum>
|
||||
struct is_enum_set<Enum, cm::void_t<typename cm_enum_set_traits<Enum>::type>>
|
||||
: std::true_type
|
||||
{
|
||||
};
|
||||
}
|
||||
|
||||
#if defined(__SUNPRO_CC) && defined(__sparc)
|
||||
// Oracle DeveloperStudio C++ compiler on Solaris/Sparc crash on the following
|
||||
// template declarations, so declare explicitly the operators.
|
||||
|
||||
// Helper macro to define the enum_set_traits struct specialization.
|
||||
# define CM_ENUM_SET_TRAITS(E) \
|
||||
template <> \
|
||||
struct cm_enum_set_traits<E::value_type> \
|
||||
{ \
|
||||
using type = E; \
|
||||
using value_type = E::value_type; \
|
||||
}; \
|
||||
\
|
||||
inline E operator+(E::value_type lhs, E::value_type rhs) \
|
||||
{ \
|
||||
return { lhs, rhs }; \
|
||||
} \
|
||||
\
|
||||
inline E operator|(E::value_type lhs, E::value_type rhs) \
|
||||
{ \
|
||||
return { lhs, rhs }; \
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
// Helper macro to define the enum_set_traits struct specialization.
|
||||
# define CM_ENUM_SET_TRAITS(E) \
|
||||
template <> \
|
||||
struct cm_enum_set_traits<E::value_type> \
|
||||
{ \
|
||||
using type = E; \
|
||||
using value_type = E::value_type; \
|
||||
};
|
||||
|
||||
template <typename Enum,
|
||||
typename cm::enable_if_t<cm::is_enum_set<Enum>::value, int> = 0>
|
||||
inline typename cm_enum_set_traits<Enum>::type operator+(Enum lhs, Enum rhs)
|
||||
{
|
||||
return { 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)
|
||||
typename cm::enable_if_t<cm::is_enum_set<Enum>::value, int> = 0>
|
||||
inline typename cm_enum_set_traits<Enum>::type operator|(Enum lhs, Enum rhs)
|
||||
{
|
||||
return cm::enum_set<Enum>{ lhs, rhs };
|
||||
return { lhs, rhs };
|
||||
}
|
||||
#endif
|
||||
|
Loading…
Reference in New Issue
Block a user