blob: 4aa1f1f67b73ab89b4d8688f8ecf09b0b2b01770 [file] [log] [blame]
// { dg-do compile { target c++20 } }
#include <vector>
#include <testsuite_hooks.h>
template<typename T>
struct Alloc : std::allocator<T>
{
using std::allocator<T>::allocator;
constexpr explicit Alloc(int p) : personality(p) { }
template<typename U>
constexpr Alloc(const Alloc<U>& a) : personality(a.personality) { }
int personality = 0;
constexpr bool operator==(const Alloc& a) const noexcept
{ return personality == a.personality; }
};
constexpr bool
test_push_back()
{
std::vector<int> v;
int& r = v.emplace_back(7);
VERIFY( r == 7 );
VERIFY( &r == &v.front() );
v.emplace_back(r);
v.emplace_back(v.front());
v.emplace_back(v.back());
VERIFY( v.size() == 4 );
v.emplace_back(8);
VERIFY( v.size() == 5 );
VERIFY( v.back() == 8 );
v.pop_back();
VERIFY( v.size() == 4 );
VERIFY( v.back() == 7 );
v.pop_back();
v.pop_back();
v.pop_back();
v.pop_back();
VERIFY( v.empty() );
v.push_back(99);
for (std::size_t i = 0, c = v.capacity(); i <= c; ++i)
v.push_back(v.front());
VERIFY( v.capacity() > v.size() );
std::vector<int, Alloc<int>> va;
va.push_back(99);
va.push_back(va.front());
VERIFY( va.size() == 2 );
return true;
}
static_assert( test_push_back() );
template<typename T = int>
constexpr std::false_type
pop_back_empty() { return {}; }
template<typename T = int>
requires (std::bool_constant<(std::vector<T>().pop_back(), true)>::value)
constexpr std::true_type
pop_back_empty() { return {}; }
static_assert( ! pop_back_empty() );
constexpr bool
test_insert_erase()
{
std::vector<int> v;
// vector::emplace(const_iterator, Args&&...)
auto p = v.emplace(v.begin());
VERIFY( p == v.begin() );
p = v.emplace(v.end(), 7);
VERIFY( p == --v.end() );
// vector::insert(const_iterator, const T&)
p = v.insert(v.begin(), *p);
VERIFY( p == v.begin() );
VERIFY( *p == 7 );
VERIFY( &*p == &v.front() );
// vector::insert(const_iterator, T&&)
p = v.insert(v.end(), 1);
VERIFY( p == --v.end() );
v.insert(p, v.front());
v.insert(v.end(), v.back());
VERIFY( v.size() == 6 );
v.insert(v.end(), 8);
VERIFY( v.size() == 7 );
VERIFY( v.back() == 8 );
// vector::insert(const_iterator, size_type, const T&)
v.insert(v.begin(), 2, v.front());
v.insert(v.end(), 3, 99);
VERIFY( v.size() == 12 );
struct input_iterator
{
using iterator_category = std::input_iterator_tag;
using value_type = int;
using pointer = const int*;
using reference = int;
using difference_type = int;
constexpr input_iterator() : val(0) { }
constexpr input_iterator(int i) : val(i) { }
constexpr input_iterator& operator++() { --val; return *this; }
constexpr input_iterator operator++(int) { return {val--}; }
constexpr int operator*() const { return val; }
constexpr const int* operator->() const { return &val; }
constexpr bool operator==(const input_iterator&) const = default;
int val;
};
// vector::insert(const_iterator, Iter, Iter);
v.insert(v.begin() + 2, input_iterator(), input_iterator());
VERIFY( v.size() == 12 );
v.reserve(13);
auto n = v.capacity() - v.size();
v.insert(v.end() - 9, input_iterator(n), input_iterator()); // no reallocation
VERIFY( v.size() == (12 + n) );
short a[] = { 84, 85 };
v.insert(v.end() - 1, a, a + 2); // reallocation needed
VERIFY( v.size() == (12 + n + 2) );
v.resize(32);
// vector::insert(const_iterator, initializer_list<T>)
v.insert(v.begin(), {1,2,3});
VERIFY( v.size() == 35 );
v.rbegin()[0] = 999;
v.rbegin()[1] = 888;
// vector::erase(const_iterator)
v.erase(v.end() - 1);
VERIFY( v.size() == 34 );
VERIFY( v.back() == 888 );
v.erase(v.begin());
v.erase(v.begin() + 1);
v.erase(v.end() - 1);
VERIFY( v.size() == 31 );
// vector::erase(const_iterator, const_iterator)
v.erase(v.begin(), v.begin());
v.erase(v.end(), v.end());
v.erase(v.begin(), v.begin() + 1);
VERIFY( v.size() == 30 );
v.erase(v.begin() + 2, v.end() - 2);
VERIFY( v.size() == 4 );
v.erase(v.begin(), v.end());
VERIFY( v.empty() );
v.erase( v.begin(), v.begin() );
VERIFY( v.empty() );
v.insert(v.end(), 99);
for (std::size_t i = 0, c = v.capacity(); i <= c; ++i)
v.insert(v.end() - 1, v.front());
VERIFY( v.capacity() > v.size() );
v.insert(v.end(), 999);
for (std::size_t i = 0, c = v.capacity(); i <= c; ++i)
v.insert(v.begin(), v.front());
std::vector<int, Alloc<int>> va;
va.insert(va.begin(), 99);
va.insert(va.begin(), va.front());
VERIFY( va.size() == 2 );
va.erase(va.begin());
return true;
}
static_assert( test_insert_erase() );
constexpr bool
test_clear()
{
std::vector<int> v0;
v0.clear();
VERIFY( v0.size() == 0 );
VERIFY( v0.capacity() == 0 );
std::vector<int> v{1, 10, 100};
v.clear();
VERIFY( v.size() == 0 );
VERIFY( v.capacity() == 3 );
std::vector<int, Alloc<int>> va;
va.clear();
va.push_back(1);
va.clear();
va.clear();
return true;
}
static_assert( test_clear() );
constexpr bool
test_erasure()
{
const char* names[] = { "Vince", "Clarke", "Andy", "Bell" };
std::vector<const char*> e(std::begin(names), std::end(names));
auto n = std::erase(e, names[0]);
VERIFY( n == 1 );
VERIFY( e.size() == 3 );
n = std::erase_if(e, [](auto name) { return name[4] == '\0'; });
VERIFY( n == 2 );
VERIFY( e.size() == 1 );
return true;
}
static_assert( test_erasure() );