mirror of
https://github.com/KhronosGroup/SPIRV-Tools
synced 2024-10-18 11:10:05 +00:00
enumset: add iterator based constructor/insert (#5344)
Expanding a bit the EnumSet API to have iterator-based insert and constructors (like the STL). This is also a pre-requisite from the capability-trimming pass as it allows to build a const set from a constexpr std::array easily. Signed-off-by: Nathan Gauër <brioche@google.com>
This commit is contained in:
parent
daad2295c9
commit
17d9669d51
@ -204,6 +204,14 @@ class EnumSet {
|
||||
}
|
||||
}
|
||||
|
||||
// Creates a set initialized with the content of the range [begin; end[.
|
||||
template <class InputIt>
|
||||
EnumSet(InputIt begin, InputIt end) : EnumSet() {
|
||||
for (; begin != end; ++begin) {
|
||||
insert(*begin);
|
||||
}
|
||||
}
|
||||
|
||||
// Copies the EnumSet `other` into a new EnumSet.
|
||||
EnumSet(const EnumSet& other)
|
||||
: buckets_(other.buckets_), size_(other.size_) {}
|
||||
@ -256,6 +264,15 @@ class EnumSet {
|
||||
// insertion.
|
||||
iterator insert(const_iterator, T&& value) { return insert(value).first; }
|
||||
|
||||
// Inserts all the values in the range [`first`; `last[.
|
||||
// Similar to `std::unordered_set::insert`.
|
||||
template <class InputIt>
|
||||
void insert(InputIt first, InputIt last) {
|
||||
for (auto it = first; it != last; ++it) {
|
||||
insert(*it);
|
||||
}
|
||||
}
|
||||
|
||||
// Removes the value `value` into the set.
|
||||
// Similar to `std::unordered_set::erase`.
|
||||
// Returns the number of erased elements.
|
||||
|
@ -286,6 +286,30 @@ constexpr std::array kCapabilities{
|
||||
spv::Capability::Max,
|
||||
};
|
||||
|
||||
namespace {
|
||||
std::vector<TestEnum> enumerateValuesFromToWithStep(size_t start, size_t end,
|
||||
size_t step) {
|
||||
assert(end > start && "end > start");
|
||||
std::vector<TestEnum> orderedValues;
|
||||
for (size_t i = start; i < end; i += step) {
|
||||
orderedValues.push_back(static_cast<TestEnum>(i));
|
||||
}
|
||||
return orderedValues;
|
||||
}
|
||||
|
||||
EnumSet<TestEnum> createSetUnorderedInsertion(
|
||||
const std::vector<TestEnum>& values) {
|
||||
std::vector shuffledValues(values.cbegin(), values.cend());
|
||||
std::mt19937 rng(0);
|
||||
std::shuffle(shuffledValues.begin(), shuffledValues.end(), rng);
|
||||
EnumSet<TestEnum> set;
|
||||
for (auto value : shuffledValues) {
|
||||
set.insert(value);
|
||||
}
|
||||
return set;
|
||||
}
|
||||
} // namespace
|
||||
|
||||
TEST(EnumSet, IsEmpty1) {
|
||||
EnumSet<TestEnum> set;
|
||||
EXPECT_TRUE(set.empty());
|
||||
@ -439,29 +463,58 @@ TEST(EnumSet, DefaultIsEmpty) {
|
||||
}
|
||||
}
|
||||
|
||||
namespace {
|
||||
std::vector<TestEnum> enumerateValuesFromToWithStep(size_t start, size_t end,
|
||||
size_t step) {
|
||||
assert(end > start && "end > start");
|
||||
std::vector<TestEnum> orderedValues;
|
||||
for (size_t i = start; i < end; i += step) {
|
||||
orderedValues.push_back(static_cast<TestEnum>(i));
|
||||
}
|
||||
return orderedValues;
|
||||
TEST(EnumSet, EqualityCompareEmpty) {
|
||||
EnumSet<TestEnum> set1;
|
||||
EnumSet<TestEnum> set2;
|
||||
|
||||
EXPECT_TRUE(set1 == set2);
|
||||
EXPECT_FALSE(set1 != set2);
|
||||
}
|
||||
|
||||
EnumSet<TestEnum> createSetUnorderedInsertion(
|
||||
const std::vector<TestEnum>& values) {
|
||||
std::vector shuffledValues(values.cbegin(), values.cend());
|
||||
std::mt19937 rng(0);
|
||||
std::shuffle(shuffledValues.begin(), shuffledValues.end(), rng);
|
||||
EnumSet<TestEnum> set;
|
||||
for (auto value : shuffledValues) {
|
||||
set.insert(value);
|
||||
}
|
||||
return set;
|
||||
TEST(EnumSet, EqualityCompareSame) {
|
||||
EnumSet<TestEnum> set1;
|
||||
EnumSet<TestEnum> set2;
|
||||
|
||||
set1.insert(TestEnum::ONE);
|
||||
set1.insert(TestEnum::TWENTY);
|
||||
set2.insert(TestEnum::TWENTY);
|
||||
set2.insert(TestEnum::ONE);
|
||||
|
||||
EXPECT_TRUE(set1 == set2);
|
||||
EXPECT_FALSE(set1 != set2);
|
||||
}
|
||||
|
||||
TEST(EnumSet, EqualityCompareDifferent) {
|
||||
EnumSet<TestEnum> set1;
|
||||
EnumSet<TestEnum> set2;
|
||||
|
||||
set1.insert(TestEnum::ONE);
|
||||
set1.insert(TestEnum::TWENTY);
|
||||
set2.insert(TestEnum::FIVE);
|
||||
set2.insert(TestEnum::ONE);
|
||||
|
||||
EXPECT_FALSE(set1 == set2);
|
||||
EXPECT_TRUE(set1 != set2);
|
||||
}
|
||||
|
||||
TEST(EnumSet, ConstructFromIterators) {
|
||||
auto orderedValues = enumerateValuesFromToWithStep(0, 2, /* step= */ 1);
|
||||
EnumSet<TestEnum> set1 = createSetUnorderedInsertion(orderedValues);
|
||||
|
||||
EnumSet<TestEnum> set2(orderedValues.cbegin(), orderedValues.cend());
|
||||
|
||||
EXPECT_EQ(set1, set2);
|
||||
}
|
||||
|
||||
TEST(EnumSet, InsertUsingIteratorRange) {
|
||||
auto orderedValues = enumerateValuesFromToWithStep(0, 2, /* step= */ 1);
|
||||
EnumSet<TestEnum> set1 = createSetUnorderedInsertion(orderedValues);
|
||||
|
||||
EnumSet<TestEnum> set2;
|
||||
set2.insert(orderedValues.cbegin(), orderedValues.cend());
|
||||
|
||||
EXPECT_EQ(set1, set2);
|
||||
}
|
||||
} // namespace
|
||||
|
||||
TEST(CapabilitySet, RangeBasedLoopOrderIsEnumOrder) {
|
||||
auto orderedValues = enumerateValuesFromToWithStep(0, 2, /* step= */ 1);
|
||||
|
Loading…
Reference in New Issue
Block a user