blob: 5bcda3464f1f4979c451baa5f63194ed9f58a741 [file] [log] [blame]
// { dg-do run { target c++23 } }
// { dg-timeout-factor 2 }
#include <flat_map>
#if __cpp_lib_flat_map != 202207L
# error "Feature-test macro __cpp_lib_flat_map has wrong value in <flat_map>"
#endif
#include <deque>
#include <ranges>
#include <vector>
#include <testsuite_allocator.h>
#include <testsuite_hooks.h>
#include <testsuite_iterators.h>
#include <tuple>
struct Gt {
template<typename T, typename U>
bool operator()(T const& l, U const & r) const
{ return l > r; }
};
void
test_deduction_guide()
{
__gnu_test::test_input_range<std::pair<long, float>> r(0, 0);
std::flat_map it1(r.begin(), r.begin());
static_assert(std::is_same_v<decltype(it1), std::flat_map<long, float>>);
std::flat_map fr1(std::from_range, r);
static_assert(std::is_same_v<decltype(fr1), std::flat_map<long, float>>);
Gt cmp;
std::flat_map it2(r.begin(), r.begin(), cmp);
static_assert(std::is_same_v<decltype(it2), std::flat_map<long, float, Gt>>);
std::flat_map fr2(std::from_range, r, cmp);
static_assert(std::is_same_v<decltype(fr2), std::flat_map<long, float, Gt>>);
using Alloc = __gnu_test::SimpleAllocator<std::pair<const long, float>>;
Alloc alloc;
// No matching deduction guide
// std::flat_map it3(r.begin(), r.begin(), alloc);
std::flat_map fr3(std::from_range, r, alloc);
static_assert(std::is_same_v<
decltype(fr3),
std::flat_map<long, float, std::less<long>,
std::vector<long, __gnu_test::SimpleAllocator<long>>,
std::vector<float, __gnu_test::SimpleAllocator<float>>>>);
// No matching deduction guide
// std::flat_map it4(r.begin(), r.begin(), cmp, alloc);
std::flat_map fr4(std::from_range, r, cmp, alloc);
static_assert(std::is_same_v<
decltype(fr4),
std::flat_map<long, float, Gt,
std::vector<long, __gnu_test::SimpleAllocator<long>>,
std::vector<float, __gnu_test::SimpleAllocator<float>>>>);
__gnu_test::test_input_range<std::pair<const long, const float>> r2(0, 0);
std::flat_map it5(r2.begin(), r2.begin());
static_assert(std::is_same_v<decltype(it5), std::flat_map<long, float>>);
std::flat_map fr5(std::from_range, r2);
static_assert(std::is_same_v<decltype(fr5), std::flat_map<long, float>>);
__gnu_test::test_input_range<std::pair<const long&, float&>> r3(0, 0);
std::flat_map it6(r3.begin(), r3.begin());
static_assert(std::is_same_v<decltype(it6), std::flat_map<long, float>>);
std::flat_map fr6(std::from_range, r3);
static_assert(std::is_same_v<decltype(fr6), std::flat_map<long, float>>);
__gnu_test::test_input_range<std::tuple<long, float>> r4(0, 0);
std::flat_map it7(r4.begin(), r4.begin());
static_assert(std::is_same_v<decltype(it7), std::flat_map<long, float>>);
std::flat_map fr7(std::from_range, r4);
static_assert(std::is_same_v<decltype(fr7), std::flat_map<long, float>>);
}
template<template<typename> class KeyContainer, template<typename> class MappedContainer>
void
test01()
{
std::flat_map<int, int, std::less<int>, KeyContainer<int>, MappedContainer<int>> m;
static_assert( std::ranges::random_access_range<decltype(m)> );
m.insert({1,-1});
m.insert({2,-2});
m.insert({3,-3});
m.insert({1,-4});
m.insert({2,-5});
m.insert({3,-6});
m.insert({0, 0});
VERIFY( m.size() == 4 );
VERIFY( std::ranges::equal(m.keys(), (int[]){0, 1, 2, 3}) );
VERIFY( std::ranges::equal(m.values(), (int[]){0, -1, -2, -3}) );
for (int i = 0; i < 4; i++)
{
m.clear();
int j = i;
m.insert(m.end(), {j,-j});
j = (j + 1) % 4;
m.insert(m.end(), {j,-j});
j = (j + 1) % 4;
m.insert(m.end(), {j,-j});
j = (j + 1) % 4;
m.insert(m.end(), {j,-j});
m.insert(m.begin() + i, {1,-4});
m.insert(m.begin() + i, {2,-5});
m.insert(m.begin() + i, {3,-6});
m.insert(m.begin() + i, {0,-7});
VERIFY( std::ranges::equal(m.keys(), (int[]){0, 1, 2, 3}) );
VERIFY( std::ranges::equal(m.values(), (int[]){0, -1, -2, -3}) );
}
m.clear();
m = {{10,0},{10,1}};
VERIFY( m.size() == 1 );
m.insert({{11,2},{12,3},{11,4}});
VERIFY( m.size() == 3 );
VERIFY( m[10] == 0 );
VERIFY( m[11] == 2 );
VERIFY( m[12] == 3 );
m[20] = 42;
VERIFY( m[20] == 42 );
VERIFY( m.end()[-1] == std::pair(20,42) );
}
void
test02()
{
std::flat_map<int, int, std::greater<int>> m;
static_assert( std::ranges::random_access_range<decltype(m)> );
auto r = m.insert({1,-1});
VERIFY( r.first->first == 1 && r.first->second == -1 && r.second );
r = m.insert({2,-2});
VERIFY( r.first->first == 2 && r.first->second == -2 && r.second );
r = m.insert({3,-3});
VERIFY( r.first->first == 3 && r.first->second == -3 && r.second );
r = m.insert({1,-4});
VERIFY( r.first->first == 1 && r.first->second == -1 && !r.second );
r = m.insert({2,-5});
VERIFY( r.first->first == 2 && r.first->second == -2 && !r.second );
r = m.insert({3,-6});
VERIFY( r.first->first == 3 && r.first->second == -3 && !r.second );
r = m.insert_or_assign(0, 0);
VERIFY( r.first->first == 0 && r.first->second == 0 && r.second );
r = m.insert_or_assign(0, 1);
VERIFY( r.first->first == 0 && r.first->second == 1 && !r.second );
VERIFY( *m.insert_or_assign(m.end(), 0, 2) == std::pair(0, 2) );
VERIFY( m.size() == 4 );
VERIFY( std::ranges::equal(m.keys(), (int[]){3, 2, 1, 0}) );
VERIFY( std::ranges::equal(m.values(), (int[]){-3, -2, -1, 2}) );
VERIFY( m.contains(3) && !m.contains(7) );
VERIFY( m.count(3) == 1 );
}
void
test03()
{
std::flat_map<int, int> m;
m = {std::pair(1, 2), {3, 4}, {5, 6}};
m.insert({std::pair(7, 8), {9, 10}});
auto it = m.find(0);
VERIFY( it == m.end() );
it = m.find(9);
VERIFY( it->second == 10 );
const auto n = m;
VERIFY( m == m );
VERIFY( m == n );
m.erase(m.begin());
m.erase(5);
m.erase(m.end()-2, m.end());
VERIFY( std::ranges::equal(m, (std::pair<int, int>[]){{3, 4}}) );
VERIFY( m != n );
VERIFY( n < m );
m = n;
erase_if(m, [](const auto& x) { auto [k, v] = x; return k < 5 || k > 5; });
VERIFY( std::ranges::equal(m, (std::pair<int, int>[]){{5, 6}}) );
}
void
test04()
{
using vector = std::vector<int, __gnu_test::uneq_allocator<int>>;
vector v1 = {1, 2, 3};
vector v2 = {4, 5, 6};
__gnu_test::uneq_allocator<int> alloc(42);
using flat_map = std::flat_map<int, int, std::less<int>, vector, vector>;
flat_map m1(alloc);
VERIFY( m1.keys().get_allocator().get_personality() == 42 );
VERIFY( m1.values().get_allocator().get_personality() == 42 );
flat_map m2(v1, v2, alloc);
VERIFY( m2.keys().get_allocator().get_personality() == 42 );
VERIFY( m2.values().get_allocator().get_personality() == 42 );
flat_map m3(std::sorted_unique_t{}, v1, v2, alloc);
VERIFY( m2.keys().get_allocator().get_personality() == 42 );
VERIFY( m2.values().get_allocator().get_personality() == 42 );
alloc = __gnu_test::uneq_allocator<int>(43);
flat_map m4(m3, alloc);
VERIFY( m4.keys().get_allocator().get_personality() == 43 );
VERIFY( m4.values().get_allocator().get_personality() == 43 );
alloc = __gnu_test::uneq_allocator<int>(44);
flat_map m5(std::move(m4), alloc);
VERIFY( m5.keys().get_allocator().get_personality() == 44 );
VERIFY( m5.values().get_allocator().get_personality() == 44 );
}
void
test05()
{
std::vector<std::pair<int, int>> v = {{2, -2}, {3,-3}, {1,-1}, {5,-5}, {4,-4}};
std::flat_map<int, int> m = {std::from_range, v};
VERIFY( std::ranges::equal(m | std::views::keys, (int[]){1, 2, 3, 4, 5}) );
VERIFY( std::ranges::equal(m | std::views::values, (int[]){-1, -2, -3, -4, -5}) );
}
void
test06()
{
// PR libstdc++/118156 - flat_foo::insert_range cannot handle non-common ranges
std::flat_map<int, int> m;
auto r = std::views::zip(std::views::iota(1), std::views::iota(2)) | std::views::take(5);
static_assert(!std::ranges::common_range<decltype(r)>);
m.insert_range(r);
VERIFY( std::ranges::equal(m | std::views::keys, (int[]){1, 2, 3, 4, 5}) );
VERIFY( std::ranges::equal(m | std::views::values, (int[]){2, 3, 4, 5, 6}) );
m.clear();
m.insert_range(r | std::views::reverse);
VERIFY( std::ranges::equal(m | std::views::keys, (int[]){1, 2, 3, 4, 5}) );
VERIFY( std::ranges::equal(m | std::views::values, (int[]){2, 3, 4, 5, 6}) );
}
void
test07()
{
// PR libstdc++/119427 - std::erase_if(std::flat_foo) does not work
// PR libstdc++/120465 - erase_if for flat_map calls predicate with incorrect type
std::flat_map<int, int> m = {std::pair{1, 2}, {3, 4}, {5, 6}};
auto n = std::erase_if(m, [](auto x) { return x.first == 1 || x.second == 6; });
VERIFY( n == 2 );
VERIFY( std::ranges::equal(m, (std::pair<int,int>[]){{3,4}}) );
}
void
test08()
{
// PR libstdc++/120432 - flat_map operator[] is broken for const lvalue keys
std::flat_map<int, int> m;
const int k = 42;
m[k] = 0;
}
void
test09()
{
// PR libstdc++/122921 - The value_type of flat_map's iterator should be
// pair<Key, T> instead of pair<const Key, T>
using type = std::flat_map<int, int>;
using value_type = std::ranges::range_value_t<type>;
using value_type = type::value_type;
using value_type = std::pair<int, int>;
}
int
main()
{
test01<std::vector, std::vector>();
test01<std::deque, std::deque>();
test01<std::vector, std::deque>();
test01<std::deque, std::vector>();
test02();
test03();
test04();
test05();
test06();
test07();
test08();
test09();
}