Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
20 changes: 19 additions & 1 deletion tests/std/tests/P0896R4_ranges_range_machinery/test.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,11 @@
#include <valarray>
#include <vector>

#if _HAS_CXX23
#include <flat_map>
#include <flat_set>
#endif // _HAS_CXX23

#include <range_algorithm_support.hpp>

// Note that many tests herein assume:
Expand Down Expand Up @@ -836,7 +841,11 @@ constexpr bool test_std_container() {
}
static_assert(test_empty<T&, true>());
if constexpr (std::contiguous_iterator<I>) {
static_assert(test_data<T&, V*>());
if constexpr (std::is_same_v<I, CI>) {
static_assert(test_data<T&, V const*>());
} else {
static_assert(test_data<T&, V*>());
}
static_assert(test_cdata<T&, V const*>());
}
static_assert(!ranges::view<T&>);
Expand Down Expand Up @@ -899,6 +908,7 @@ static_assert(test_std_container<std::multimap<int, int>, std::bidirectional_ite
static_assert(test_std_container<std::multiset<int>, std::bidirectional_iterator_tag>());
static_assert(test_std_container<std::set<int>, std::bidirectional_iterator_tag>());
static_assert(test_std_container<std::string, std::contiguous_iterator_tag>());
// Implementation-specific: unordered_meow uses list's iterators, so they're bidirectional instead of forward.
static_assert(test_std_container<std::unordered_map<int, int>, std::bidirectional_iterator_tag>());
static_assert(test_std_container<std::unordered_multimap<int, int>, std::bidirectional_iterator_tag>());
static_assert(test_std_container<std::unordered_multiset<int>, std::bidirectional_iterator_tag>());
Expand All @@ -907,6 +917,14 @@ static_assert(test_std_container<std::vector<int>, std::contiguous_iterator_tag>
static_assert(test_std_container<std::vector<bool>, std::random_access_iterator_tag>());
static_assert(test_std_container<std::wstring, std::contiguous_iterator_tag>());

#if _HAS_CXX23
static_assert(test_std_container<std::flat_map<int, int>, std::random_access_iterator_tag>());
static_assert(test_std_container<std::flat_multimap<int, int>, std::random_access_iterator_tag>());
// Implementation-specific: flat_set uses the underlying container's iterators, so they're contiguous here.
static_assert(test_std_container<std::flat_set<int>, std::contiguous_iterator_tag>());
static_assert(test_std_container<std::flat_multiset<int>, std::contiguous_iterator_tag>());
#endif // _HAS_CXX23

// Validate that "old" fancy pointers that fail to model contiguous_iterator don't break contiguity of containers.
template <class T>
struct fancy_pointer {
Expand Down
60 changes: 56 additions & 4 deletions tests/std/tests/P1206R7_ranges_to_mappish/test.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -4,11 +4,15 @@
#include <algorithm>
#include <cassert>
#include <cstddef>
#include <flat_map>
#include <functional>
#include <map>
#include <memory>
#include <ranges>
#include <string_view>
#include <unordered_map>
#include <utility>
#include <vector>

#include <range_algorithm_support.hpp>

Expand Down Expand Up @@ -71,6 +75,20 @@ struct mappish_instantiator {
template <class Key, class Val, class... Args>
using apply = std::unordered_multimap<Key, Val, std::hash<Key>, std::equal_to<Key>, Args...>;
};
template <>
struct deduce_container_impl<std::flat_map> {
template <class Key, class Val, class... Args>
using apply = std::flat_map<Key, Val, std::less<Key>,
std::vector<Key, typename std::allocator_traits<Args>::template rebind_alloc<Key>...>,
std::vector<Val, typename std::allocator_traits<Args>::template rebind_alloc<Val>...>>;
};
template <>
struct deduce_container_impl<std::flat_multimap> {
template <class Key, class Val, class... Args>
using apply = std::flat_multimap<Key, Val, std::less<Key>,
std::vector<Key, typename std::allocator_traits<Args>::template rebind_alloc<Key>...>,
std::vector<Val, typename std::allocator_traits<Args>::template rebind_alloc<Val>...>>;
};

template <template <class...> class C, class Key, class Val, class... Args>
using deduce_container = deduce_container_impl<C>::template apply<Key, Val, Args...>;
Expand Down Expand Up @@ -145,26 +163,56 @@ struct mappish_instantiator {

using Alloc = myalloc<std::pair<const int, std::string_view>>;
using T = deduce_container<C, int, std::string_view, Alloc>;
constexpr bool is_flat =
std::_Is_specialization_v<T, std::flat_map> || std::_Is_specialization_v<T, std::flat_multimap>;

{
std::same_as<T> auto c4 = ranges::to<T>(R{some_pairs}, Alloc{13});
assert(c4.get_allocator().state == 13);
assert(ranges::is_permutation(c4, expected, any_pair_eq));

if constexpr (is_flat) {
const auto containers = std::move(c4).extract();
assert(containers.keys.get_allocator().state == 13);
assert(containers.values.get_allocator().state == 13);
} else {
assert(c4.get_allocator().state == 13);
}
}
{
std::same_as<T> auto c5 = ranges::to<C>(R{some_pairs}, Alloc{13});
assert(c5.get_allocator().state == 13);
assert(ranges::is_permutation(c5, expected, any_pair_eq));

if constexpr (is_flat) {
const auto containers = std::move(c5).extract();
assert(containers.keys.get_allocator().state == 13);
assert(containers.values.get_allocator().state == 13);
} else {
assert(c5.get_allocator().state == 13);
}
}
{
std::same_as<T> auto c6 = R{some_pairs} | ranges::to<T>(Alloc{13});
assert(c6.get_allocator().state == 13);
assert(ranges::is_permutation(c6, expected, any_pair_eq));

if constexpr (is_flat) {
const auto containers = std::move(c6).extract();
assert(containers.keys.get_allocator().state == 13);
assert(containers.values.get_allocator().state == 13);
} else {
assert(c6.get_allocator().state == 13);
}
}
{
std::same_as<T> auto c7 = R{some_pairs} | ranges::to<C>(Alloc{13});
assert(c7.get_allocator().state == 13);
assert(ranges::is_permutation(c7, expected, any_pair_eq));

if constexpr (is_flat) {
const auto containers = std::move(c7).extract();
assert(containers.keys.get_allocator().state == 13);
assert(containers.values.get_allocator().state == 13);
} else {
assert(c7.get_allocator().state == 13);
}
}
}

Expand All @@ -176,6 +224,8 @@ struct mappish_instantiator {
test_mappish<R, std::multimap, is_multi::yes>();
test_mappish<R, std::unordered_map, is_multi::no>();
test_mappish<R, std::unordered_multimap, is_multi::yes>();
test_mappish<R, std::flat_map, is_multi::no>();
test_mappish<R, std::flat_multimap, is_multi::yes>();
}
}
};
Expand All @@ -186,4 +236,6 @@ int main() {
mappish_instantiator::test_copy_move<std::multimap>();
mappish_instantiator::test_copy_move<std::unordered_map>();
mappish_instantiator::test_copy_move<std::unordered_multimap>();
mappish_instantiator::test_copy_move<std::flat_map>();
mappish_instantiator::test_copy_move<std::flat_multimap>();
}
49 changes: 45 additions & 4 deletions tests/std/tests/P1206R7_ranges_to_settish/test.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,9 @@
#include <algorithm>
#include <cassert>
#include <cstddef>
#include <flat_set>
#include <functional>
#include <memory>
#include <ranges>
#include <set>
#include <unordered_set>
Expand Down Expand Up @@ -65,6 +68,18 @@ struct settish_instantiator {
template <class Key, class... Args>
using apply = std::unordered_multiset<Key, std::hash<Key>, std::equal_to<Key>, Args...>;
};
template <>
struct deduce_container_impl<std::flat_set> {
template <class Key, class... Args>
using apply = std::flat_set<Key, std::less<Key>,
std::vector<Key, typename std::allocator_traits<Args>::template rebind_alloc<Key>...>>;
};
template <>
struct deduce_container_impl<std::flat_multiset> {
template <class Key, class... Args>
using apply = std::flat_multiset<Key, std::less<Key>,
std::vector<Key, typename std::allocator_traits<Args>::template rebind_alloc<Key>...>>;
};

template <template <class...> class C, class Key, class... Args>
using deduce_container = deduce_container_impl<C>::template apply<Key, Args...>;
Expand Down Expand Up @@ -139,26 +154,48 @@ struct settish_instantiator {

using Alloc = myalloc<int>;
using T = deduce_container<C, int, Alloc>;
constexpr bool is_flat =
std::_Is_specialization_v<T, std::flat_set> || std::_Is_specialization_v<T, std::flat_multiset>;

{
std::same_as<T> auto c4 = ranges::to<T>(R{some_ints}, Alloc{13});
assert(c4.get_allocator().state == 13);
assert(ranges::is_permutation(c4, expected));

if constexpr (is_flat) {
assert(std::move(c4).extract().get_allocator().state == 13);
} else {
assert(c4.get_allocator().state == 13);
}
}
{
std::same_as<T> auto c5 = ranges::to<C>(R{some_ints}, Alloc{13});
assert(c5.get_allocator().state == 13);
assert(ranges::is_permutation(c5, expected));

if constexpr (is_flat) {
assert(std::move(c5).extract().get_allocator().state == 13);
} else {
assert(c5.get_allocator().state == 13);
}
}
{
std::same_as<T> auto c6 = R{some_ints} | ranges::to<T>(Alloc{13});
assert(c6.get_allocator().state == 13);
assert(ranges::is_permutation(c6, expected));

if constexpr (is_flat) {
assert(std::move(c6).extract().get_allocator().state == 13);
} else {
assert(c6.get_allocator().state == 13);
}
}
{
std::same_as<T> auto c7 = R{some_ints} | ranges::to<C>(Alloc{13});
assert(c7.get_allocator().state == 13);
assert(ranges::is_permutation(c7, expected));

if constexpr (is_flat) {
assert(std::move(c7).extract().get_allocator().state == 13);
} else {
assert(c7.get_allocator().state == 13);
}
}
}

Expand All @@ -168,6 +205,8 @@ struct settish_instantiator {
test_settish<R, std::multiset, is_multi::yes>();
test_settish<R, std::unordered_set, is_multi::no>();
test_settish<R, std::unordered_multiset, is_multi::yes>();
test_settish<R, std::flat_set, is_multi::no>();
test_settish<R, std::flat_multiset, is_multi::yes>();
}
};

Expand All @@ -177,4 +216,6 @@ int main() {
settish_instantiator::test_copy_move<std::multiset>();
settish_instantiator::test_copy_move<std::unordered_set>();
settish_instantiator::test_copy_move<std::unordered_multiset>();
settish_instantiator::test_copy_move<std::flat_set>();
settish_instantiator::test_copy_move<std::flat_multiset>();
}
53 changes: 27 additions & 26 deletions tests/std/tests/P2286R8_text_formatting_range_map/test.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@
#include <concepts>
#include <cstddef>
#include <cstring>
#include <flat_map>
#include <format>
#include <iterator>
#include <map>
Expand Down Expand Up @@ -325,7 +326,7 @@ void test_char(TestFunction check, ExceptionTest check_exception) {

template <class TestFunction, class ExceptionTest>
void test_char_to_wchar(TestFunction check, ExceptionTest check_exception) {
map<char, char> input{{'a', 'A'}, {'c', 'C'}, {'b', 'B'}};
flat_map<char, char> input{{'a', 'A'}, {'c', 'C'}, {'b', 'B'}};

using CharT = wchar_t;
check(SV("{'a': 'A', 'b': 'B', 'c': 'C'}"), SV("{}"), input);
Expand Down Expand Up @@ -646,24 +647,24 @@ void test_int(TestFunction check, ExceptionTest check_exception) {

template <class CharT, class TestFunction, class ExceptionTest>
void test_floating_point(TestFunction check, ExceptionTest check_exception) {
map<double, double> input{{1.0, -1.0}, {-42, 42}};
flat_multimap<double, double> input{{11.0, 42.0}, {11.0, -1.0}};

check(SV("{-42: 42, 1: -1}"), SV("{}"), input);
check(SV("{-42: 42, 1: -1}^42"), SV("{}^42"), input);
check(SV("{-42: 42, 1: -1}^42"), SV("{:}^42"), input);
check(SV("{11: 42, 11: -1}"), SV("{}"), input);
check(SV("{11: 42, 11: -1}^42"), SV("{}^42"), input);
check(SV("{11: 42, 11: -1}^42"), SV("{:}^42"), input);

// ***** underlying has no format-spec

// *** align-fill & width ***
check(SV("{-42: 42, 1: -1} "), SV("{:21}"), input);
check(SV("{-42: 42, 1: -1}*****"), SV("{:*<21}"), input);
check(SV("__{-42: 42, 1: -1}___"), SV("{:_^21}"), input);
check(SV("#####{-42: 42, 1: -1}"), SV("{:#>21}"), input);
check(SV("{11: 42, 11: -1} "), SV("{:21}"), input);
check(SV("{11: 42, 11: -1}*****"), SV("{:*<21}"), input);
check(SV("__{11: 42, 11: -1}___"), SV("{:_^21}"), input);
check(SV("#####{11: 42, 11: -1}"), SV("{:#>21}"), input);

check(SV("{-42: 42, 1: -1} "), SV("{:{}}"), input, 21);
check(SV("{-42: 42, 1: -1}*****"), SV("{:*<{}}"), input, 21);
check(SV("__{-42: 42, 1: -1}___"), SV("{:_^{}}"), input, 21);
check(SV("#####{-42: 42, 1: -1}"), SV("{:#>{}}"), input, 21);
check(SV("{11: 42, 11: -1} "), SV("{:{}}"), input, 21);
check(SV("{11: 42, 11: -1}*****"), SV("{:*<{}}"), input, 21);
check(SV("__{11: 42, 11: -1}___"), SV("{:_^{}}"), input, 21);
check(SV("#####{11: 42, 11: -1}"), SV("{:#>{}}"), input, 21);

check_exception("The format string contains an invalid escape sequence", SV("{:}<}"), input);
check_exception("The fill option contains an invalid value", SV("{:{<}"), input);
Expand All @@ -686,10 +687,10 @@ void test_floating_point(TestFunction check, ExceptionTest check_exception) {
check_exception("The format specifier should consume the input or end with a '}'", SV("{:L}"), input);

// *** n
check(SV("__-42: 42, 1: -1___"), SV("{:_^19n}"), input);
check(SV("__11: 42, 11: -1___"), SV("{:_^19n}"), input);

// *** type ***
check(SV("__{-42: 42, 1: -1}___"), SV("{:_^21m}"), input); // the m type does the same as the default.
check(SV("__{11: 42, 11: -1}___"), SV("{:_^21m}"), input); // the m type does the same as the default.
check_exception("Type s requires character type as formatting argument", SV("{:s}"), input);
check_exception("Type ?s requires character type as formatting argument", SV("{:?s}"), input);

Expand All @@ -698,15 +699,15 @@ void test_floating_point(TestFunction check, ExceptionTest check_exception) {
}

// ***** Only underlying has a format-spec
check(SV("{-42: 42 , 1: -1 }"), SV("{::10}"), input);
check(SV("{-42: 42***, 1: -1*****}"), SV("{::*<10}"), input);
check(SV("{_-42: 42__, __1: -1___}"), SV("{::_^10}"), input);
check(SV("{###-42: 42, #####1: -1}"), SV("{::#>10}"), input);
check(SV("{11: 42 , 11: -1 }"), SV("{::10}"), input);
check(SV("{11: 42****, 11: -1****}"), SV("{::*<10}"), input);
check(SV("{__11: 42__, __11: -1__}"), SV("{::_^10}"), input);
check(SV("{####11: 42, ####11: -1}"), SV("{::#>10}"), input);

check(SV("{-42: 42 , 1: -1 }"), SV("{::{}}"), input, 10);
check(SV("{-42: 42***, 1: -1*****}"), SV("{::*<{}}"), input, 10);
check(SV("{_-42: 42__, __1: -1___}"), SV("{::_^{}}"), input, 10);
check(SV("{###-42: 42, #####1: -1}"), SV("{::#>{}}"), input, 10);
check(SV("{11: 42 , 11: -1 }"), SV("{::{}}"), input, 10);
check(SV("{11: 42****, 11: -1****}"), SV("{::*<{}}"), input, 10);
check(SV("{__11: 42__, __11: -1__}"), SV("{::_^{}}"), input, 10);
check(SV("{####11: 42, ####11: -1}"), SV("{::#>{}}"), input, 10);

check_exception("The format string contains an invalid escape sequence", SV("{::}<}"), input);
check_exception("The fill option contains an invalid value", SV("{::{<}"), input);
Expand Down Expand Up @@ -734,9 +735,9 @@ void test_floating_point(TestFunction check, ExceptionTest check_exception) {
}

// ***** Both have a format-spec
check(SV("^^{###-42: 42, #####1: -1}^^^"), SV("{:^^29:#>10}"), input);
check(SV("^^{###-42: 42, #####1: -1}^^^"), SV("{:^^{}:#>10}"), input, 29);
check(SV("^^{###-42: 42, #####1: -1}^^^"), SV("{:^^{}:#>{}}"), input, 29, 10);
check(SV("^^{####11: 42, ####11: -1}^^^"), SV("{:^^29:#>10}"), input);
check(SV("^^{####11: 42, ####11: -1}^^^"), SV("{:^^{}:#>10}"), input, 29);
check(SV("^^{####11: 42, ####11: -1}^^^"), SV("{:^^{}:#>{}}"), input, 29, 10);

check_exception(
"The argument index value is too large for the number of arguments supplied", SV("{:^^{}:#>10}"), input);
Expand Down
Loading