| |
| #include <cstdint> |
| #include <initializer_list> |
| #include <iostream> |
| #include <iterator> |
| #include <limits> |
| #include <set> |
| #include <type_traits> |
| #include <utility> |
| |
| #include <cmext/enum_set> |
| |
| 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; |
| |
| { |
| 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; |
| } |
| 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; |
| } |
| } |
| { |
| 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() != |
| std::numeric_limits< |
| typename std::underlying_type<Test>::type>::digits) { |
| ++failed; |
| } |
| if (testSet2.size() != 0 || testSet2.max_size() != 5) { |
| ++failed; |
| } |
| } |
| } |
| |
| void testIteration() |
| { |
| std::cout << "testIteration()" << std::endl; |
| |
| EnumSetTest2 testSet{ Test2::A, Test2::C, Test2::B }; |
| |
| if (testSet.size() != 3) { |
| ++failed; |
| } |
| |
| std::set<std::uint8_t> reference{ static_cast<std::uint8_t>(Test::A), |
| static_cast<std::uint8_t>(Test::B), |
| static_cast<std::uint8_t>(Test::C) }; |
| std::set<std::uint8_t> s; |
| |
| for (auto e : testSet) { |
| s.insert(static_cast<std::uint8_t>(e)); |
| } |
| if (s != reference) { |
| ++failed; |
| } |
| |
| s.clear(); |
| for (auto rit = testSet.rbegin(); rit != testSet.rend(); rit++) { |
| s.insert(static_cast<std::uint8_t>(*rit)); |
| } |
| if (s != reference) { |
| ++failed; |
| } |
| } |
| |
| void testEdition() |
| { |
| std::cout << "testEdition()" << std::endl; |
| |
| { |
| EnumSetTest testSet{ Test::A, Test::C, Test::B }; |
| |
| auto pos = testSet.insert(Test::E); |
| if (!pos.second || testSet.size() != 4 || *(pos.first) != Test::E || |
| testSet.find(Test::E) == testSet.end()) { |
| ++failed; |
| } |
| testSet.insert(Test::E); |
| if (testSet.size() != 4 || testSet.find(Test::E) == testSet.end()) { |
| ++failed; |
| } |
| |
| testSet.erase(Test::A); |
| if (testSet.size() != 3 || testSet.find(Test::A) != testSet.end()) { |
| ++failed; |
| } |
| testSet.erase(Test::A); |
| if (testSet.size() != 3 || testSet.find(Test::A) != testSet.end()) { |
| ++failed; |
| } |
| } |
| { |
| EnumSetTest testSet{ Test::A, Test::C, Test::B }; |
| |
| testSet += { Test::D, Test::E }; |
| |
| std::set<std::uint8_t> reference{ static_cast<std::uint8_t>(Test::A), |
| static_cast<std::uint8_t>(Test::B), |
| static_cast<std::uint8_t>(Test::C), |
| static_cast<std::uint8_t>(Test::D), |
| static_cast<std::uint8_t>(Test::E) }; |
| std::set<std::uint8_t> s; |
| for (auto e : testSet) { |
| s.insert(static_cast<std::uint8_t>(e)); |
| } |
| if (s != reference) { |
| ++failed; |
| } |
| |
| testSet -= { Test::D, Test::B }; |
| reference.erase(static_cast<std::uint8_t>(Test::D)); |
| reference.erase(static_cast<std::uint8_t>(Test::B)); |
| s.clear(); |
| for (auto e : testSet) { |
| s.insert(static_cast<std::uint8_t>(e)); |
| } |
| if (s != reference) { |
| ++failed; |
| } |
| } |
| { |
| 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), |
| static_cast<std::uint8_t>(Test::B), |
| static_cast<std::uint8_t>(Test::C), |
| static_cast<std::uint8_t>(Test::D), |
| static_cast<std::uint8_t>(Test::E) }; |
| std::set<std::uint8_t> s; |
| for (auto e : testSet1) { |
| s.insert(static_cast<std::uint8_t>(e)); |
| } |
| if (s != reference) { |
| ++failed; |
| } |
| |
| testSet1.erase(testSet2); |
| |
| reference.erase(static_cast<std::uint8_t>(Test::A)); |
| reference.erase(static_cast<std::uint8_t>(Test::D)); |
| reference.erase(static_cast<std::uint8_t>(Test::E)); |
| s.clear(); |
| for (auto e : testSet1) { |
| s.insert(static_cast<std::uint8_t>(e)); |
| } |
| if (s != reference) { |
| ++failed; |
| } |
| } |
| { |
| 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)) { |
| ++failed; |
| } |
| |
| testSet1.flip(testSet2); |
| std::set<std::uint8_t> reference{ static_cast<std::uint8_t>(Test::B), |
| static_cast<std::uint8_t>(Test::E) }; |
| std::set<std::uint8_t> s; |
| for (auto e : testSet1) { |
| s.insert(static_cast<std::uint8_t>(e)); |
| } |
| if (s != reference) { |
| ++failed; |
| } |
| } |
| { |
| EnumSetTest testSet1; |
| 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; |
| } |
| } |
| { |
| EnumSetTest2 testSet1; |
| EnumSetTest2 testSet2{ Test2::A, Test2::C, Test2::B }; |
| |
| testSet1.set(); |
| if (testSet1.size() != 5 || testSet1.size() != testSet1.max_size()) { |
| ++failed; |
| } |
| testSet1.flip({ Test2::D, Test2::E }); |
| if (testSet1.size() != 3 || testSet1 != testSet2) { |
| ++failed; |
| } |
| testSet1.flip(Test2::D | Test2::E); |
| testSet2 += Test2::D + Test2::E; |
| if (testSet1.size() != 5 || testSet1 != testSet2) { |
| ++failed; |
| } |
| testSet1.flip(Test2::E); |
| testSet2 -= Test2::E; |
| if (testSet1.size() != 4 || testSet1 != testSet2) { |
| ++failed; |
| } |
| testSet1 ^= { Test2::A, Test2::B, Test2::E, Test2::D }; |
| testSet2 = { Test2::C, Test2::E }; |
| if (testSet1.size() != 2 || testSet1 != testSet2) { |
| ++failed; |
| } |
| testSet1 ^= { Test2::A, Test2::B, Test2::E }; |
| testSet2 = { Test2::A, Test2::B, Test2::C }; |
| if (testSet1.size() != 3 || testSet1 != testSet2) { |
| ++failed; |
| } |
| testSet2 = Test2::A | Test2::B | Test2::C; |
| if (testSet1.size() != 3 || testSet1 != testSet2) { |
| ++failed; |
| } |
| } |
| } |
| |
| void testChecks() |
| { |
| std::cout << "testChecks()" << std::endl; |
| |
| { |
| EnumSetTest 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; |
| } |
| } |
| { |
| EnumSetTest2 testSet; |
| |
| if (!testSet.none()) { |
| ++failed; |
| } |
| if (testSet.any() || testSet.all()) { |
| ++failed; |
| } |
| |
| testSet = Test2::A; |
| if (!testSet.any() || testSet.none() || testSet.all()) { |
| ++failed; |
| } |
| |
| testSet.set(); |
| if (!testSet.all() || !testSet.any() || testSet.none()) { |
| ++failed; |
| } |
| } |
| { |
| EnumSetTest testSet1; |
| EnumSetTest 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; |
| } |
| } |
| } |
| } |
| |
| int testCMExtEnumSet(int /*unused*/, char* /*unused*/[]) |
| { |
| testDeclaration(); |
| testIteration(); |
| testEdition(); |
| testChecks(); |
| |
| return failed; |
| } |