mirror of
https://github.com/Kitware/CMake.git
synced 2025-10-19 02:17:27 +08:00

AppleClang 8.0 and below do not understand a `= default;` constructor in static constant default initialization, but do accept `{}`.
432 lines
10 KiB
C++
432 lines
10 KiB
C++
|
|
#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;
|
|
|
|
{
|
|
static EnumSetTest const testSet1;
|
|
static EnumSetTest2 const testSet2;
|
|
static_cast<void>(testSet1);
|
|
static_cast<void>(testSet2);
|
|
}
|
|
|
|
{
|
|
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;
|
|
}
|