blob: 50e45a639abd6029192edd3ed4a9857fb6bb78cd [file]
// { dg-do compile { target c++26 } }
#include <deque>
#ifndef __cpp_lib_constexpr_deque
#error "Feature test macro for constexpr deque is missing in <deque>"
#elif __cpp_lib_constexpr_deque != 202502L
# error "Feature test macro for constexpr deque has wrong value in <deque>"
#endif
#include <ranges>
#include <numeric>
#include <testsuite_hooks.h>
#include <testsuite_iterators.h>
#include <testsuite_allocator.h>
using namespace __gnu_test;
template<typename Alloc>
constexpr bool
ctor_tests()
{
Alloc alloc;
std::deque<int, Alloc> dq2(alloc);
std::deque<int, Alloc> dq3(4, alloc);
VERIFY( dq3.front() == 0 );
VERIFY( dq3.size() == 4 );
std::deque<int, Alloc> dq4(4, 5, alloc);
VERIFY( dq4.front() == 5 );
VERIFY( dq4.size() == 4 );
auto rg = {2, 3, 5, 7};
std::deque<int> dq5(rg.begin(), rg.end());
VERIFY( dq5.front() == 2 );
VERIFY( dq5.back() == 7 );
VERIFY( dq5.size() == 4 );
std::deque<int> dq6(std::from_range, rg);
VERIFY( dq6 == dq5 );
std::deque<int> dq1{1, 2, 3};
std::deque<int> dq7(dq1);
VERIFY( dq7 == dq1 );
std::deque<int>dq8(std::move(dq1));
VERIFY( dq8 == dq7 );
dq2.insert_range(dq2.begin(), rg);
std::deque<int, Alloc> dq9(dq2, alloc);
std::deque<int, Alloc> dq10(std::move(dq2), alloc);
VERIFY( dq9 == dq10 );
std::deque<int, Alloc> dq11(rg, alloc);
VERIFY( dq11 == dq10 );
return true;
}
static_assert( ctor_tests<std::allocator<int>>() );
static_assert( ctor_tests<SimpleAllocator<int>>() );
constexpr bool
insert_tests()
{
std::deque<int> dq1 {};
auto rg = {1, 2, 3, 4, 5};
dq1.insert(dq1.begin() , 1);
dq1.insert(dq1.end(), 2);
VERIFY( dq1.size() == 2 );
VERIFY( dq1.front() == 1 );
VERIFY( dq1.back() == 2 );
dq1.insert(dq1.end(), 1, 3);
dq1.insert(dq1.end(), rg.begin() + 3, rg.end());
VERIFY( dq1[0] == 1 );
VERIFY( dq1[1] == 2 );
VERIFY( dq1[2] == 3 );
VERIFY( dq1[3] == 4 );
VERIFY( dq1[4] == 5 );
dq1.clear();
dq1.insert(dq1.begin(), rg.begin(), rg.end());
VERIFY( dq1[0] == 1 );
VERIFY( dq1[1] == 2 );
VERIFY( dq1[2] == 3 );
VERIFY( dq1[3] == 4 );
VERIFY( dq1[4] == 5 );
dq1.insert_range(dq1.end(), rg);
VERIFY( dq1[5] == 1 );
VERIFY( dq1[6] == 2 );
VERIFY( dq1[7] == 3 );
VERIFY( dq1[8] == 4 );
VERIFY( dq1[9] == 5 );
std::deque<int>dq2 {2, 3, 5, 7};
dq2.erase(dq2.begin());
VERIFY( dq2.size() == 3 );
dq2.clear();
VERIFY( dq2.size() == 0);
VERIFY( dq2.empty() );
std::deque<int> dq3, dq4;
dq3.insert_range(dq3.begin(), rg);
dq4.append_range(rg);
VERIFY( dq3 == dq4 );
dq3.erase(dq3.begin(), dq3.end());
dq3.prepend_range(rg);
VERIFY( dq3 == dq4 );
struct S {
int foo;
constexpr S (int i, int j) : foo{i + j} {}
};
std::deque<S> dq5 {};
dq5.emplace(dq5.end(), 0, 1);
const S& s1 = dq5.emplace_back(1, 1);
const S& s2 = dq5.emplace_front(2, 1);
VERIFY( dq5.front().foo == 3 );
VERIFY( dq5.back().foo == 2 );
VERIFY( dq5[1].foo == 1 );
std::deque<int> dq6 {2, 3};
dq6.push_front(1);
dq6.push_back(4);
VERIFY( dq6.front() == 1);
VERIFY( dq6.back() == 4 );
dq6.pop_front();
dq6.pop_back();
std::deque<int> dq7 {1, 2};
dq7.resize(4);
VERIFY( dq7.back() == 0 );
dq7.resize(2);
VERIFY( dq7.front() == 1 );
VERIFY( dq7.back() == 2 );
dq7.clear();
dq7.resize(2);
VERIFY( dq7.front() == 0 );
VERIFY( dq7.back() == 0 );
std::deque<int> dq8 {1, 4};
dq8.swap(dq6);
VERIFY( dq6.front() == 1 );
VERIFY( dq6.back() == 4 );
VERIFY( dq8.front() == 2 );
VERIFY( dq8.back() == 3 );
return true;
}
static_assert( insert_tests() );
constexpr bool
iterators_tests()
{
std::deque<int> dq0 {};
VERIFY( dq0.begin() == dq0.end() );
dq0.resize(1);
VERIFY( dq0.begin() != dq0.end() );
dq0.resize(2);
VERIFY( dq0.begin() != dq0.end() );
VERIFY( dq0.cbegin() == dq0.begin() );
VERIFY( dq0.crbegin() == dq0.rbegin() );
VERIFY( dq0.cend() == dq0.end() );
VERIFY( dq0.crend() == dq0.rend() );
auto it = dq0.begin();
VERIFY( it[0] == 0 );
VERIFY( &*it == &dq0.front() );
VERIFY( &it[1] == &dq0[1] );
VERIFY( it++ == dq0.begin() );
VERIFY( ++it == dq0.end() );
VERIFY( (it - 2) == dq0.begin() );
VERIFY( (it - dq0.begin()) == 2 );
it -= 2;
it += 1;
VERIFY( (it + 1) == dq0.end() );
VERIFY( (1 + it) == dq0.end() );
it = it + 1;
auto it2 = dq0.begin();
std::swap(it, it2);
VERIFY( it == dq0.begin() );
VERIFY( it2 == dq0.end() );
auto rit = dq0.rbegin();
VERIFY( rit[0] == 0 );
VERIFY( &*rit == &dq0.back() );
VERIFY( &rit[1] == &dq0[0] );
VERIFY( rit++ == dq0.rbegin() );
VERIFY( ++rit == dq0.rend() );
VERIFY( (rit - 2) == dq0.rbegin() );
VERIFY( (rit - dq0.rbegin()) == 2 );
rit -= 2;
rit += 1;
VERIFY( (rit + 1) == dq0.rend() );
VERIFY( (1 + rit) == dq0.rend() );
rit = rit + 1;
auto rit2 = dq0.rbegin();
std::swap(rit, rit2);
VERIFY( rit == dq0.rbegin() );
VERIFY( rit2 == dq0.rend() );
return true;
}
static_assert( iterators_tests() );
constexpr bool
capacity_tests()
{
std::deque<int> dq0 {};
VERIFY( dq0.empty() );
VERIFY( dq0.max_size() );
dq0.push_front(0);
VERIFY( dq0.size() == 1 );
dq0.erase(dq0.begin());
dq0.shrink_to_fit();
return true;
}
static_assert( capacity_tests() );
constexpr bool
nonmember_tests()
{
std::deque<int> dq0 {0, 1};
std::deque<int> dq1 {0, 1};
VERIFY( (dq0 == dq1) == true );
VERIFY( (dq0 != dq1) == false );
VERIFY( (dq0 <= dq1) == true );
VERIFY( (dq0 >= dq1) == true );
VERIFY( (dq0 < dq1) == false );
VERIFY( (dq0 > dq1) == false );
VERIFY( (dq0 <=> dq1) == 0 );
VERIFY( (dq0 <=> dq1) <= 0 );
VERIFY( (dq0 <=> dq1) >= 0 );
std::deque<int> dq2 {2, 4};
std::swap(dq1, dq2);
VERIFY( (dq0 == dq1) == false );
VERIFY( (dq0 != dq1) == true );
VERIFY( (dq0 <= dq1) == true );
VERIFY( (dq0 >= dq1) == false );
VERIFY( (dq0 < dq1) == true );
VERIFY( (dq0 > dq1) == false );
VERIFY( (dq0 <=> dq1) != 0 );
VERIFY( (dq0 <=> dq1) <= 0 );
VERIFY( (dq0 <=> dq1) < 0 );
std::erase(dq0, 0);
VERIFY( dq0.front() == 1 );
std::erase_if(dq1, [](int x) { return x % 2 == 0; });
VERIFY( dq1.empty() );
return true;
}
static_assert( nonmember_tests() );
template<typename Range>
constexpr bool
ranges_test()
{
using Tp = std::ranges::range_value_t<Range>;
Tp a[] {0, 1, 2, 3, 4,
5, 6, 7, 8, 9};
// Constructor tests
auto dq1 = std::deque<Tp>(std::from_range, Range(a, a+5));
VERIFY( dq1[0] == 0 );
VERIFY( dq1[1] == 1 );
VERIFY( dq1[2] == 2 );
VERIFY( dq1[3] == 3 );
VERIFY( dq1[4] == 4 );
// Insert tests
std::deque<Tp> dq2;
dq2.insert_range(dq2.begin(), Range(a, a+5));
VERIFY( dq2[0] == 0 );
VERIFY( dq2[1] == 1 );
VERIFY( dq2[2] == 2 );
VERIFY( dq2[3] == 3 );
VERIFY( dq2[4] == 4 );
std::deque<Tp> dq3;
dq3.assign_range(Range(a, a+5));
VERIFY( dq2 == dq3 );
dq2.insert_range(dq2.end(), Range(a+5, a+10));
VERIFY( dq2[5] == 5 );
VERIFY( dq2[6] == 6 );
VERIFY( dq2[7] == 7 );
VERIFY( dq2[8] == 8 );
VERIFY( dq2[9] == 9 );
std::deque<Tp> dq4;
dq4.prepend_range(Range(a, a+5));
dq4.append_range(Range(a+5, a+10));
VERIFY( dq2 == dq4 );
return true;
}
static_assert( ranges_test<test_forward_range<int>>() );
static_assert( ranges_test<test_forward_sized_range<int>>() );
static_assert( ranges_test<test_sized_range_sized_sent<int, forward_iterator_wrapper>>() );
static_assert( ranges_test<test_input_range<int>>() );
static_assert( ranges_test<test_input_sized_range<int>>() );
static_assert( ranges_test<test_sized_range_sized_sent<int, input_iterator_wrapper>>() );
static_assert( ranges_test<test_range<int, input_iterator_wrapper_nocopy>>() );
static_assert( ranges_test<test_sized_range<int, input_iterator_wrapper_nocopy>>() );
static_assert( ranges_test<test_sized_range_sized_sent<int, input_iterator_wrapper_nocopy>>() );
static_assert( ranges_test<test_forward_range<short>>() );
static_assert( ranges_test<test_input_range<short>>() );
// Not lvalue-convertible to int
struct C {
constexpr C(int v) : val(v) { }
constexpr operator int() && { return val; }
friend bool operator==(C c, C b) = default;
friend constexpr bool operator==(C c, int b)
{ return b == c.val; }
int val;
};
using rvalue_input_range = test_range<C, input_iterator_wrapper_rval>;
static_assert( ranges_test<rvalue_input_range>() );