Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
49 commits
Select commit Hold shift + click to select a range
c06daba
Test that hints given to `flat_multiset::emplace_hint` and `insert` a…
vmichal Jan 7, 2026
08f6af5
Test that hints given to `flat_multimap::emplace_hint` and `insert` a…
vmichal Jan 7, 2026
e24412d
Add more tests for flat_set::erase.
vmichal Jan 7, 2026
355c391
Refactor existing flat_map construction tests - use all codepaths (in…
vmichal Jan 8, 2026
ba114e6
Refactor existing flat_map allocator construction tests - add allocat…
vmichal Jan 8, 2026
439980b
Add tests for flat_map construction from (iter, iter), initializer_li…
vmichal Jan 8, 2026
386b1f4
Reword fixme regarding missing flat_map construction tests.
vmichal Jan 8, 2026
5139e7a
Unify checks that flat_map and flat_multimap accept their dedicated _…
vmichal Jan 8, 2026
21838ca
Generalize flat_map erase_if and swap tests for various containers.
vmichal Jan 8, 2026
8a4dd86
Remove explicitly specified template arguments in flat_set constructo…
vmichal Jan 8, 2026
804dc74
Merge branch 'feature/flat_map' into test-flat-meow
vmichal Jan 8, 2026
da13b30
Fix typo
vmichal Jan 9, 2026
70c9c33
Test that heterogeneous lookup works with transparent comparator that…
vmichal Jan 9, 2026
f3b0642
Don't optimize heterogeneous when key is not of key_type.
vmichal Jan 9, 2026
99d9892
Properly use flat_set deduction guides in tests.
vmichal Jan 9, 2026
ee5e510
Reduce scope of previously-global type alias in flat_set tests.
vmichal Jan 9, 2026
a157e32
Add death tests for all asserts in <flat_set>
vmichal Jan 9, 2026
c94b5e2
Add death tests for all asserts in <flat_map>
vmichal Jan 9, 2026
3673606
Separate death tests into logical groups by what type of violation th…
vmichal Jan 9, 2026
1c1e240
Test that heterogeneous flat_map lookup operations don't attempt to c…
vmichal Jan 9, 2026
2ff469a
Extract code testing container requirements from flat_set test into a…
vmichal Jan 9, 2026
72a7967
Refactor requirements on flat_map to use checks shared with flat_set.
vmichal Jan 9, 2026
652e37b
Improve printing of causes of failing tests for containers that don't…
vmichal Jan 9, 2026
d8e6812
Fix three-way-comparability test
vmichal Jan 9, 2026
047ee85
Check invariants and requirements of more flat_map objects in tests
vmichal Jan 9, 2026
513f799
Remove using namespace std from the shared test header, add std:: qua…
vmichal Jan 9, 2026
65dc3c4
Fix typo: Check invariants of correct container. Properly compare ref…
vmichal Jan 9, 2026
c402040
flat_set::reference should not be mutable. Make it the same type as f…
vmichal Jan 9, 2026
5b14ad2
Revert "flat_set::reference should not be mutable. Make it the same t…
vmichal Jan 9, 2026
2ab424f
Container *begin() may return reference or const_reference (as is the…
vmichal Jan 9, 2026
e51799e
Improve comments.
StephanTLavavej Jan 9, 2026
637ab36
Include more headers.
StephanTLavavej Jan 9, 2026
62f38a3
Down with typename.
StephanTLavavej Jan 9, 2026
14f0159
Remove unused and shadowing `struct is_nothrow_swappable`.
StephanTLavavej Jan 9, 2026
3d87da6
Use aliases.
StephanTLavavej Jan 9, 2026
3e2958c
Avoid shadowing: `empty` => `my_empty`
StephanTLavavej Jan 9, 2026
15dc457
`template <typename T>` => `template <class T>`
StephanTLavavej Jan 9, 2026
7ee5304
Increase strictness.
StephanTLavavej Jan 9, 2026
0877fbc
Add const.
StephanTLavavej Jan 9, 2026
da4b643
Test const overloading.
StephanTLavavej Jan 10, 2026
615f456
Consistently order key_container_type before mapped_container_type.
StephanTLavavej Jan 10, 2026
a01e682
Use `adjacent_find()` to check uniqueness.
StephanTLavavej Jan 10, 2026
0a78e60
`std::declval` => `declval`
StephanTLavavej Jan 11, 2026
cf5a3f8
Use `lt` alias.
StephanTLavavej Jan 11, 2026
5510f60
West const.
StephanTLavavej Jan 11, 2026
5c584ec
`_STD` => `std::`, `_RANGES` => `ranges::`
StephanTLavavej Jan 11, 2026
f2a0049
`assert_check_content` => `check_content`, mark check functions as `[…
StephanTLavavej Jan 11, 2026
d7af0bd
Drop bogus commented-out tuple_size specialization.
StephanTLavavej Jan 11, 2026
96ca5f7
Construct temporaries with braces.
StephanTLavavej Jan 11, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion stl/inc/flat_set
Original file line number Diff line number Diff line change
Expand Up @@ -637,7 +637,7 @@ private:
_NODISCARD size_type _Erase(const _Ty& _Val) {
_STL_INTERNAL_STATIC_ASSERT(_Transparent<key_compare> || is_same_v<_Ty, _Kty>);

if constexpr (_IsUnique) {
if constexpr (_IsUnique && is_same_v<_Ty, key_type>) { // Optimization restricted due to GH-5992
const const_iterator _Where = lower_bound(_Val);
if (_Where != cend() && !_Compare(_Val, *_Where)) {
_Mycont.erase(_Where);
Expand Down
189 changes: 189 additions & 0 deletions tests/std/include/test_container_requirements.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,189 @@
// Copyright (c) Microsoft Corporation.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception

#pragma once

#include <algorithm>
#include <cassert>
#include <compare>
#include <format>
#include <iterator>
#include <print>
#include <type_traits>
#include <utility>

// Extracted common functionality from flat_map and flat_set tests.
// May be extended for other containers if needed.

template <class T>
void assert_container_requirements(const T& s) {
T m = s;
assert(m == s);

static_assert(std::is_same_v<decltype(m = s), T&>);
static_assert(std::is_same_v<decltype(m = std::move(m)), T&>);
static_assert(std::is_same_v<decltype(m.begin()), typename T::iterator>);
static_assert(std::is_same_v<decltype(m.end()), typename T::iterator>);
static_assert(std::is_same_v<decltype(s.begin()), typename T::const_iterator>);
static_assert(std::is_same_v<decltype(s.end()), typename T::const_iterator>);
static_assert(std::is_same_v<decltype(m.cbegin()), typename T::const_iterator>);
static_assert(std::is_same_v<decltype(m.cend()), typename T::const_iterator>);
static_assert(std::is_same_v<decltype(s.cbegin()), typename T::const_iterator>);
static_assert(std::is_same_v<decltype(s.cend()), typename T::const_iterator>);
static_assert(std::is_convertible_v<typename T::iterator, typename T::const_iterator>);
static_assert(std::is_same_v<decltype(m.begin() <=> m.end()), std::strong_ordering>);
static_assert(std::is_same_v<decltype(s.size()), typename T::size_type>);
static_assert(std::is_same_v<decltype(s.max_size()), typename T::size_type>);
static_assert(std::is_same_v<decltype(*m.begin()), typename T::reference>
|| std::is_same_v<decltype(*m.begin()), typename T::const_reference>);
static_assert(std::is_same_v<decltype(*m.cbegin()), typename T::const_reference>);

T my_moved = std::move(m);
assert(!(my_moved != s));

T my_empty{};
assert(my_empty.empty());

T non_empty = s;
my_empty.swap(non_empty);
assert(non_empty.empty());
assert(my_empty == s);

std::swap(my_empty, non_empty);
assert(my_empty.empty());
assert(non_empty == s);

assert(s.cbegin() <= s.cend());
assert((s.cbegin() < s.cend()) == !s.empty());

assert(m.begin() <= m.end());
assert((m.begin() < m.end()) == !m.empty());

assert(static_cast<T::size_type>(s.cend() - s.cbegin()) == s.size());
}

template <class T>
void assert_reversible_container_requirements(const T& s) {
static_assert(std::is_same_v<std::reverse_iterator<typename T::iterator>, typename T::reverse_iterator>);
static_assert(
std::is_same_v<std::reverse_iterator<typename T::const_iterator>, typename T::const_reverse_iterator>);
static_assert(std::is_same_v<decltype(T{}.rbegin()), typename T::reverse_iterator>);
static_assert(std::is_same_v<decltype(T{}.rend()), typename T::reverse_iterator>);
static_assert(std::is_same_v<decltype(s.rbegin()), typename T::const_reverse_iterator>);
static_assert(std::is_same_v<decltype(s.rend()), typename T::const_reverse_iterator>);
static_assert(std::is_same_v<decltype(T{}.crbegin()), typename T::const_reverse_iterator>);
static_assert(std::is_same_v<decltype(T{}.crend()), typename T::const_reverse_iterator>);
static_assert(std::is_same_v<decltype(s.crbegin()), typename T::const_reverse_iterator>);
static_assert(std::is_same_v<decltype(s.crend()), typename T::const_reverse_iterator>);
static_assert(std::is_convertible_v<typename T::reverse_iterator, typename T::const_reverse_iterator>);
}

template <class T>
concept map_has_nothrow_swappable_containers = requires {
typename T::key_container_type;
typename T::mapped_container_type;
requires std::is_nothrow_swappable_v<typename T::key_container_type>;
requires std::is_nothrow_swappable_v<typename T::mapped_container_type>;
};

template <class T>
concept set_has_nothrow_swappable_containers = requires {
typename T::container_type;
requires std::is_nothrow_swappable_v<typename T::container_type>;
};

template <class T>
concept has_nothrow_swappable_containers =
set_has_nothrow_swappable_containers<T> || map_has_nothrow_swappable_containers<T>;

template <class T>
void assert_noexcept_requirements(T& s) {
static_assert(noexcept(s.begin()));
static_assert(noexcept(s.end()));
static_assert(noexcept(s.cbegin()));
static_assert(noexcept(s.cend()));
static_assert(noexcept(s.rbegin()));
static_assert(noexcept(s.rend()));
static_assert(noexcept(s.crbegin()));
static_assert(noexcept(s.crend()));

static_assert(noexcept(s.empty()));
static_assert(noexcept(s.size()));
static_assert(noexcept(s.max_size()));

if constexpr (!std::is_const_v<T>) {
constexpr bool is_noexcept =
has_nothrow_swappable_containers<T> && std::is_nothrow_swappable_v<typename T::key_compare>;
static_assert(noexcept(s.swap(s)) == is_noexcept);
static_assert(noexcept(std::ranges::swap(s, s)) == is_noexcept); // using ADL-swap
static_assert(noexcept(s.clear()));
}
}

template <bool ExpectedUnique, class T>
void assert_is_sorted_maybe_unique(const T& s) {
const auto val_comp = s.value_comp();
const auto begin_it = s.cbegin();
const auto end_it = s.cend();

// internal check by the container itself
assert(s._Is_sorted_and_unique());

// external check observable by the user
assert(std::is_sorted(begin_it, end_it, val_comp));
if constexpr (ExpectedUnique) {
const auto not_comp = [&](const auto& left, const auto& right) { return !val_comp(left, right); };
const bool is_unique = std::adjacent_find(begin_it, end_it, not_comp) == end_it;

if constexpr (std::formattable<T, char>) {
if (!is_unique) {
std::println("Container {} is not unique", s);
}
}
assert(is_unique);
}
}

template <class T>
void assert_set_requirements() {
using iterator = T::iterator;
using const_iterator = T::const_iterator;
using key_type = T::key_type;
using value_type = T::value_type;
using reference = T::reference;
using const_reference = T::const_reference;

static_assert(std::same_as<std::const_iterator<const_iterator>, const_iterator>);
static_assert(std::is_convertible_v<iterator, const_iterator>);

// additionally:
static_assert(std::is_same_v<key_type, value_type>);
static_assert(std::same_as<std::const_iterator<iterator>, iterator>);
static_assert(std::is_convertible_v<const_iterator, iterator>);
static_assert(std::is_same_v<decltype(*std::declval<T>().begin()), const value_type&>);
static_assert(std::is_same_v<std::remove_cvref_t<reference>, value_type>);
static_assert(std::is_same_v<const_reference, const value_type&>);
}

template <class T>
void assert_map_requirements() {
using iterator = T::iterator;
using const_iterator = T::const_iterator;
using key_type = T::key_type;
using value_type = T::value_type;
using mapped_type = T::mapped_type;

static_assert(std::same_as<std::const_iterator<const_iterator>, const_iterator>);
static_assert(std::is_convertible_v<iterator, const_iterator>);

// additionally:
static_assert(std::is_same_v<value_type, std::pair<key_type, mapped_type>>);
}

template <class T>
void assert_three_way_comparability() {
using value_type = T::value_type;
if constexpr (std::three_way_comparable<value_type>) {
static_assert(std::three_way_comparable<T>);
}
}
Loading