blob: ce0aca0bf0cb1e4a61161d4d5006ab003c48f4ad [file] [log] [blame]
//////////////////////////////////////////////////////////////////////////////
//
// \(C\) Copyright Benedek Thaler 2015-2016
// \(C\) Copyright Ion Gaztanaga 2019-2020. Distributed under the Boost
// Software License, Version 1.0. (See accompanying file
// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
//
// See http://www.boost.org/libs/container for documentation.
//
//////////////////////////////////////////////////////////////////////////////
#include <boost/core/lightweight_test.hpp>
#include <cstring> // memcmp
#include <iostream>
#include <algorithm>
#include <limits>
#include <boost/container/list.hpp>
#include <boost/container/vector.hpp>
#include <boost/core/no_exceptions_support.hpp>
#include <boost/type_traits/is_default_constructible.hpp>
#include <boost/type_traits/is_nothrow_move_constructible.hpp>
#include "dummy_test_allocator.hpp"
#include "propagate_allocator_test.hpp"
#include "check_equal_containers.hpp"
#include "movable_int.hpp"
#include <boost/algorithm/cxx14/equal.hpp>
#define BOOST_CONTAINER_DEVECTOR_ALLOC_STATS
#include <boost/container/devector.hpp>
#undef BOOST_CONTAINER_DEVECTOR_ALLOC_STATS
#include "test_util.hpp"
#include "test_elem.hpp"
#include "input_iterator.hpp"
using namespace boost::container;
struct boost_container_devector;
#ifdef _MSC_VER
#pragma warning (push)
#pragma warning (disable : 4127) // conditional expression is constant
#endif
namespace boost {
namespace container {
namespace test {
template<>
struct alloc_propagate_base<boost_container_devector>
{
template <class T, class Allocator>
struct apply
{
typedef devector<T, Allocator> type;
};
};
}}} //namespace boost::container::test {
struct different_growth_policy
{
template <typename SizeType>
static SizeType new_capacity(SizeType capacity)
{
return (capacity) ? capacity * 4u : 32u;
}
};
// END HELPERS
template <class Devector> void test_constructor_default()
{
Devector a;
BOOST_TEST(a.empty());
BOOST_TEST(a.get_alloc_count() == 0u);
BOOST_TEST(a.capacity() == 0u);
}
template <class Devector> void test_constructor_allocator()
{
typename Devector::allocator_type alloc_template;
Devector a(alloc_template);
BOOST_TEST(a.empty());
BOOST_TEST(a.get_alloc_count() == 0u);
BOOST_TEST(a.capacity() == 0u);
}
template <class Devector> void test_constructor_reserve_only()
{
{
Devector a(16, reserve_only_tag_t());
BOOST_TEST(a.size() == 0u);
BOOST_TEST(a.capacity() >= 16u);
}
{
Devector b(0, reserve_only_tag_t());
BOOST_TEST(b.get_alloc_count() == 0u);
}
}
template <class Devector> void test_constructor_reserve_only_front_back()
{
{
Devector a(8, 8, reserve_only_tag_t());
BOOST_TEST(a.size() == 0u);
BOOST_TEST(a.capacity() >= 16u);
for (int i = 8; i; --i)
{
a.emplace_front(i);
}
for (int i = 9; i < 17; ++i)
{
a.emplace_back(i);
}
const int expected [] = {1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16};
test_equal_range(a, expected);
BOOST_TEST(a.get_alloc_count() <= 1u);
}
{
Devector b(0, 0, reserve_only_tag_t());
BOOST_TEST(b.get_alloc_count() == 0u);
}
}
template <class Devector> void test_constructor_n()
{
{
Devector a(8);
const int expected [] = {0, 0, 0, 0, 0, 0, 0, 0};
test_equal_range(a, expected);
}
{
Devector b(0);
test_equal_range(b);
BOOST_TEST(b.get_alloc_count() == 0u);
}
#ifndef BOOST_NO_EXCEPTIONS
typedef typename Devector::value_type T;
BOOST_IF_CONSTEXPR (! boost::move_detail::is_nothrow_default_constructible<T>::value)
{
test_elem_throw::on_ctor_after(4);
BOOST_TEST_THROWS(Devector(8), test_exception);
BOOST_TEST(test_elem_base::no_living_elem());
test_elem_throw::do_not_throw();
}
#endif //#ifndef BOOST_NO_EXCEPTIONS
}
template <class Devector> void test_constructor_n_copy_throwing(dtl::true_)
{
#ifndef BOOST_NO_EXCEPTIONS
typedef typename Devector::value_type T;
test_elem_throw::on_copy_after(4);
const T x(404);
BOOST_TEST_THROWS(Devector(8, x), test_exception);
test_elem_throw::do_not_throw();
#endif //#ifndef BOOST_NO_EXCEPTIONS
}
template <class Devector> void test_constructor_n_copy_throwing(dtl::false_)
{}
template <class Devector> void test_constructor_n_copy()
{
typedef typename Devector::value_type T;
{
const T x(9);
Devector a(8, x);
const int expected [] = {9, 9, 9, 9, 9, 9, 9, 9};
test_equal_range(a, expected);
}
{
const T x(9);
Devector b(0, x);
test_equal_range(b);
BOOST_TEST(b.get_alloc_count() == 0u);
}
test_constructor_n_copy_throwing<Devector>
(dtl::bool_<! boost::move_detail::is_nothrow_copy_constructible<T>::value>());
BOOST_TEST(test_elem_base::no_living_elem());
}
template <class Devector> void test_constructor_input_range()
{
typedef typename Devector::value_type T;
{
devector<T> expected; get_range<devector<T> >(16, expected);
devector<T> input = expected;
input_iterator<Devector> input_begin = make_input_iterator(input, input.begin());
input_iterator<Devector> input_end = make_input_iterator(input, input.end());
Devector a(input_begin, input_end);
BOOST_TEST(a == expected);
}
{ // empty range
devector<T> input;
input_iterator<Devector> input_begin = make_input_iterator(input, input.begin());
Devector b(input_begin, input_begin);
test_equal_range(b);
BOOST_TEST(b.get_alloc_count() == 0u);
}
BOOST_TEST(test_elem_base::no_living_elem());
/* //if move_if_noexcept is implemented
#ifndef BOOST_NO_EXCEPTIONS
if (! boost::move_detail::is_nothrow_copy_constructible<T>::value)
{
devector<T> input; get_range<devector<T> >(16, input);
input_iterator<Devector> input_begin = make_input_iterator(input, input.begin());
input_iterator<Devector> input_end = make_input_iterator(input, input.end());
test_elem_throw::on_copy_after(4);
BOOST_TEST_THROWS(Devector c(input_begin, input_end), test_exception);
}
BOOST_TEST(test_elem_base::no_living_elem());
#endif //#ifndef BOOST_NO_EXCEPTIONS
*/
}
void test_constructor_forward_range_throwing(dtl::true_)
{}
void test_constructor_forward_range_throwing(dtl::false_)
{}
template <class Devector> void test_constructor_forward_range()
{
typedef typename Devector::value_type T;
boost::container::list<T> ncx;
ncx.emplace_back(1);
ncx.emplace_back(2);
ncx.emplace_back(3);
ncx.emplace_back(4);
ncx.emplace_back(5);
ncx.emplace_back(6);
ncx.emplace_back(7);
ncx.emplace_back(8);
const boost::container::list<T> &x = ncx;
{
Devector a(x.begin(), x.end());
const int expected[] = {1, 2, 3, 4, 5, 6, 7, 8};
test_equal_range(a, expected);
BOOST_TEST(a.get_alloc_count() <= 1u);
a.reset_alloc_stats();
}
{
Devector b(x.begin(), x.begin());
test_equal_range(b);
BOOST_TEST(b.get_alloc_count() == 0u);
}
#ifndef BOOST_NO_EXCEPTIONS
BOOST_IF_CONSTEXPR (! boost::move_detail::is_nothrow_copy_constructible<T>::value)
{
test_elem_throw::on_copy_after(4);
BOOST_TEST_THROWS(Devector c(x.begin(), x.end()), test_exception);
test_elem_throw::do_not_throw();
}
#endif //#ifndef BOOST_NO_EXCEPTIONS
}
template <class Devector> void test_constructor_pointer_range()
{
typedef typename Devector::value_type T;
boost::container::vector<T> x; get_range<boost::container::vector<T> >(8, x);
const T* xbeg = x.data();
const T* xend = x.data() + x.size();
{
Devector a(xbeg, xend);
const int expected[] = {1, 2, 3, 4, 5, 6, 7, 8};
test_equal_range(a, expected);
BOOST_TEST(a.get_alloc_count() <= 1u);
}
{
Devector b(xbeg, xbeg);
test_equal_range(b);
BOOST_TEST(b.get_alloc_count() == 0u);
}
#ifndef BOOST_NO_EXCEPTIONS
if (! boost::move_detail::is_nothrow_copy_constructible<T>::value)
{
test_elem_throw::on_copy_after(4);
BOOST_TEST_THROWS(Devector c(xbeg, xend), test_exception);
test_elem_throw::do_not_throw();
}
#endif //#ifndef BOOST_NO_EXCEPTIONS
}
template <class Devector> void test_copy_constructor()
{
{
Devector a;
Devector b(a);
test_equal_range(b);
BOOST_TEST(b.get_alloc_count() == 0u);
}
{
Devector a; get_range<Devector>(8, a);
Devector b(a);
const int expected [] = {1, 2, 3, 4, 5, 6, 7, 8};
test_equal_range(b, expected);
BOOST_TEST(b.get_alloc_count() <= 1u);
}
#ifndef BOOST_NO_EXCEPTIONS
typedef typename Devector::value_type T;
if (! boost::move_detail::is_nothrow_copy_constructible<T>::value)
{
Devector a; get_range<Devector>(8, a);
test_elem_throw::on_copy_after(4);
BOOST_TEST_THROWS(Devector b(a), test_exception);
test_elem_throw::do_not_throw();
}
#endif //#ifndef BOOST_NO_EXCEPTIONS
}
template <class Devector> void test_move_constructor()
{
{ // empty
Devector a;
Devector b(boost::move(a));
BOOST_TEST(a.empty());
BOOST_TEST(b.empty());
}
{ // maybe small
Devector a; get_range<Devector>(1, 5, 5, 9, a);
Devector b(boost::move(a));
const int expected [] = {1, 2, 3, 4, 5, 6, 7, 8};
test_equal_range(b, expected);
// a is unspecified but valid state
a.clear();
BOOST_TEST(a.empty());
}
{ // big
Devector a; get_range<Devector>(32, a);
Devector b(boost::move(a));
boost::container::vector<int> expected; get_range<boost::container::vector<int> >(32, expected);
test_equal_range(b, expected);
// a is unspecified but valid state
a.clear();
BOOST_TEST(a.empty());
}
}
template <class Devector> void test_destructor()
{
Devector a;
Devector b; get_range<Devector>(3, b);
}
template <class Devector> void test_assignment()
{
const typename Devector::size_type alloc_count =
boost::container::allocator_traits
< typename Devector::allocator_type >::propagate_on_container_copy_assignment::value;
{ // assign to empty (maybe small)
Devector a;
Devector c; get_range<Devector>(6, c);
Devector &b = c;
a = b;
const int expected[] = {1, 2, 3, 4, 5, 6};
test_equal_range(a, expected);
}
{ // assign from empty
Devector a; get_range<Devector>(6, a);
const Devector b;
a = b;
test_equal_range(a);
}
{ // assign to non-empty
Devector a; get_range<Devector>(11, 15, 15, 19, a);
Devector c; get_range<Devector>(6, c);
const Devector &b = c;
a = b;
const int expected[] = {1, 2, 3, 4, 5, 6};
test_equal_range(a, expected);
}
{ // assign to free front
Devector a; get_range<Devector>(11, 15, 15, 19, a);
a.reserve_front(8);
a.reset_alloc_stats();
Devector c; get_range<Devector>(6, c);
const Devector &b = c;
a = b;
const int expected [] = {1, 2, 3, 4, 5, 6};
test_equal_range(a, expected);
BOOST_TEST(a.get_alloc_count() == alloc_count);
}
{ // assignment overlaps contents
Devector a; get_range<Devector>(11, 15, 15, 19, a);
a.reserve_front(12);
a.reset_alloc_stats();
Devector c; get_range<Devector>(6, c);
const Devector &b = c;
a = b;
const int expected [] = {1, 2, 3, 4, 5, 6};
test_equal_range(a, expected);
BOOST_TEST(a.get_alloc_count() == alloc_count);
}
{ // assignment exceeds contents
Devector a; get_range<Devector>(11, 13, 13, 15, a);
a.reserve_front(8);
a.reserve_back(8);
a.reset_alloc_stats();
Devector c; get_range<Devector>(12, c);
const Devector &b = c;
a = b;
const int expected[] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12};
test_equal_range(a, expected);
BOOST_TEST(a.get_alloc_count() == alloc_count);
}
#ifndef BOOST_NO_EXCEPTIONS
typedef typename Devector::value_type T;
BOOST_IF_CONSTEXPR (! boost::move_detail::is_nothrow_copy_constructible<T>::value)
{
// strong guarantee if reallocation is needed (no guarantee otherwise)
Devector a; get_range<Devector>(6, a);
Devector c; get_range<Devector>(12, c);
const Devector &b = c;
test_elem_throw::on_copy_after(3);
BOOST_TEST_THROWS(a = b, test_exception);
test_elem_throw::do_not_throw();
const int expected[] = {1, 2, 3, 4, 5, 6};
test_equal_range(a, expected);
}
#endif //#ifndef BOOST_NO_EXCEPTIONS
}
template <class Devector> void test_move_assignment_throwing(dtl::true_)
// move should be used on the slow path
{
Devector a; get_range<Devector>(11, 15, 15, 19, a);
Devector b; get_range<Devector>(6, b);
test_elem_throw::on_copy_after(3);
a = boost::move(b);
test_elem_throw::do_not_throw();
const int expected [] = {1, 2, 3, 4, 5, 6};
test_equal_range(a, expected);
b.clear();
test_equal_range(b);
}
template <class Devector> void test_move_assignment_throwing(dtl::false_)
{}
template <class Devector> void test_move_assignment()
{
{ // assign to empty (maybe small)
Devector a;
Devector b; get_range<Devector>(6, b);
a = boost::move(b);
const int expected [] = {1, 2, 3, 4, 5, 6};
test_equal_range(a, expected);
// b is in unspecified but valid state
b.clear();
test_equal_range(b);
}
{ // assign from empty
Devector a; get_range<Devector>(6, a);
Devector b;
a = boost::move(b);
test_equal_range(a);
test_equal_range(b);
}
{ // assign to non-empty
Devector a; get_range<Devector>(11, 15, 15, 19, a);
Devector b; get_range<Devector>(6, b);
a = boost::move(b);
const int expected [] = {1, 2, 3, 4, 5, 6};
test_equal_range(a, expected);
b.clear();
test_equal_range(b);
}
typedef typename Devector::value_type T;
test_move_assignment_throwing<Devector>
(boost::move_detail::bool_<! boost::move_detail::is_nothrow_copy_constructible<T>::value>());
}
template <class Devector> void test_il_assignment()
{
#if !defined(BOOST_NO_CXX11_HDR_INITIALIZER_LIST)
{ // assign to empty (maybe small)
Devector a;
a = {1, 2, 3, 4, 5, 6 };
test_equal_range(a, {1, 2, 3, 4, 5, 6});
}
{ // assign from empty
Devector a; get_range<Devector>(6, a);
a = {};
test_equal_range(a);
}
{ // assign to non-empty
Devector a; get_range<Devector>(11, 15, 15, 19, a);
a = {1, 2, 3, 4, 5, 6};
test_equal_range(a, {1, 2, 3, 4, 5, 6});
}
{ // assign to free front
Devector a; get_range<Devector>(11, 15, 15, 19, a);
a.reserve_front(8);
a.reset_alloc_stats();
a = {1, 2, 3, 4, 5, 6};
test_equal_range(a, {1, 2, 3, 4, 5, 6});
BOOST_TEST(a.get_alloc_count() == 0u);
}
{ // assignment overlaps contents
Devector a; get_range<Devector>(11, 15, 15, 19, a);
a.reserve_front(12);
a.reset_alloc_stats();
a = {1, 2, 3, 4, 5, 6};
test_equal_range(a, {1, 2, 3, 4, 5, 6});
BOOST_TEST(a.get_alloc_count() == 0u);
}
{ // assignment exceeds contents
Devector a; get_range<Devector>(11, 13, 13, 15, a);
a.reserve_front(8);
a.reserve_back(8);
a.reset_alloc_stats();
a = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12};
test_equal_range(a, {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12});
BOOST_TEST(a.get_alloc_count() == 0u);
}
#ifndef BOOST_NO_EXCEPTIONS
typedef typename Devector::value_type T;
if (! boost::move_detail::is_nothrow_copy_constructible<T>::value)
{
// strong guarantee if reallocation is needed (no guarantee otherwise)
Devector a; get_range<Devector>(6, a);
test_elem_throw::on_copy_after(3);
BOOST_TRY
{
a = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12};
BOOST_TEST(false);
}
BOOST_CATCH(const test_exception&) {}
BOOST_CATCH_END
test_elem_throw::do_not_throw();
test_equal_range(a, {1, 2, 3, 4, 5, 6});
}
#endif //BOOST_NO_EXCEPTIONS
#endif //#if !defined(BOOST_NO_CXX11_HDR_INITIALIZER_LIST)
}
template <class Devector> void test_assign_input_range()
{
typedef typename Devector::value_type T;
{ // assign to empty, keep it small
devector<T> expected; get_range<Devector>(1, 13, 13, 25, expected);
devector<T> input = expected;
input_iterator<Devector> input_begin = make_input_iterator(input, input.begin());
input_iterator<Devector> input_end = make_input_iterator(input, input.end());
Devector a;
a.reset_alloc_stats();
a.assign(input_begin, input_end);
BOOST_TEST(a == expected);
}
{ // assign to empty (maybe small)
devector<T> input; get_range<devector<T> >(6, input);
input_iterator<Devector> input_begin = make_input_iterator(input, input.begin());
input_iterator<Devector> input_end = make_input_iterator(input, input.end());
Devector a;
a.assign(input_begin, input_end);
const int expected [] = {1, 2, 3, 4, 5, 6};
test_equal_range(a, expected);
}
{ // assign from empty
devector<T> input; get_range<devector<T> >(6, input);
input_iterator<Devector> input_begin = make_input_iterator(input, input.begin());
Devector a; get_range<Devector>(6, a);
a.assign(input_begin, input_begin);
test_equal_range(a);
}
{ // assign to non-empty
devector<T> input; get_range<devector<T> >(6, input);
input_iterator<Devector> input_begin = make_input_iterator(input, input.begin());
input_iterator<Devector> input_end = make_input_iterator(input, input.end());
Devector a; get_range<Devector>(11, 15, 15, 19, a);
a.assign(input_begin, input_end);
const int expected [] = {1, 2, 3, 4, 5, 6};
test_equal_range(a, expected);
}
{ // assign to free front
devector<T> input; get_range<devector<T> >(6, input);
input_iterator<Devector> input_begin = make_input_iterator(input, input.begin());
input_iterator<Devector> input_end = make_input_iterator(input, input.end());
Devector a; get_range<Devector>(11, 15, 15, 19, a);
a.reserve_front(8);
a.reset_alloc_stats();
a.assign(input_begin, input_end);
const int expected[] = {1, 2, 3, 4, 5, 6};
test_equal_range(a, expected);
}
{ // assignment overlaps contents
devector<T> input; get_range<devector<T> >(6, input);
input_iterator<Devector> input_begin = make_input_iterator(input, input.begin());
input_iterator<Devector> input_end = make_input_iterator(input, input.end());
Devector a; get_range<Devector>(11, 15, 15, 19, a);
a.reserve_front(12);
a.reset_alloc_stats();
a.assign(input_begin, input_end);
const int expected[] = {1, 2, 3, 4, 5, 6};
test_equal_range(a, expected);
}
{ // assignment exceeds contents
devector<T> input; get_range<devector<T> >(12, input);
input_iterator<Devector> input_begin = make_input_iterator(input, input.begin());
input_iterator<Devector> input_end = make_input_iterator(input, input.end());
Devector a; get_range<Devector>(11, 13, 13, 15, a);
a.reserve_front(8);
a.reserve_back(8);
a.reset_alloc_stats();
a.assign(input_begin, input_end);
const int expected[] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12};
test_equal_range(a, expected);
}
#ifndef BOOST_NO_EXCEPTIONS
if (! boost::move_detail::is_nothrow_copy_constructible<T>::value)
{
// strong guarantee if reallocation is needed (no guarantee otherwise)
devector<T> input; get_range<devector<T> >(12, input);
input_iterator<Devector> input_begin = make_input_iterator(input, input.begin());
input_iterator<Devector> input_end = make_input_iterator(input, input.end());
Devector a; get_range<Devector>(6, a);
test_elem_throw::on_copy_after(3);
BOOST_TEST_THROWS(a.assign(input_begin, input_end), test_exception);
test_elem_throw::do_not_throw();
const int expected[] = {1, 2, 3, 4, 5, 6};
test_equal_range(a, expected);
}
#endif //#ifndef BOOST_NO_EXCEPTIONS
}
template <class Devector> void test_assign_forward_range_throwing(dtl::false_)
{}
template <class Devector> void test_assign_forward_range()
{
typedef typename Devector::value_type T;
typedef boost::container::list<T> List;
boost::container::list<T> x;
typedef typename List::iterator list_iterator;
x.emplace_back(1);
x.emplace_back(2);
x.emplace_back(3);
x.emplace_back(4);
x.emplace_back(5);
x.emplace_back(6);
x.emplace_back(7);
x.emplace_back(8);
x.emplace_back(9);
x.emplace_back(10);
x.emplace_back(11);
x.emplace_back(12);
list_iterator one = x.begin();
list_iterator six = one;
list_iterator twelve = one;
iterator_advance(six, 6);
iterator_advance(twelve, 12);
{ // assign to empty (maybe small)
Devector a;
a.assign(one, six);
const int expected [] = {1, 2, 3, 4, 5, 6};
test_equal_range(a, expected);
}
{ // assign from empty
Devector a; get_range<Devector>(6, a);
a.assign(one, one);
test_equal_range(a);
}
{ // assign to non-empty
Devector a; get_range<Devector>(11, 15, 15, 19, a);
a.assign(one, six);
const int expected [] = {1, 2, 3, 4, 5, 6};
test_equal_range(a, expected);
}
{ // assign to free front
Devector a; get_range<Devector>(11, 15, 15, 19, a);
a.reserve_front(8);
a.reset_alloc_stats();
a.assign(one, six);
const int expected [] = {1, 2, 3, 4, 5, 6};
test_equal_range(a, expected);
BOOST_TEST(a.get_alloc_count() == 0u);
}
{ // assignment overlaps contents
Devector a; get_range<Devector>(11, 15, 15, 19, a);
a.reserve_front(12);
a.reset_alloc_stats();
a.assign(one, six);
const int expected [] = {1, 2, 3, 4, 5, 6};
test_equal_range(a, expected);
BOOST_TEST(a.get_alloc_count() == 0u);
}
{ // assignment exceeds contents
Devector a; get_range<Devector>(11, 13, 13, 15, a);
a.reserve_front(8);
a.reserve_back(8);
a.reset_alloc_stats();
a.assign(one, twelve);
const int expected [] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12};
test_equal_range(a, expected);
BOOST_TEST(a.get_alloc_count() == 0u);
}
#ifndef BOOST_NO_EXCEPTIONS
BOOST_IF_CONSTEXPR(! boost::move_detail::is_nothrow_copy_constructible<T>::value)
{
// strong guarantee if reallocation is needed (no guarantee otherwise)
Devector a; get_range<Devector>(6, a);
test_elem_throw::on_copy_after(3);
BOOST_TEST_THROWS(a.assign(one, twelve), test_exception);
test_elem_throw::do_not_throw();
const int expected [] = {1, 2, 3, 4, 5, 6};
test_equal_range(a, expected);
}
#endif //#ifndef BOOST_NO_EXCEPTIONS
}
template <class Devector> void test_assign_pointer_range()
{
typedef typename Devector::value_type T;
boost::container::vector<T> x; get_range<boost::container::vector<T> >(12, x);
const T* one = x.data();
const T* six = one + 6;
const T* twelve = one + 12;
{ // assign to empty (maybe small)
Devector a;
a.assign(one, six);
const int expected[] = {1, 2, 3, 4, 5, 6};
test_equal_range(a, expected);
}
{ // assign from empty
Devector a; get_range<Devector>(6, a);
a.assign(one, one);
test_equal_range(a);
}
{ // assign to non-empty
Devector a; get_range<Devector>(11, 15, 15, 19, a);
a.assign(one, six);
const int expected[] = {1, 2, 3, 4, 5, 6};
test_equal_range(a, expected);
}
{ // assign to free front
Devector a; get_range<Devector>(11, 15, 15, 19, a);
a.reserve_front(8);
a.reset_alloc_stats();
a.assign(one, six);
const int expected[] = {1, 2, 3, 4, 5, 6};
test_equal_range(a, expected);
BOOST_TEST(a.get_alloc_count() == 0u);
}
{ // assignment overlaps contents
Devector a; get_range<Devector>(11, 15, 15, 19, a);
a.reserve_front(12);
a.reset_alloc_stats();
a.assign(one, six);
const int expected[] = {1, 2, 3, 4, 5, 6};
test_equal_range(a, expected);
BOOST_TEST(a.get_alloc_count() == 0u);
}
{ // assignment exceeds contents
Devector a; get_range<Devector>(11, 13, 13, 15, a);
a.reserve_front(8);
a.reserve_back(8);
a.reset_alloc_stats();
a.assign(one, twelve);
const int expected[] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12};
test_equal_range(a, expected);
BOOST_TEST(a.get_alloc_count() == 0u);
}
#ifndef BOOST_NO_EXCEPTIONS
if (! boost::move_detail::is_nothrow_copy_constructible<T>::value)
{
// strong guarantee if reallocation is needed (no guarantee otherwise)
Devector a; get_range<Devector>(6, a);
test_elem_throw::on_copy_after(3);
BOOST_TEST_THROWS(a.assign(one, twelve), test_exception);
test_elem_throw::do_not_throw();
const int expected[] = {1, 2, 3, 4, 5, 6};
test_equal_range(a, expected);
}
#endif //#ifndef BOOST_NO_EXCEPTIONS
}
template <class Devector> void test_assign_n()
{
typedef typename Devector::value_type T;
{ // assign to empty (maybe small)
Devector a;
a.assign(6, T(9));
const int expected[] = {9, 9, 9, 9, 9, 9};
test_equal_range(a, expected);
}
{ // assign from empty
Devector a; get_range<Devector>(6, a);
a.assign(0, T(404));
test_equal_range(a);
}
{ // assign to non-empty
Devector a; get_range<Devector>(11, 15, 15, 19, a);
a.assign(6, T(9));
const int expected[] = {9, 9, 9, 9, 9, 9};
test_equal_range(a, expected);
}
{ // assign to free front
Devector a; get_range<Devector>(11, 15, 15, 19, a);
a.reserve_front(8);
a.reset_alloc_stats();
a.assign(6, T(9));
const int expected[] = {9, 9, 9, 9, 9, 9};
test_equal_range(a, expected);
BOOST_TEST(a.get_alloc_count() == 0u);
}
{ // assignment overlaps contents
Devector a; get_range<Devector>(11, 15, 15, 19, a);
a.reserve_front(12);
a.reset_alloc_stats();
a.assign(6, T(9));
const int expected[] = {9, 9, 9, 9, 9, 9};
test_equal_range(a, expected);
BOOST_TEST(a.get_alloc_count() == 0u);
}
{ // assignment exceeds contents
Devector a; get_range<Devector>(11, 13, 13, 15, a);
a.reserve_front(8);
a.reserve_back(8);
a.reset_alloc_stats();
a.assign(12, T(9));
const int expected[] = {9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9};
test_equal_range(a, expected);
BOOST_TEST(a.get_alloc_count() == 0u);
}
#ifndef BOOST_NO_EXCEPTIONS
if (! boost::move_detail::is_nothrow_copy_constructible<T>::value)
{
// strong guarantee if reallocation is needed (no guarantee otherwise)
Devector a; get_range<Devector>(6, a);
test_elem_throw::on_copy_after(3);
BOOST_TEST_THROWS(a.assign(32, T(9)), test_exception);
test_elem_throw::do_not_throw();
const int expected[] = {1, 2, 3, 4, 5, 6};
test_equal_range(a, expected);
}
#endif //#ifndef BOOST_NO_EXCEPTIONS
}
template <class Devector> void test_assign_il()
{
#if !defined(BOOST_NO_CXX11_HDR_INITIALIZER_LIST)
{ // assign to empty (maybe small)
Devector a;
a.assign({1, 2, 3, 4, 5, 6});
test_equal_range(a, {1, 2, 3, 4, 5, 6});
}
{ // assign from empty
Devector a; get_range<Devector>(6, a);
a.assign({});
test_equal_range(a);
}
{ // assign to non-empty
Devector a; get_range<Devector>(11, 15, 15, 19, a);
a.assign({1, 2, 3, 4, 5, 6});
test_equal_range(a, {1, 2, 3, 4, 5, 6});
}
{ // assign to free front
Devector a; get_range<Devector>(11, 15, 15, 19, a);
a.reserve_front(8);
a.reset_alloc_stats();
a.assign({1, 2, 3, 4, 5, 6});
test_equal_range(a, {1, 2, 3, 4, 5, 6});
BOOST_TEST(a.get_alloc_count() == 0u);
}
{ // assignment overlaps contents
Devector a; get_range<Devector>(11, 15, 15, 19, a);
a.reserve_front(12);
a.reset_alloc_stats();
a.assign({1, 2, 3, 4, 5, 6});
test_equal_range(a, {1, 2, 3, 4, 5, 6});
BOOST_TEST(a.get_alloc_count() == 0u);
}
{ // assignment exceeds contents
Devector a; get_range<Devector>(11, 13, 13, 15, a);
a.reserve_front(8);
a.reserve_back(8);
a.reset_alloc_stats();
a.assign({1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12});
test_equal_range(a, {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12});
BOOST_TEST(a.get_alloc_count() == 0u);
}
#ifndef BOOST_NO_EXCEPTIONS
typedef typename Devector::value_type T;
if (! boost::move_detail::is_nothrow_copy_constructible<T>::value)
{
// strong guarantee if reallocation is needed (no guarantee otherwise)
Devector a; get_range<Devector>(6, a);
test_elem_throw::on_copy_after(3);
BOOST_TEST_THROWS(a.assign({1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18}), test_exception);
test_elem_throw::do_not_throw();
test_equal_range(a, {1, 2, 3, 4, 5, 6});
}
#endif //#ifndef BOOST_NO_EXCEPTIONS
#endif //#if !defined(BOOST_NO_CXX11_HDR_INITIALIZER_LIST)
}
template <class Devector> void test_get_allocator()
{
Devector a;
(void) a.get_allocator();
}
template <class Devector> void test_begin_end()
{
boost::container::vector<int> expected; get_range<boost::container::vector<int> >(10, expected);
{
Devector actual; get_range<Devector>(10, actual);
BOOST_TEST(boost::algorithm::equal(expected.begin(), expected.end(), actual.begin(), actual.end()));
BOOST_TEST(boost::algorithm::equal(expected.rbegin(), expected.rend(), actual.rbegin(), actual.rend()));
BOOST_TEST(boost::algorithm::equal(expected.cbegin(), expected.cend(), actual.cbegin(), actual.cend()));
BOOST_TEST(boost::algorithm::equal(expected.crbegin(), expected.crend(), actual.crbegin(), actual.crend()));
}
{
Devector cactual; get_range<Devector>(10, cactual);
BOOST_TEST(boost::algorithm::equal(expected.begin(), expected.end(), cactual.begin(), cactual.end()));
BOOST_TEST(boost::algorithm::equal(expected.rbegin(), expected.rend(), cactual.rbegin(), cactual.rend()));
}
}
template <class Devector> void test_empty()
{
typedef typename Devector::value_type T;
Devector a;
BOOST_TEST(a.empty());
a.push_front(T(1));
BOOST_TEST(! a.empty());
a.pop_back();
BOOST_TEST(a.empty());
Devector b(16, reserve_only_tag_t());
BOOST_TEST(b.empty());
Devector c; get_range<Devector>(3, c);
BOOST_TEST(! c.empty());
}
//template <typename ST>
//using gp_devector = devector<unsigned, different_growth_policy>;
void test_max_size()
{/*
gp_devector<unsigned char> a;
BOOST_TEST(a.max_size() == (std::numeric_limits<unsigned char>::max)());
gp_devector<unsigned short> b;
BOOST_TEST(b.max_size() == (std::numeric_limits<unsigned short>::max)());
gp_devector<unsigned int> c;
BOOST_TEST(c.max_size() >= b.max_size());
gp_devector<std::size_t> d;
BOOST_TEST(d.max_size() >= c.max_size());
*/
}
void test_exceeding_max_size()
{/*
#ifndef BOOST_NO_EXCEPTIONS
using Devector = gp_devector<unsigned char>;
Devector a((std::numeric_limits<typename Devector::size_type>::max)());
BOOST_TEST_THROWS(a.emplace_back(404), std::length_error);
#endif //#ifndef BOOST_NO_EXCEPTIONS
*/
}
template <class Devector> void test_size()
{
typedef typename Devector::value_type T;
Devector a;
BOOST_TEST(a.size() == 0u);
a.push_front(T(1));
BOOST_TEST(a.size() == 1u);
a.pop_back();
BOOST_TEST(a.size() == 0u);
Devector b(16, reserve_only_tag_t());
BOOST_TEST(b.size() == 0u);
Devector c; get_range<Devector>(3, c);
BOOST_TEST(c.size() == 3u);
}
template <class Devector> void test_capacity()
{
Devector a;
BOOST_TEST(a.capacity() == 0u);
Devector b(128, reserve_only_tag_t());
BOOST_TEST(b.capacity() >= 128u);
Devector c; get_range<Devector>(10, c);
BOOST_TEST(c.capacity() >= 10u);
}
template <class Devector> void test_resize_front_throwing(dtl::true_)
{
#ifndef BOOST_NO_EXCEPTIONS
typedef typename Devector::iterator iterator;
Devector d; get_range<Devector>(5, d);
boost::container::vector<int> d_origi; get_range<boost::container::vector<int> >(5, d_origi);
iterator origi_begin = d.begin();
test_elem_throw::on_ctor_after(3);
BOOST_TEST_THROWS(d.resize_front(256), test_exception);
test_elem_throw::do_not_throw();
test_equal_range(d, d_origi);
BOOST_TEST(origi_begin == d.begin());
#endif //#ifndef BOOST_NO_EXCEPTIONS
}
template <class Devector> void test_resize_front_throwing(dtl::false_)
{}
template <class Devector> void test_resize_front()
{
typedef typename Devector::value_type T;
// size < required, alloc needed
{
Devector a; get_range<Devector>(5, a);
a.resize_front(8);
const int expected [] = {0, 0, 0, 1, 2, 3, 4, 5};
test_equal_range(a, expected);
}
// size < required, but capacity provided
{
Devector b; get_range<Devector>(5, b);
b.reserve_front(16);
b.resize_front(8);
const int expected [] = {0, 0, 0, 1, 2, 3, 4, 5};
test_equal_range(b, expected);
}
/*
// size < required, move would throw
if (! boost::is_nothrow_move_constructible<T>::value && std::is_copy_constructible<T>::value)
{
Devector c; get_range<Devector>(5, c);
test_elem_throw::on_move_after(3);
c.resize_front(8); // shouldn't use the throwing move
test_elem_throw::do_not_throw();
test_equal_range(c, {0, 0, 0, 1, 2, 3, 4, 5});
}
*/
test_resize_front_throwing<Devector>
(dtl::bool_<! boost::move_detail::is_nothrow_default_constructible<T>::value>());
// size >= required
{
Devector e; get_range<Devector>(6, e);
e.resize_front(4);
const int expected [] = {3, 4, 5, 6};
test_equal_range(e, expected);
}
// size < required, does not fit front small buffer
{
boost::container::vector<int> expected(128);
Devector g;
g.resize_front(128);
test_equal_range(g, expected);
}
// size = required
{
Devector e; get_range<Devector>(6, e);
e.resize_front(6);
const int expected [] = {1, 2, 3, 4, 5, 6};
test_equal_range(e, expected);
}
}
template <class Devector> void test_resize_front_copy_throwing(dtl::true_)
{
#ifndef BOOST_NO_EXCEPTIONS
typedef typename Devector::value_type T;
typedef typename Devector::iterator iterator;
// size < required, copy throws
{
Devector c; get_range<Devector>(5, c);
boost::container::vector<int> c_origi; get_range<boost::container::vector<int> >(5, c_origi);
test_elem_throw::on_copy_after(3);
BOOST_TEST_THROWS(c.resize_front(256, T(404)), test_exception);
test_elem_throw::do_not_throw();
test_equal_range(c, c_origi);
}
// size < required, copy throws, but later
{
Devector c; get_range<Devector>(5, c);
boost::container::vector<int> c_origi; get_range<boost::container::vector<int> >(5, c_origi);
iterator origi_begin = c.begin();
test_elem_throw::on_copy_after(7);
BOOST_TEST_THROWS(c.resize_front(256, T(404)), test_exception);
test_elem_throw::do_not_throw();
test_equal_range(c, c_origi);
BOOST_TEST(origi_begin == c.begin());
}
#endif //#ifndef BOOST_NO_EXCEPTIONS
}
template <class Devector> void test_resize_front_copy_throwing(dtl::false_)
{}
template <class Devector> void test_resize_front_copy()
{
typedef typename Devector::value_type T;
// size < required, alloc needed
{
Devector a; get_range<Devector>(5, a);
a.resize_front(8, T(9));
const int expected [] = {9, 9, 9, 1, 2, 3, 4, 5};
test_equal_range(a, expected);
}
// size < required, but capacity provided
{
Devector b; get_range<Devector>(5, b);
b.reserve_front(16);
b.resize_front(8, T(9));
const int expected [] = {9, 9, 9, 1, 2, 3, 4, 5};
test_equal_range(b, expected);
}
test_resize_front_copy_throwing<Devector>
(dtl::bool_<! boost::move_detail::is_nothrow_copy_constructible<T>::value>());
// size >= required
{
Devector e; get_range<Devector>(6, e);
e.resize_front(4, T(404));
const int expected[] = {3, 4, 5, 6};
test_equal_range(e, expected);
}
// size < required, does not fit front small buffer
{
boost::container::vector<int> expected(128, 9);
Devector g;
g.resize_front(128, T(9));
test_equal_range(g, expected);
}
// size = required
{
Devector e; get_range<Devector>(6, e);
e.resize_front(6, T(9));
const int expected[] = {1, 2, 3, 4, 5, 6};
test_equal_range(e, expected);
}
// size < required, tmp is already inserted
{
Devector f; get_range<Devector>(8, f);
const T& tmp = *(f.begin() + 1);
f.resize_front(16, tmp);
const int expected[] = {2,2,2,2,2,2,2,2,1,2,3,4,5,6,7,8};
test_equal_range(f, expected);
}
}
template <class Devector> void test_resize_back_throwing(dtl::true_)
// size < required, constructor throws
{
#ifndef BOOST_NO_EXCEPTIONS
typedef typename Devector::iterator iterator;
Devector d; get_range<Devector>(5, d);
boost::container::vector<int> d_origi; get_range<boost::container::vector<int> >(5, d_origi);
iterator origi_begin = d.begin();
test_elem_throw::on_ctor_after(3);
BOOST_TEST_THROWS(d.resize_back(256), test_exception);
test_elem_throw::do_not_throw();
test_equal_range(d, d_origi);
BOOST_TEST(origi_begin == d.begin());
#endif //#ifndef BOOST_NO_EXCEPTIONS
}
template <class Devector> void test_resize_back_throwing(dtl::false_)
{}
template <class Devector> void test_resize_back()
{
typedef typename Devector::value_type T;
// size < required, alloc needed
{
Devector a; get_range<Devector>(5, a);
a.resize_back(8);
const int expected [] = {1, 2, 3, 4, 5, 0, 0, 0};
test_equal_range(a, expected);
}
// size < required, but capacity provided
{
Devector b; get_range<Devector>(5, b);
b.reserve_back(16);
b.resize_back(8);
const int expected [] = {1, 2, 3, 4, 5, 0, 0, 0};
test_equal_range(b, expected);
}
/*
// size < required, move would throw
if (! boost::is_nothrow_move_constructible<T>::value && std::is_copy_constructible<T>::value)
{
Devector c; get_range<Devector>(5, c);
test_elem_throw::on_move_after(3);
c.resize_back(8); // shouldn't use the throwing move
test_elem_throw::do_not_throw();
test_equal_range(c, {1, 2, 3, 4, 5, 0, 0, 0});
}
*/
test_resize_back_throwing<Devector>
(dtl::bool_<! boost::move_detail::is_nothrow_default_constructible<T>::value>());
// size >= required
{
Devector e; get_range<Devector>(6, e);
e.resize_back(4);
const int expected [] = {1, 2, 3, 4};
test_equal_range(e, expected);
}
// size < required, does not fit front small buffer
{
boost::container::vector<int> expected(128);
Devector g;
g.resize_back(128);
test_equal_range(g, expected);
}
// size = required
{
Devector e; get_range<Devector>(6, e);
e.resize_back(6);
const int expected [] = {1, 2, 3, 4, 5, 6};
test_equal_range(e, expected);
}
}
template <class Devector> void test_resize_back_copy_throwing(dtl::true_)
{
#ifndef BOOST_NO_EXCEPTIONS
typedef typename Devector::value_type T;
typedef typename Devector::iterator iterator;
// size < required, copy throws
{
Devector c; get_range<Devector>(5, c);
boost::container::vector<int> c_origi; get_range<boost::container::vector<int> >(5, c_origi);
test_elem_throw::on_copy_after(3);
BOOST_TEST_THROWS(c.resize_back(256, T(404)), test_exception);
test_elem_throw::do_not_throw();
test_equal_range(c, c_origi);
}
// size < required, copy throws, but later
{
Devector c; get_range<Devector>(5, c);
boost::container::vector<int> c_origi; get_range<boost::container::vector<int> >(5, c_origi);
iterator origi_begin = c.begin();
test_elem_throw::on_copy_after(7);
BOOST_TEST_THROWS(c.resize_back(256, T(404)), test_exception);
test_elem_throw::do_not_throw();
test_equal_range(c, c_origi);
BOOST_TEST(origi_begin == c.begin());
}
// size < required, copy throws
{
Devector c; get_range<Devector>(5, c);
boost::container::vector<int> c_origi; get_range<boost::container::vector<int> >(5, c_origi);
iterator origi_begin = c.begin();
test_elem_throw::on_copy_after(3);
BOOST_TEST_THROWS(c.resize_back(256, T(404)), test_exception);
test_elem_throw::do_not_throw();
test_equal_range(c, c_origi);
BOOST_TEST(origi_begin == c.begin());
}
#endif //#ifndef BOOST_NO_EXCEPTIONS
}
template <class Devector> void test_resize_back_copy_throwing(dtl::false_)
{}
template <class Devector> void test_resize_back_copy()
{
typedef typename Devector::value_type T;
// size < required, alloc needed
{
Devector a; get_range<Devector>(5, a);
a.resize_back(8, T(9));
const int expected [] = {1, 2, 3, 4, 5, 9, 9, 9};
test_equal_range(a, expected);
}
// size < required, but capacity provided
{
Devector b; get_range<Devector>(5, b);
b.reserve_back(16);
b.resize_back(8, T(9));
const int expected [] = {1, 2, 3, 4, 5, 9, 9, 9};
test_equal_range(b, expected);
}
test_resize_back_copy_throwing<Devector>
(dtl::bool_<! boost::move_detail::is_nothrow_copy_constructible<T>::value>());
// size >= required
{
Devector e; get_range<Devector>(6, e);
e.resize_back(4, T(404));
const int expected [] = {1, 2, 3, 4};
test_equal_range(e, expected);
}
// size < required, does not fit front small buffer
{
boost::container::vector<int> expected(128, 9);
Devector g;
g.resize_back(128, T(9));
test_equal_range(g, expected);
}
// size = required
{
Devector e; get_range<Devector>(6, e);
e.resize_back(6, T(9));
const int expected [] = {1, 2, 3, 4, 5, 6};
test_equal_range(e, expected);
}
// size < required, tmp is already inserted
{
Devector f; get_range<Devector>(8, f);
const T& tmp = *(f.begin() + 1);
f.resize_back(16, tmp);
const int expected [] = {1,2,3,4,5,6,7,8,2,2,2,2,2,2,2,2};
test_equal_range(f, expected);
}
}
/*
template <class Devector> void test_constructor_unsafe_uninitialized()
{
{
Devector a(8, unsafe_uninitialized_tag_t());
BOOST_TEST(a.size() == 8u);
for (int i = 0; i < 8; ++i)
{
new (a.data() + i) T(i+1);
}
const int expected [] = {1, 2, 3, 4, 5, 6, 7, 8};
test_equal_range(a, expected);
}
{
Devector b(0, unsafe_uninitialized_tag_t());
BOOST_TEST(b.get_alloc_count() == 0u);
}
}
*/
/*
template <class Devector> void test_unsafe_uninitialized_resize_front()
{
typedef typename Devector::value_type T;
{ // noop
Devector a; get_range<Devector>(8, a);
a.reset_alloc_stats();
a.unsafe_uninitialized_resize_front(a.size());
const int expected [] = {1, 2, 3, 4, 5, 6, 7, 8};
test_equal_range(a, expected);
BOOST_TEST(a.get_alloc_count() == 0u);
}
{ // grow (maybe has enough capacity)
Devector b; get_range<Devector>(0, 0, 5, 9, b);
b.unsafe_uninitialized_resize_front(8);
for (int i = 0; i < 4; ++i)
{
new (b.data() + i) T(i+1);
}
const int expected [] = {1, 2, 3, 4, 5, 6, 7, 8};
test_equal_range(b, expected);
}
{ // shrink uninitialized
Devector c; get_range<Devector>(8, c);
c.unsafe_uninitialized_resize_front(16);
c.unsafe_uninitialized_resize_front(8);
const int expected [] = {1, 2, 3, 4, 5, 6, 7, 8};
test_equal_range(c, expected );
}
if (std::is_trivially_destructible<T>::value)
{
// shrink
Devector d; get_range<Devector>(8, d);
d.unsafe_uninitialized_resize_front(4);
test_equal_range(d, {5, 6, 7, 8});
}
}
template <class Devector> void test_unsafe_uninitialized_resize_back()
{
typedef typename Devector::value_type T;
{ // noop
Devector a; get_range<Devector>(8, a);
a.reset_alloc_stats();
a.unsafe_uninitialized_resize_back(a.size());
test_equal_range(a, {1, 2, 3, 4, 5, 6, 7, 8});
BOOST_TEST(a.get_alloc_count() == 0u);
}
{ // grow (maybe has enough capacity)
Devector b; get_range<Devector>(1, 5, 0, 0, b);
b.unsafe_uninitialized_resize_back(8);
for (int i = 0; i < 4; ++i)
{
new (b.data() + 4 + i) T(i+5);
}
test_equal_range(b, {1, 2, 3, 4, 5, 6, 7, 8});
}
{ // shrink uninitialized
Devector c; get_range<Devector>(8, c);
c.unsafe_uninitialized_resize_back(16);
c.unsafe_uninitialized_resize_back(8);
test_equal_range(c, {1, 2, 3, 4, 5, 6, 7, 8});
}
if (std::is_trivially_destructible<T>::value)
{
// shrink
Devector d; get_range<Devector>(8, d);
d.unsafe_uninitialized_resize_back(4);
test_equal_range(d, {1, 2, 3, 4});
}
}
*/
template <class Devector> void test_reserve_front()
{
typedef typename Devector::value_type value_type;
Devector a;
a.reserve_front(100);
for (unsigned i = 0; i < 100u; ++i)
{
a.push_front(value_type(i));
}
BOOST_TEST(a.get_alloc_count() == 1u);
Devector b;
b.reserve_front(4);
b.reserve_front(6);
b.reserve_front(4);
b.reserve_front(8);
b.reserve_front(16);
}
template <class Devector> void test_reserve_back()
{
Devector a;
typedef typename Devector::value_type value_type;
a.reserve_back(100);
for (unsigned i = 0; i < 100; ++i)
{
a.push_back(value_type(i));
}
BOOST_TEST(a.get_alloc_count() == 1u);
Devector b;
b.reserve_back(4);
b.reserve_back(6);
b.reserve_back(4);
b.reserve_back(8);
b.reserve_back(16);
}
template <typename Devector>
void test_shrink_to_fit_always()
{
Devector a;
a.reserve(100);
a.push_back(1);
a.push_back(2);
a.push_back(3);
a.shrink_to_fit();
boost::container::vector<unsigned> expected;
expected.push_back(1);
expected.push_back(2);
expected.push_back(3);
test_equal_range(a, expected);
std::size_t exp_capacity = 3u;
BOOST_TEST(a.capacity() == exp_capacity);
}
template <typename Devector>
void test_shrink_to_fit_never()
{
Devector a;
a.reserve(100);
a.push_back(1);
a.push_back(2);
a.push_back(3);
a.shrink_to_fit();
boost::container::vector<unsigned> expected;
expected.emplace_back(1);
expected.emplace_back(2);
expected.emplace_back(3);
test_equal_range(a, expected);
BOOST_TEST(a.capacity() == 100u);
}
void shrink_to_fit()
{
typedef devector<unsigned> devector_u_shr;
typedef devector<unsigned> small_devector_u_shr;
test_shrink_to_fit_always<devector_u_shr>();
test_shrink_to_fit_always<small_devector_u_shr>();
}
template <class Devector> void test_index_operator()
{
typedef typename Devector::value_type T;
{ // non-const []
Devector a; get_range<Devector>(5, a);
BOOST_TEST(a[0] == 1);
BOOST_TEST(a[4] == 5);
BOOST_TEST(&a[3] == &a[0] + 3);
a[0] = T(100);
BOOST_TEST(a[0] == 100);
}
{ // const []
Devector b; get_range<Devector>(5, b);
const Devector &a = b;
BOOST_TEST(a[0] == 1);
BOOST_TEST(a[4] == 5);
BOOST_TEST(&a[3] == &a[0] + 3);
}
}
template <class Devector> void test_at()
{
#ifndef BOOST_NO_EXCEPTIONS
typedef typename Devector::value_type T;
{ // non-const at
Devector a; get_range<Devector>(3, a);
BOOST_TEST(a.at(0) == 1);
a.at(0) = T(100);
BOOST_TEST(a.at(0) == 100);
BOOST_TEST_THROWS((void)a.at(3), out_of_range_t);
}
{ // const at
Devector b; get_range<Devector>(3, b);
const Devector &a = b;
BOOST_TEST(a.at(0) == 1);
BOOST_TEST_THROWS((void)a.at(3), out_of_range_t);
}
#endif //#ifndef BOOST_NO_EXCEPTIONS
}
template <class Devector> void test_front()
{
typedef typename Devector::value_type T;
{ // non-const front
Devector a; get_range<Devector>(3, a);
BOOST_TEST(a.front() == 1);
a.front() = T(100);
BOOST_TEST(a.front() == 100);
}
{ // const front
Devector b; get_range<Devector>(3, b); const Devector &a = b;
BOOST_TEST(a.front() == 1);
}
}
template <class Devector> void test_back()
{
typedef typename Devector::value_type T;
{ // non-const back
Devector a; get_range<Devector>(3, a);
BOOST_TEST(a.back() == 3);
a.back() = T(100);
BOOST_TEST(a.back() == 100);
}
{ // const back
Devector b; get_range<Devector>(3, b); const Devector &a = b;
BOOST_TEST(a.back() == 3);
}
}
void test_data()
{
unsigned c_array[] = {1, 2, 3, 4};
{ // non-const data
devector<unsigned> a(c_array, c_array + 4);
BOOST_TEST(a.data() == &a.front());
BOOST_TEST(std::memcmp(c_array, a.data(), 4 * sizeof(unsigned)) == 0);
*(a.data()) = 100;
BOOST_TEST(a.front() == 100u);
}
{ // const data
const devector<unsigned> a(c_array, c_array + 4);
BOOST_TEST(a.data() == &a.front());
BOOST_TEST(std::memcmp(c_array, a.data(), 4 * sizeof(unsigned)) == 0);
}
}
template <class Devector> void test_emplace_front(dtl::true_)
{
#ifndef BOOST_NO_EXCEPTIONS
typedef typename Devector::iterator iterator;
Devector b; get_range<Devector>(4, b);
iterator origi_begin = b.begin();
test_elem_throw::on_ctor_after(1);
BOOST_TEST_THROWS(b.emplace_front(404), test_exception);
test_elem_throw::do_not_throw();
iterator new_begin = b.begin();
BOOST_TEST(origi_begin == new_begin);
BOOST_TEST(b.size() == 4u);
#endif //#ifndef BOOST_NO_EXCEPTIONS
}
template <class Devector> void test_emplace_front(dtl::false_)
{
}
template <class Devector> void test_emplace_front()
{
typedef typename Devector::value_type T;
{
Devector a;
a.emplace_front(3);
a.emplace_front(2);
a.emplace_front(1);
boost::container::vector<int> expected; get_range<boost::container::vector<int> >(3, expected);
test_equal_range(a, expected);
}
test_emplace_front<Devector>
(dtl::bool_<!boost::move_detail::is_nothrow_default_constructible<T>::value>());
}
template <class Devector> void test_push_front()
{
typedef typename Devector::value_type T;
{
boost::container::vector<int> expected; get_range<boost::container::vector<int> >(16, expected);
std::reverse(expected.begin(), expected.end());
Devector a;
for (int i = 1; i <= 16; ++i)
{
T elem(i);
a.push_front(elem);
}
test_equal_range(a, expected);
}
#ifndef BOOST_NO_EXCEPTIONS
typedef typename Devector::iterator iterator;
if (! boost::move_detail::is_nothrow_copy_constructible<T>::value)
{
Devector b; get_range<Devector>(4, b);
iterator origi_begin = b.begin();
const T elem(404);
test_elem_throw::on_copy_after(1);
BOOST_TEST_THROWS(b.push_front(elem), test_exception);
test_elem_throw::do_not_throw();
iterator new_begin = b.begin();
BOOST_TEST(origi_begin == new_begin);
BOOST_TEST(b.size() == 4u);
}
// test when tmp is already inserted
{
Devector c; get_range<Devector>(4, c);
const T& tmp = *(c.begin() + 1);
c.push_front(tmp);
const int expected[] = {2, 1, 2, 3, 4};
test_equal_range(c, expected);
}
#endif //#ifndef BOOST_NO_EXCEPTIONS
}
template <class Devector> void test_push_front_rvalue_throwing(dtl::true_)
{
#ifndef BOOST_NO_EXCEPTIONS
typedef typename Devector::value_type T;
typedef typename Devector::iterator iterator;
Devector b; get_range<Devector>(4, b);
iterator origi_begin = b.begin();
test_elem_throw::on_move_after(1);
BOOST_TEST_THROWS(b.push_front(T(404)), test_exception);
test_elem_throw::do_not_throw();
iterator new_begin = b.begin();
BOOST_TEST(origi_begin == new_begin);
BOOST_TEST(b.size() == 4u);
#endif //#ifndef BOOST_NO_EXCEPTIONS
}
template <class Devector> void test_push_front_rvalue_throwing(dtl::false_)
{}
template <class Devector> void test_push_front_rvalue()
{
typedef typename Devector::value_type T;
{
boost::container::vector<int> expected; get_range<boost::container::vector<int> >(16, expected);
Devector a;
for (int i = 16; i > 0; --i)
{
T elem(i);
a.push_front(boost::move(elem));
}
test_equal_range(a, expected);
}
test_push_front_rvalue_throwing<Devector>(dtl::bool_<! boost::is_nothrow_move_constructible<T>::value>());
}
template <class Devector> void test_pop_front()
{
{
Devector a;
a.emplace_front(1);
a.pop_front();
BOOST_TEST(a.empty());
}
{
Devector b;
b.emplace_back(2);
b.pop_front();
BOOST_TEST(b.empty());
b.emplace_front(3);
b.pop_front();
BOOST_TEST(b.empty());
}
{
Devector c; get_range<Devector>(20, c);
for (int i = 0; i < 20; ++i)
{
BOOST_TEST(!c.empty());
c.pop_front();
}
BOOST_TEST(c.empty());
}
}
template <class Devector> void test_emplace_back_throwing(dtl::true_)
{
#ifndef BOOST_NO_EXCEPTIONS
typedef typename Devector::iterator iterator;
Devector b; get_range<Devector>(4, b);
iterator origi_begin = b.begin();
test_elem_throw::on_ctor_after(1);
BOOST_TEST_THROWS(b.emplace_back(404), test_exception);
test_elem_throw::do_not_throw();
iterator new_begin = b.begin();
BOOST_TEST(origi_begin == new_begin);
BOOST_TEST(b.size() == 4u);
#endif //#ifndef BOOST_NO_EXCEPTIONS
}
template <class Devector> void test_emplace_back_throwing(dtl::false_)
{}
template <class Devector> void test_emplace_back()
{
typedef typename Devector::value_type T;
{
Devector a;
a.emplace_back(1);
a.emplace_back(2);
a.emplace_back(3);
boost::container::vector<int> expected; get_range<boost::container::vector<int> >(3, expected);
test_equal_range<Devector>(a, expected);
}
test_emplace_back_throwing<Devector>
(dtl::bool_<! boost::move_detail::is_nothrow_default_constructible<T>::value>());
}
template <class Devector> void test_push_back_throwing(dtl::true_)
{
#ifndef BOOST_NO_EXCEPTIONS
typedef typename Devector::value_type T;
typedef typename Devector::iterator iterator;
Devector b; get_range<Devector>(4, b);
iterator origi_begin = b.begin();
const T elem(404);
test_elem_throw::on_copy_after(1);
BOOST_TEST_THROWS(b.push_back(elem), test_exception);
test_elem_throw::do_not_throw();
iterator new_begin = b.begin();
BOOST_TEST(origi_begin == new_begin);
BOOST_TEST(b.size() == 4u);
#endif //#ifndef BOOST_NO_EXCEPTIONS
}
template <class Devector> void test_push_back_throwing(dtl::false_)
{}
template <class Devector> void test_push_back()
{
typedef typename Devector::value_type T;
{
boost::container::vector<int> expected; get_range<boost::container::vector<int> >(16, expected);
Devector a;
for (int i = 1; i <= 16; ++i)
{
T elem(i);
a.push_back(elem);
}
test_equal_range(a, expected);
}
test_push_back_throwing<Devector>(dtl::bool_<! boost::move_detail::is_nothrow_copy_constructible<T>::value>());
// test when tmp is already inserted
{
Devector c; get_range<Devector>(4, c);
const T& tmp = *(c.begin() + 1);
c.push_back(tmp);
const int expected[] = {1, 2, 3, 4, 2};
test_equal_range(c, expected);
}
}
template <class Devector> void test_push_back_rvalue_throwing(dtl::true_)
{
#ifndef BOOST_NO_EXCEPTIONS
typedef typename Devector::value_type T;
typedef typename Devector::iterator iterator;
Devector b; get_range<Devector>(4, b);
iterator origi_begin = b.begin();
test_elem_throw::on_move_after(1);
BOOST_TEST_THROWS(b.push_back(T(404)), test_exception);
test_elem_throw::do_not_throw();
iterator new_begin = b.begin();
BOOST_TEST(origi_begin == new_begin);
BOOST_TEST(b.size() == 4u);
#endif //#ifndef BOOST_NO_EXCEPTIONS
}
template <class Devector> void test_push_back_rvalue_throwing(dtl::false_)
{}
template <class Devector> void test_push_back_rvalue()
{
typedef typename Devector::value_type T;
{
boost::container::vector<int> expected; get_range<boost::container::vector<int> >(16, expected);
Devector a;
for (int i = 1; i <= 16; ++i)
{
T elem(i);
a.push_back(boost::move(elem));
}
test_equal_range(a, expected);
}
test_push_back_rvalue_throwing<Devector>(dtl::bool_<! boost::is_nothrow_move_constructible<T>::value>());
}
/*
template <class Devector> void test_unsafe_push_front()
{
typedef typename Devector::value_type T;
typedef typename Devector::iterator iterator;
{
boost::container::vector<int> expected; get_range<boost::container::vector<int> >(16, expected);
std::reverse(expected.begin(), expected.end());
Devector a;
a.reserve_front(16);
for (std::size_t i = 1; i <= 16; ++i)
{
T elem(i);
a.unsafe_push_front(elem);
}
test_equal_range(a, expected);
}
#ifndef BOOST_NO_EXCEPTIONS
if (! boost::move_detail::is_nothrow_copy_constructible<T>::value)
{
Devector b; get_range<Devector>(4, b);
b.reserve_front(5);
iterator origi_begin = b.begin();
const T elem(404);
test_elem_throw::on_copy_after(1);
BOOST_TEST_THROWS(b.unsafe_push_front(elem), test_exception);
test_elem_throw::do_not_throw();
iterator new_begin = b.begin();
BOOST_TEST(origi_begin == new_begin);
BOOST_TEST(b.size() == 4u);
}
#endif //#ifndef BOOST_NO_EXCEPTIONS
}
template <class Devector> void test_unsafe_push_front_rvalue()
{
typedef typename Devector::value_type T;
{
boost::container::vector<int> expected; get_range<boost::container::vector<int> >(16, expected);
std::reverse(expected.begin(), expected.end());
Devector a;
a.reserve_front(16);
for (std::size_t i = 1; i <= 16; ++i)
{
T elem(i);
a.unsafe_push_front(boost::move(elem));
}
test_equal_range(a, expected);
}
}
*/
/*
template <class Devector> void test_unsafe_push_back()
{
typedef typename Devector::value_type T;
typedef typename Devector::iterator iterator;
{
boost::container::vector<int> expected; get_range<boost::container::vector<int> >(16, expected);
Devector a;
a.reserve(16);
for (std::size_t i = 1; i <= 16; ++i)
{
T elem(i);
a.unsafe_push_back(elem);
}
test_equal_range(a, expected);
}
#ifndef BOOST_NO_EXCEPTIONS
if (! boost::move_detail::is_nothrow_copy_constructible<T>::value)
{
Devector b; get_range<Devector>(4, b);
b.reserve(5);
iterator origi_begin = b.begin();
const T elem(404);
test_elem_throw::on_copy_after(1);
BOOST_TEST_THROWS(b.unsafe_push_back(elem), test_exception);
test_elem_throw::do_not_throw();
iterator new_begin = b.begin();
BOOST_TEST(origi_begin == new_begin);
BOOST_TEST(b.size() == 4u);
}
#endif
}
template <class Devector> void test_unsafe_push_back_rvalue()
{
typedef typename Devector::value_type T;
{
boost::container::vector<int> expected; get_range<boost::container::vector<int> >(16, expected);
Devector a;
a.reserve(16);
for (std::size_t i = 1; i <= 16; ++i)
{
T elem(i);
a.unsafe_push_back(boost::move(elem));
}
test_equal_range(a, expected);
}
}
*/
template <class Devector> void test_pop_back()
{
{
Devector a;
a.emplace_back(1);
a.pop_back();
BOOST_TEST(a.empty());
}
{
Devector b;
b.emplace_front(2);
b.pop_back();
BOOST_TEST(b.empty());
b.emplace_back(3);
b.pop_back();
BOOST_TEST(b.empty());
}
{
Devector c; get_range<Devector>(20, c);
for (int i = 0; i < 20; ++i)
{
BOOST_TEST(!c.empty());
c.pop_back();
}
BOOST_TEST(c.empty());
}
}
template <class Devector> void test_emplace_throwing(dtl::true_)
{
#ifndef BOOST_NO_EXCEPTIONS
typedef typename Devector::iterator iterator;
Devector j; get_range<Devector>(4, j);
iterator origi_begin = j.begin();
test_elem_throw::on_ctor_after(1);
BOOST_TEST_THROWS(j.emplace(j.begin() + 2, 404), test_exception);
test_elem_throw::do_not_throw();
const int expected[] = {1, 2, 3, 4};
test_equal_range(j, expected);
BOOST_TEST(origi_begin == j.begin());
#endif
}
template <class Devector> void test_emplace_throwing(dtl::false_)
{}
template <class Devector> void test_emplace()
{
typedef typename Devector::iterator iterator;
{
Devector a; get_range<Devector>(16, a);
typename Devector::iterator it = a.emplace(a.begin(), 123);
const int expected[] = {123, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16};
test_equal_range(a, expected);
BOOST_TEST(*it == 123);
}
{
Devector b; get_range<Devector>(16, b);
typename Devector::iterator it = b.emplace(b.end(), 123);
const int expected [] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 123};
test_equal_range(b, expected);
BOOST_TEST(*it == 123);
}
{
Devector c; get_range<Devector>(16, c);
c.pop_front();
typename Devector::iterator it = c.emplace(c.begin(), 123);
const int expected [] = {123, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16};
test_equal_range(c, expected);
BOOST_TEST(*it == 123);
}
{
Devector d; get_range<Devector>(16, d);
d.pop_back();
typename Devector::iterator it = d.emplace(d.end(), 123);
const int expected [] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 123};
test_equal_range(d, expected);
BOOST_TEST(*it == 123);
}
{
Devector e; get_range<Devector>(16, e);
typename Devector::iterator it = e.emplace(e.begin() + 5, 123);
const int expected [] = {1, 2, 3, 4, 5, 123, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16};
test_equal_range(e, expected);
BOOST_TEST(*it == 123);
}
{
Devector f; get_range<Devector>(16, f);
f.pop_front();
f.pop_back();
iterator valid = f.begin() + 1;
typename Devector::iterator it = f.emplace(f.begin() + 1, 123);
const int expected [] = {2, 123, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15};
test_equal_range(f, expected);
BOOST_TEST(*it == 123);
BOOST_TEST(*valid == 3);
}
{
Devector g; get_range<Devector>(16, g);
g.pop_front();
g.pop_back();
iterator valid = g.end() - 2;
typename Devector::iterator it = g.emplace(g.end() - 1, 123);
const int expected[] = {2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 123, 15};
test_equal_range(g, expected);
BOOST_TEST(*it == 123);
BOOST_TEST(*valid == 14);
}
{
Devector h; get_range<Devector>(16, h);
h.pop_front();
h.pop_back();
iterator valid = h.begin() + 7;
typename Devector::iterator it = h.emplace(h.begin() + 7, 123);
const int expected[] = {2, 3, 4, 5, 6, 7, 8, 123, 9, 10, 11, 12, 13, 14, 15};
test_equal_range(h, expected);
BOOST_TEST(*it == 123);
BOOST_TEST(*valid == 9);
}
{
Devector i;
i.emplace(i.begin(), 1);
i.emplace(i.end(), 10);
for (int j = 2; j < 10; ++j)
{
i.emplace(i.begin() + (j-1), j);
}
const int expected[] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
test_equal_range(i, expected);
}
typedef typename Devector::value_type T;
test_emplace_throwing<Devector>
(dtl::bool_<! boost::move_detail::is_nothrow_default_constructible<T>::value>());
}
template <class Devector> void test_insert_throwing(dtl::true_)
{
#ifndef BOOST_NO_EXCEPTIONS
typedef typename Devector::value_type T;
typedef typename Devector::iterator iterator;
T test_elem(123);
Devector j; get_range<Devector>(4, j);
iterator origi_begin = j.begin();
test_elem_throw::on_copy_after(1);
BOOST_TEST_THROWS(j.insert(j.begin() + 2, test_elem), test_exception);
test_elem_throw::do_not_throw();
const int expected[] = {1, 2, 3, 4};
test_equal_range(j, expected);
BOOST_TEST(origi_begin == j.begin());
#endif //#ifndef BOOST_NO_EXCEPTIONS
}
template <class Devector> void test_insert_throwing(dtl::false_)
{}
template <class Devector> void test_insert()
{
typedef typename Devector::value_type T;
typedef typename Devector::iterator iterator;
T test_elem(123);
{
Devector a; get_range<Devector>(16, a);
typename Devector::iterator it = a.insert(a.begin(), test_elem);
const int expected[] = {123, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16};
test_equal_range(a, expected);
BOOST_TEST(*it == 123);
}
{
Devector b; get_range<Devector>(16, b);
typename Devector::iterator it = b.insert(b.end(), test_elem);
const int expected[] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 123};
test_equal_range(b, expected);
BOOST_TEST(*it == 123);
}
{
Devector c; get_range<Devector>(16, c);
c.pop_front();
typename Devector::iterator it = c.insert(c.begin(), test_elem);
const int expected[] = {123, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16};
test_equal_range(c, expected);
BOOST_TEST(*it == 123);
}
{
Devector d; get_range<Devector>(16, d);
d.pop_back();
typename Devector::iterator it = d.insert(d.end(), test_elem);
const int expected[] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 123};
test_equal_range(d, expected);
BOOST_TEST(*it == 123);
}
{
Devector e; get_range<Devector>(16, e);
typename Devector::iterator it = e.insert(e.begin() + 5, test_elem);
const int expected[] = {1, 2, 3, 4, 5, 123, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16};
test_equal_range(e, expected);
BOOST_TEST(*it == 123);
}
{
Devector f; get_range<Devector>(16, f);
f.pop_front();
f.pop_back();
iterator valid = f.begin() + 1;
typename Devector::iterator it = f.insert(f.begin() + 1, test_elem);
const int expected[] = {2, 123, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15};
test_equal_range(f, expected);
BOOST_TEST(*it == 123);
BOOST_TEST(*valid == 3);
}
{
Devector g; get_range<Devector>(16, g);
g.pop_front();
g.pop_back();
iterator valid = g.end() - 2;
typename Devector::iterator it = g.insert(g.end() - 1, test_elem);
const int expected[] = {2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 123, 15};
test_equal_range(g, expected);
BOOST_TEST(*it == 123);
BOOST_TEST(*valid == 14);
}
{
Devector h; get_range<Devector>(16, h);
h.pop_front();
h.pop_back();
iterator valid = h.begin() + 7;
typename Devector::iterator it = h.insert(h.begin() + 7, test_elem);
const int expected[] = {2, 3, 4, 5, 6, 7, 8, 123, 9, 10, 11, 12, 13, 14, 15};
test_equal_range(h, expected);
BOOST_TEST(*it == 123);
BOOST_TEST(*valid == 9);
}
{
Devector i;
i.insert(i.begin(), T(1));
i.insert(i.end(), T(10));
for (int j = 2; j < 10; ++j)
{
i.insert(i.begin() + (j-1), T(j));
}
const int expected[] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
test_equal_range(i, expected);
}
test_insert_throwing<Devector>
(dtl::bool_<! boost::move_detail::is_nothrow_copy_constructible<T>::value>());
// test when tmp is already inserted and there's free capacity
{
Devector c; get_range<Devector>(6, c);
c.pop_back();
const T& tmp = *(c.begin() + 2);
c.insert(c.begin() + 1, tmp);
const int expected[] = {1, 3, 2, 3, 4, 5};
test_equal_range(c, expected);
}
// test when tmp is already inserted and maybe there's no free capacity
{
Devector c; get_range<Devector>(6, c);
const T& tmp = *(c.begin() + 2);
c.insert(c.begin() + 1, tmp);
const int expected[] = {1, 3, 2, 3, 4, 5, 6};
test_equal_range(c, expected);
}
}
template <class Devector> void test_insert_rvalue_throwing(dtl::true_)
{
#ifndef BOOST_NO_EXCEPTIONS
typedef typename Devector::value_type T;
typedef typename Devector::iterator iterator;
Devector j; get_range<Devector>(4, j);
iterator origi_begin = j.begin();
test_elem_throw::on_ctor_after(1);
BOOST_TEST_THROWS(j.insert(j.begin() + 2, T(404)), test_exception);
test_elem_throw::do_not_throw();
const int expected[] = {1, 2, 3, 4};
test_equal_range(j, expected);
BOOST_TEST(origi_begin == j.begin());
#endif //#ifndef BOOST_NO_EXCEPTIONS
}
template <class Devector> void test_insert_rvalue_throwing(dtl::false_)
{}
template <class Devector> void test_insert_rvalue()
{
typedef typename Devector::value_type T;
typedef typename Devector::iterator iterator;
{
Devector a; get_range<Devector>(16, a);
typename Devector::iterator it = a.insert(a.begin(), T(123));
const int expected[] = {123, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16};
test_equal_range(a, expected);
BOOST_TEST(*it == 123);
}
{
Devector b; get_range<Devector>(16, b);
typename Devector::iterator it = b.insert(b.end(), T(123));
const int expected[] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 123};
test_equal_range(b, expected);
BOOST_TEST(*it == 123);
}
{
Devector c; get_range<Devector>(16, c);
c.pop_front();
typename Devector::iterator it = c.insert(c.begin(), T(123));
const int expected[] = {123, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16};
test_equal_range(c, expected);
BOOST_TEST(*it == 123);
}
{
Devector d; get_range<Devector>(16, d);
d.pop_back();
typename Devector::iterator it = d.insert(d.end(), T(123));
const int expected[] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 123};
test_equal_range(d, expected);
BOOST_TEST(*it == 123);
}
{
Devector e; get_range<Devector>(16, e);
typename Devector::iterator it = e.insert(e.begin() + 5, T(123));
const int expected[] = {1, 2, 3, 4, 5, 123, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16};
test_equal_range(e, expected);
BOOST_TEST(*it == 123);
}
{
Devector f; get_range<Devector>(16, f);
f.pop_front();
f.pop_back();
iterator valid = f.begin() + 1;
typename Devector::iterator it = f.insert(f.begin() + 1, T(123));
const int expected[] = {2, 123, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15};
test_equal_range(f, expected);
BOOST_TEST(*it == 123);
BOOST_TEST(*valid == 3);
}
{
Devector g; get_range<Devector>(16, g);
g.pop_front();
g.pop_back();
iterator valid = g.end() - 2;
typename Devector::iterator it = g.insert(g.end() - 1, T(123));
const int expected[] = {2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 123, 15};
test_equal_range(g, expected);
BOOST_TEST(*it == 123);
BOOST_TEST(*valid == 14);
}
{
Devector h; get_range<Devector>(16, h);
h.pop_front();
h.pop_back();
iterator valid = h.begin() + 7;
typename Devector::iterator it = h.insert(h.begin() + 7, T(123));
const int expected[] = {2, 3, 4, 5, 6, 7, 8, 123, 9, 10, 11, 12, 13, 14, 15};
test_equal_range(h, expected);
BOOST_TEST(*it == 123);
BOOST_TEST(*valid == 9);
}
{
Devector i;
i.insert(i.begin(), T(1));
i.insert(i.end(), T(10));
for (int j = 2; j < 10; ++j)
{
i.insert(i.begin() + (j-1), T(j));
}
const int expected[] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
test_equal_range(i, expected);
}
test_insert_rvalue_throwing<Devector>
(dtl::bool_<! boost::move_detail::is_nothrow_default_constructible<T>::value>());
}
template <class Devector> void test_insert_n_throwing(dtl::true_)
{
#ifndef BOOST_NO_EXCEPTIONS
typedef typename Devector::value_type T;
// insert at begin
{
Devector j; get_range<Devector>(4, j);
const T x(404);
test_elem_throw::on_copy_after(3);
BOOST_TEST_THROWS(j.insert(j.begin(), 4, x), test_exception);
test_elem_throw::do_not_throw();
}
// insert at end
{
Devector k; get_range<Devector>(4, k);
const T x(404);
test_elem_throw::on_copy_after(3);
BOOST_TEST_THROWS(k.insert(k.end(), 4, x), test_exception);
test_elem_throw::do_not_throw();
}
#endif //#ifndef BOOST_NO_EXCEPTIONS
}
template <class Devector> void test_insert_n_throwing(dtl::false_)
{}
template <class Devector> void test_insert_n()
{
typedef typename Devector::value_type T;
typedef typename Devector::iterator iterator;
{
Devector a;
const T x(123);
iterator ret = a.insert(a.end(), 5, x);
const int expected[] = {123, 123, 123, 123, 123};
test_equal_range(a, expected);
BOOST_TEST(ret == a.begin());
}
{
Devector b; get_range<Devector>(8, b);
const T x(9);
iterator ret = b.insert(b.begin(), 3, x);
const int expected[] = {9, 9, 9, 1, 2, 3, 4, 5, 6, 7, 8};
test_equal_range(b, expected);
BOOST_TEST(ret == b.begin());
}
{
Devector c; get_range<Devector>(8, c);
const T x(9);
iterator ret = c.insert(c.end(), 3, x);
const int expected[] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 9, 9};
test_equal_range(c, expected);
BOOST_TEST(ret == c.begin() + 8);
}
{
Devector d; get_range<Devector>(8, d);
d.pop_front();
d.pop_front();
d.pop_front();
const T x(9);
iterator origi_end = d.end();
iterator ret = d.insert(d.begin(), 3, x);
const int expected[] = {9, 9, 9, 4, 5, 6, 7, 8};
test_equal_range(d, expected);
BOOST_TEST(origi_end == d.end());
BOOST_TEST(ret == d.begin());
}
{
Devector e; get_range<Devector>(8, e);
e.pop_back();
e.pop_back();
e.pop_back();
const T x(9);
iterator origi_begin = e.begin();
iterator ret = e.insert(e.end(), 3, x);
const int expected[] = {1, 2, 3, 4, 5, 9, 9, 9};
test_equal_range(e, expected);
BOOST_TEST(origi_begin == e.begin());
BOOST_TEST(ret == e.begin() + 5);
}
{
Devector f; get_range<Devector>(8, f);
f.reset_alloc_stats();
f.pop_front();
f.pop_front();
f.pop_back();
f.pop_back();
const T x(9);
iterator ret = f.insert(f.begin() + 2, 4, x);
const int expected[] = {3, 4, 9, 9, 9, 9, 5, 6};
test_equal_range(f, expected);
BOOST_TEST(f.get_alloc_count() == 0u);
BOOST_TEST(ret == f.begin() + 2);
}
{
Devector g; get_range<Devector>(8, g);
g.reset_alloc_stats();
g.pop_front();
g.pop_front();
g.pop_back();
g.pop_back();
g.pop_back();
const T x(9);
iterator ret = g.insert(g.begin() + 2, 5, x);
const int expected[] = {3, 4, 9, 9, 9, 9, 9, 5};
test_equal_range(g, expected);
BOOST_TEST(g.get_alloc_count() == 0u);
BOOST_TEST(ret == g.begin() + 2);
}
{
Devector g; get_range<Devector>(8, g);
const T x(9);
iterator ret = g.insert(g.begin() + 2, 5, x);
const int expected[] = {1, 2, 9, 9, 9, 9, 9, 3, 4, 5, 6, 7, 8};
test_equal_range(g, expected);
BOOST_TEST(ret == g.begin() + 2);
}
{ // n == 0
Devector h; get_range<Devector>(8, h);
h.reset_alloc_stats();
const T x(9);
iterator ret = h.insert(h.begin(), 0, x);
BOOST_TEST(ret == h.begin());
ret = h.insert(h.begin() + 4, 0, x);
BOOST_TEST(ret == h.begin() + 4);
ret = h.insert(h.end(), 0, x);
BOOST_TEST(ret == h.end());
const int expected[] = {1, 2, 3, 4, 5, 6, 7, 8};
test_equal_range(h, expected);
BOOST_TEST(h.get_alloc_count() == 0u);
}
{ // test insert already inserted
Devector i; get_range<Devector>(8, i);
i.reset_alloc_stats();
i.pop_front();
i.pop_front();
iterator ret = i.insert(i.end() - 1, 2, *i.begin());
const int expected[] = {3, 4, 5, 6, 7, 3, 3, 8};
test_equal_range(i, expected);
BOOST_TEST(i.get_alloc_count() == 0u);
BOOST_TEST(ret == i.begin() + 5);
}
test_insert_n_throwing<Devector>
(dtl::bool_<! boost::move_detail::is_nothrow_copy_constructible<T>::value>());
}
template <class Devector> void test_insert_input_range()
{
typedef typename Devector::value_type T;
typedef typename Devector::iterator iterator;
devector<T> x;
x.emplace_back(9);
x.emplace_back(9);
x.emplace_back(9);
x.emplace_back(9);
x.emplace_back(9);
{
devector<T> input = x;
input_iterator<Devector> input_begin = make_input_iterator(input, input.begin());
input_iterator<Devector> input_end = make_input_iterator(input, input.begin() + 5);
Devector a;
iterator ret = a.insert(a.end(), input_begin, input_end);
const int expected[] = {9, 9, 9, 9, 9};
test_equal_range(a, expected);
BOOST_TEST(ret == a.begin());
}
{
devector<T> input = x;
input_iterator<Devector> input_begin = make_input_iterator(input, input.begin());
input_iterator<Devector> input_end = make_input_iterator(input, input.begin() + 3);
Devector b; get_range<Devector>(8, b);
iterator ret = b.insert(b.begin(), input_begin, input_end);
const int expected[] = {9, 9, 9, 1, 2, 3, 4, 5, 6, 7, 8};
test_equal_range(b, expected);
BOOST_TEST(ret == b.begin());
}
{
devector<T> input = x;
input_iterator<Devector> input_begin = make_input_iterator(input, input.begin());
input_iterator<Devector> input_end = make_input_iterator(input, input.begin() + 3);
Devector c; get_range<Devector>(8, c);
iterator ret = c.insert(c.end(), input_begin, input_end);
const int expected[] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 9, 9};
test_equal_range(c, expected);
BOOST_TEST(ret == c.begin() + 8);
}
{
devector<T> input = x;
input_iterator<Devector> input_begin = make_input_iterator(input, input.begin());
input_iterator<Devector> input_end = make_input_iterator(input, input.begin() + 3);
Devector d; get_range<Devector>(8, d);
d.pop_front();
d.pop_front();
d.pop_front();
iterator ret = d.insert(d.begin(), input_begin, input_end);
const int expected[] = {9, 9, 9, 4, 5, 6, 7, 8};
test_equal_range(d, expected);
BOOST_TEST(ret == d.begin());
}
{
devector<T> input = x;
input_iterator<Devector> input_begin = make_input_iterator(input, input.begin());
input_iterator<Devector> input_end = make_input_iterator(input, input.begin() + 3);
Devector e; get_range<Devector>(8, e);
e.pop_back();
e.pop_back();
e.pop_back();
iterator origi_begin = e.begin();
iterator ret = e.insert(e.end(), input_begin, input_end);
const int expected[] = {1, 2, 3, 4, 5, 9, 9, 9};
test_equal_range(e, expected);
BOOST_TEST(origi_begin == e.begin());
BOOST_TEST(ret == e.begin() + 5);
}
{
devector<T> input = x;
input_iterator<Devector> input_begin = make_input_iterator(input, input.begin());
input_iterator<Devector> input_end = make_input_iterator(input, input.begin() + 4);
Devector f; get_range<Devector>(8, f);
f.reset_alloc_stats();
f.pop_front();
f.pop_front();
f.pop_back();
f.pop_back();
iterator ret = f.insert(f.begin() + 2, input_begin, input_end);
const int expected[] = {3, 4, 9, 9, 9, 9, 5, 6};
test_equal_range(f, expected);
BOOST_TEST(ret == f.begin() + 2);
}
{
devector<T> input = x;
input_iterator<Devector> input_begin = make_input_iterator(input, input.begin());
input_iterator<Devector> input_end = make_input_iterator(input, input.begin() + 5);
Devector g; get_range<Devector>(8, g);
g.reset_alloc_stats();
g.pop_front();
g.pop_front();
g.pop_back();
g.pop_back();
g.pop_back();
iterator ret = g.insert(g.begin() + 2, input_begin, input_end);
const int expected [] = {3, 4, 9, 9, 9, 9, 9, 5};
test_equal_range(g, expected);
BOOST_TEST(ret == g.begin() + 2);
}
{
devector<T> input = x;
input_iterator<Devector> input_begin = make_input_iterator(input, input.begin());
input_iterator<Devector> input_end = make_input_iterator(input, input.begin() + 5);
Devector g; get_range<Devector>(8, g);
iterator ret = g.insert(g.begin() + 2, input_begin, input_end);
const int expected [] = {1, 2, 9, 9, 9, 9, 9, 3, 4, 5, 6, 7, 8};
test_equal_range(g, expected);
BOOST_TEST(ret == g.begin() + 2);
}
{ // n == 0
devector<T> input = x;
input_iterator<Devector> input_begin = make_input_iterator(input, input.begin());
Devector h; get_range<Devector>(8, h);
h.reset_alloc_stats();
iterator ret = h.insert(h.begin(), input_begin, input_begin);
BOOST_TEST(ret == h.begin());
ret = h.insert(h.begin() + 4, input_begin, input_begin);
BOOST_TEST(ret == h.begin() + 4);
ret = h.insert(h.end(), input_begin, input_begin);
BOOST_TEST(ret == h.end());
const int expected [] = {1, 2, 3, 4, 5, 6, 7, 8};
test_equal_range(h, expected);
}
#ifndef BOOST_NO_EXCEPTIONS
if (! boost::move_detail::is_nothrow_copy_constructible<T>::value)
{
// insert at begin
{
devector<T> input = x;
input_iterator<Devector> input_begin = make_input_iterator(input, input.begin());
input_iterator<Devector> input_end = make_input_iterator(input, input.begin() + 4);
Devector j; get_range<Devector>(4, j);
test_elem_throw::on_copy_after(3);
BOOST_TEST_THROWS(j.insert(j.begin(), input_begin, input_end), test_exception);
test_elem_throw::do_not_throw();
}
// insert at end
{
devector<T> input = x;
input_iterator<Devector> input_begin = make_input_iterator(input, input.begin());
input_iterator<Devector> input_end = make_input_iterator(input, input.begin() + 4);
Devector k; get_range<Devector>(4, k);
test_elem_throw::on_copy_after(3);
BOOST_TEST_THROWS(k.insert(k.end(), input_begin, input_end), test_exception);
test_elem_throw::do_not_throw();
}
}
#endif //#ifndef BOOST_NO_EXCEPTIONS
}
template <class Devector> void test_insert_range()
{
typedef typename Devector::value_type T;
typedef typename Devector::iterator iterator;
typedef boost::container::vector<T> Vector;
Vector x;
x.emplace_back(9);
x.emplace_back(10);
x.emplace_back(11);
x.emplace_back(12);
x.emplace_back(13);
typename Vector::iterator xb = x.begin();
{
Devector a;
iterator ret = a.insert(a.end(), xb, xb+5);
const int expected [] = {9, 10, 11, 12, 13};
test_equal_range(a, expected);
BOOST_TEST(ret == a.begin());
}
{
Devector b; get_range<Devector>(8, b);
iterator ret = b.insert(b.begin(), xb, xb+3);
const int expected [] = {9, 10, 11, 1, 2, 3, 4, 5, 6, 7, 8};
test_equal_range(b, expected);
BOOST_TEST(ret == b.begin());
}
{
Devector c; get_range<Devector>(8, c);
iterator ret = c.insert(c.end(), xb, xb+3);
const int expected [] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11};
test_equal_range(c, expected);
BOOST_TEST(ret == c.begin() + 8);
}
{
Devector d; get_range<Devector>(8, d);
d.pop_front();
d.pop_front();
d.pop_front();
iterator origi_end = d.end();
iterator ret = d.insert(d.begin(), xb, xb+3);
const int expected [] = {9, 10, 11, 4, 5, 6, 7, 8};
test_equal_range(d, expected);
BOOST_TEST(origi_end == d.end());
BOOST_TEST(ret == d.begin());
}
{
Devector e; get_range<Devector>(8, e);
e.pop_back();
e.pop_back();
e.pop_back();
iterator origi_begin = e.begin();
iterator ret = e.insert(e.end(), xb, xb+3);
const int expected [] = {1, 2, 3, 4, 5, 9, 10, 11};
test_equal_range(e, expected);
BOOST_TEST(origi_begin == e.begin());
BOOST_TEST(ret == e.begin() + 5);
}
{
Devector f; get_range<Devector>(8, f);
f.reset_alloc_stats();
f.pop_front();
f.pop_front();
f.pop_back();
f.pop_back();
iterator ret = f.insert(f.begin() + 2, xb, xb+4);
const int expected [] = {3, 4, 9, 10, 11, 12, 5, 6};
test_equal_range(f, expected);
BOOST_TEST(f.get_alloc_count() == 0u);
BOOST_TEST(ret == f.begin() + 2);
}
{
Devector g; get_range<Devector>(8, g);
g.reset_alloc_stats();
g.pop_front();
g.pop_front();
g.pop_back();
g.pop_back();
g.pop_back();
iterator ret = g.insert(g.begin() + 2, xb, xb+5);
const int expected [] = {3, 4, 9, 10, 11, 12, 13, 5};
test_equal_range(g, expected);
BOOST_TEST(g.get_alloc_count() == 0u);
BOOST_TEST(ret == g.begin() + 2);
}
{
Devector g; get_range<Devector>(8, g);
iterator ret = g.insert(g.begin() + 2, xb, xb+5);
const int expected [] = {1, 2, 9, 10, 11, 12, 13, 3, 4, 5, 6, 7, 8};
test_equal_range(g, expected);
BOOST_TEST(ret == g.begin() + 2);
}
{ // n == 0
Devector h; get_range<Devector>(8, h);
h.reset_alloc_stats();
iterator ret = h.insert(h.begin(), xb, xb);
BOOST_TEST(ret == h.begin());
ret = h.insert(h.begin() + 4, xb, xb);
BOOST_TEST(ret == h.begin() + 4);
ret = h.insert(h.end(), xb, xb);
BOOST_TEST(ret == h.end());
const int expected [] = {1, 2, 3, 4, 5, 6, 7, 8};
test_equal_range(h, expected);
BOOST_TEST(h.get_alloc_count() == 0u);
}
#ifndef BOOST_NO_EXCEPTIONS
if (! boost::move_detail::is_nothrow_copy_constructible<T>::value)
{
// insert at begin
{
Devector j; get_range<Devector>(4, j);
test_elem_throw::on_copy_after(3);
BOOST_TEST_THROWS(j.insert(j.begin(), xb, xb+4), test_exception);
test_elem_throw::do_not_throw();
}
// insert at end
{
Devector k; get_range<Devector>(4, k);
test_elem_throw::on_copy_after(3);
BOOST_TEST_THROWS(k.insert(k.end(), xb, xb+4), test_exception);
test_elem_throw::do_not_throw();
}
}
#endif //#ifndef BOOST_NO_EXCEPTIONS
}
template <class Devector> void test_insert_init_list()
{
#if !defined(BOOST_NO_CXX11_HDR_INITIALIZER_LIST)
typedef typename Devector::value_type T;
typedef typename Devector::iterator iterator;
{
Devector a;
iterator ret = a.insert(a.end(), {T(123), T(124), T(125), T(126), T(127)});
test_equal_range(a, {123, 124, 125, 126, 127});
BOOST_TEST(ret == a.begin());
}
{
Devector b; get_range<Devector>(8, b);
iterator ret = b.insert(b.begin(), {T(9), T(10), T(11)});
test_equal_range(b, {9, 10, 11, 1, 2, 3, 4, 5, 6, 7, 8});
BOOST_TEST(ret == b.begin());
}
{
Devector c; get_range<Devector>(8, c);
iterator ret = c.insert(c.end(), {T(9), T(10), T(11)});
test_equal_range(c, {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11});
BOOST_TEST(ret == c.begin() + 8);
}
{
Devector d; get_range<Devector>(8, d);
d.pop_front();
d.pop_front();
d.pop_front();
iterator origi_end = d.end();
iterator ret = d.insert(d.begin(), {T(9), T(10), T(11)});
test_equal_range(d, {9, 10, 11, 4, 5, 6, 7, 8});
BOOST_TEST(origi_end == d.end());
BOOST_TEST(ret == d.begin());
}
{
Devector e; get_range<Devector>(8, e);
e.pop_back();
e.pop_back();
e.pop_back();
iterator origi_begin = e.begin();
iterator ret = e.insert(e.end(), {T(9), T(10), T(11)});
test_equal_range(e, {1, 2, 3, 4, 5, 9, 10, 11});
BOOST_TEST(origi_begin == e.begin());
BOOST_TEST(ret == e.begin() + 5);
}
{
Devector f; get_range<Devector>(8, f);
f.reset_alloc_stats();
f.pop_front();
f.pop_front();
f.pop_back();
f.pop_back();
iterator ret = f.insert(f.begin() + 2, {T(9), T(10), T(11), T(12)});
test_equal_range(f, {3, 4, 9, 10, 11, 12, 5, 6});
BOOST_TEST(f.get_alloc_count() == 0u);
BOOST_TEST(ret == f.begin() + 2);
}
{
Devector g; get_range<Devector>(8, g);
g.reset_alloc_stats();
g.pop_front();
g.pop_front();
g.pop_back();
g.pop_back();
g.pop_back();
iterator ret = g.insert(g.begin() + 2, {T(9), T(10), T(11), T(12), T(13)});
test_equal_range(g, {3, 4, 9, 10, 11, 12, 13, 5});
BOOST_TEST(g.get_alloc_count() == 0u);
BOOST_TEST(ret == g.begin() + 2);
}
{
Devector g; get_range<Devector>(8, g);
iterator ret = g.insert(g.begin() + 2, {T(9), T(10), T(11), T(12), T(13)});
test_equal_range(g, {1, 2, 9, 10, 11, 12, 13, 3, 4, 5, 6, 7, 8});
BOOST_TEST(ret == g.begin() + 2);
}
#ifndef BOOST_NO_EXCEPTIONS
BOOST_IF_CONSTEXPR (! boost::move_detail::is_nothrow_copy_constructible<T>::value)
{
// insert at begin
{
Devector j; get_range<Devector>(4, j);
test_elem_throw::on_copy_after(3);
BOOST_TEST_THROWS(j.insert(j.begin(), {T(9), T(9), T(9), T(9), T(9)}), test_exception);
test_elem_throw::do_not_throw();
}
// insert at end
{
Devector k; get_range<Devector>(4, k);
test_elem_throw::on_copy_after(3);
BOOST_TEST_THROWS(k.insert(k.end(), {T(9), T(9), T(9), T(9), T(9)}), test_exception);
test_elem_throw::do_not_throw();
}
}
#endif //#ifndef BOOST_NO_EXCEPTIONS
#endif // #if !defined(BOOST_NO_CXX11_HDR_INITIALIZER_LIST)
}
template <class Devector> void test_erase()
{
typedef typename Devector::iterator iterator;
{
Devector a; get_range<Devector>(4, a);
iterator ret = a.erase(a.begin());
const int expected[] = {2, 3, 4};
test_equal_range(a, expected);
BOOST_TEST(ret == a.begin());
}
{
Devector b; get_range<Devector>(4, b);
iterator ret = b.erase(b.end() - 1);
const int expected[] = {1, 2, 3};
test_equal_range(b, expected);
BOOST_TEST(ret == b.end());
}
{
Devector c; get_range<Devector>(6, c);
iterator ret = c.erase(c.begin() + 2);
const int expected [] = {1, 2, 4, 5, 6};
test_equal_range(c, expected);
BOOST_TEST(ret == c.begin() + 2);
BOOST_TEST(c.front_free_capacity() > 0u);
}
{
Devector d; get_range<Devector>(6, d);
iterator ret = d.erase(d.begin() + 4);
const int expected [] = {1, 2, 3, 4, 6};
test_equal_range(d, expected);
BOOST_TEST(ret == d.begin() + 4);
BOOST_TEST(d.back_free_capacity() > 0u);
}
}
template <class Devector> void test_erase_range()
{
typedef typename Devector::iterator iterator;
{
Devector a; get_range<Devector>(4, a);
a.erase(a.end(), a.end());
a.erase(a.begin(), a.begin());
}
{
Devector b; get_range<Devector>(8, b);
iterator ret = b.erase(b.begin(), b.begin() + 2);
const int expected [] = {3, 4, 5, 6, 7, 8};
test_equal_range(b, expected);
BOOST_TEST(ret == b.begin());
BOOST_TEST(b.front_free_capacity() > 0u);
}
{
Devector c; get_range<Devector>(8, c);
iterator ret = c.erase(c.begin() + 1, c.begin() + 3);
const int expected [] = {1, 4, 5, 6, 7, 8};
test_equal_range(c, expected);
BOOST_TEST(ret == c.begin() + 1);
BOOST_TEST(c.front_free_capacity() > 0u);
}
{
Devector d; get_range<Devector>(8, d);
iterator ret = d.erase(d.end() - 2, d.end());
const int expected [] = {1, 2, 3, 4, 5, 6};
test_equal_range(d, expected);
BOOST_TEST(ret == d.end());
BOOST_TEST(d.back_free_capacity() > 0u);
}
{
Devector e; get_range<Devector>(8, e);
iterator ret = e.erase(e.end() - 3, e.end() - 1);
const int expected [] = {1, 2, 3, 4, 5, 8};
test_equal_range(e, expected);
BOOST_TEST(ret == e.end() - 1);
BOOST_TEST(e.back_free_capacity() > 0u);
}
{
Devector f; get_range<Devector>(8, f);
iterator ret = f.erase(f.begin(), f.end());
test_equal_range(f);
BOOST_TEST(ret == f.end());
}
}
template <class Devector> void test_swap()
{
using std::swap; // test if ADL works
// empty-empty
{
Devector a;
Devector b;
swap(a, b);
BOOST_TEST(a.empty());
BOOST_TEST(b.empty());
}
// empty-not empty
{
Devector a;
Devector b; get_range<Devector>(4, b);
swap(a, b);
const int expected [] = {1, 2, 3, 4};
{
BOOST_TEST(b.empty());
test_equal_range(a, expected);
}
swap(a, b);
{
BOOST_TEST(a.empty());
test_equal_range(b, expected);
}
}
// small-small / big-big
{
Devector a; get_range<Devector>(1, 5, 5, 7, a);
Devector b; get_range<Devector>(13, 15, 15, 19, b);
swap(a, b);
const int expected [] = {13, 14, 15, 16, 17, 18};
test_equal_range(a, expected);
const int expected2 [] = {1, 2, 3, 4, 5, 6};
test_equal_range(b, expected2);
swap(a, b);
const int expected3 [] = {13, 14, 15, 16, 17, 18};
test_equal_range(b, expected3);
const int expected4 [] = {1, 2, 3, 4, 5, 6};
test_equal_range(a, expected4);
}
// big-small + small-big
{
Devector a; get_range<Devector>(10, a);
Devector b; get_range<Devector>(9, 11, 11, 17, b);
swap(a, b);
const int expected [] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
test_equal_range(b, expected);
const int expected2 [] = {9, 10, 11, 12, 13, 14, 15, 16};
test_equal_range(a, expected2);
swap(a, b);
const int expected3 [] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
test_equal_range(a, expected3);
const int expected4 [] = {9, 10, 11, 12, 13, 14, 15, 16};
test_equal_range(b, expected4);
}
// self swap
{
Devector a; get_range<Devector>(10, a);
swap(a, a);
const int expected [] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
test_equal_range(a, expected);
}
// no overlap
{
Devector a; get_range<Devector>(1, 9, 0, 0, a);
Devector b; get_range<Devector>(0, 0, 11, 17, b);
a.pop_back();
a.pop_back();
b.pop_front();
b.pop_front();
swap(a, b);
const int expected [] = {13, 14, 15, 16};
test_equal_range(a, expected);
const int expected2 [] = {1, 2, 3, 4, 5, 6};
test_equal_range(b, expected2);
}
// big-big does not copy or move
{
Devector a; get_range<Devector>(32, a);
Devector b; get_range<Devector>(32, b);
boost::container::vector<int> c; get_range<boost::container::vector<int> >(32, c);
test_elem_throw::on_copy_after(1);
test_elem_throw::on_move_after(1);
swap(a, b);
test_elem_throw::do_not_throw();
test_equal_range(a, c);
test_equal_range(b, c);
}
}
template <class Devector> void test_clear()
{
{
Devector a;
a.clear();
BOOST_TEST(a.empty());
}
{
Devector a; get_range<Devector>(8, a);
typename Devector::size_type cp = a.capacity();
a.clear();
BOOST_TEST(a.empty());
BOOST_TEST(cp == a.capacity());
}
}
template <class Devector> void test_op_eq()
{
{ // equal
Devector a; get_range<Devector>(8, a);
Devector b; get_range<Devector>(8, b);
BOOST_TEST(a == b);
}
{ // diff size
Devector a; get_range<Devector>(8, a);
Devector b; get_range<Devector>(9, b);
BOOST_TEST(!(a == b));
}
{ // diff content
Devector a; get_range<Devector>(8, a);
Devector b; get_range<Devector>(2,6,6,10, b);
BOOST_TEST(!(a == b));
}
}
template <class Devector> void test_op_lt()
{
{ // little than
Devector a; get_range<Devector>(7, a);
Devector b; get_range<Devector>(8, b);
BOOST_TEST((a < b));
}
{ // equal
Devector a; get_range<Devector>(8, a);
Devector b; get_range<Devector>(8, b);
BOOST_TEST(!(a < b));
}
{ // greater than
Devector a; get_range<Devector>(8, a);
Devector b; get_range<Devector>(7, b);
BOOST_TEST(!(a < b));
}
}
template <class Devector> void test_op_ne()
{
{ // equal
Devector a; get_range<Devector>(8, a);
Devector b; get_range<Devector>(8, b);
BOOST_TEST(!(a != b));
}
{ // diff size
Devector a; get_range<Devector>(8, a);
Devector b; get_range<Devector>(9, b);
BOOST_TEST((a != b));
}
{ // diff content
Devector a; get_range<Devector>(8, a);
Devector b; get_range<Devector>(2,6,6,10, b);
BOOST_TEST((a != b));
}
}
template <class Devector> void test_op_gt()
{
{ // little than
Devector a; get_range<Devector>(7, a);
Devector b; get_range<Devector>(8, b);
BOOST_TEST(!(a > b));
}
{ // equal
Devector a; get_range<Devector>(8, a);
Devector b; get_range<Devector>(8, b);
BOOST_TEST(!(a > b));
}
{ // greater than
Devector a; get_range<Devector>(8, a);
Devector b; get_range<Devector>(7, b);
BOOST_TEST((a > b));
}
}
template <class Devector> void test_op_ge()
{
{ // little than
Devector a; get_range<Devector>(7, a);
Devector b; get_range<Devector>(8, b);
BOOST_TEST(!(a >= b));
}
{ // equal
Devector a; get_range<Devector>(8, a);
Devector b; get_range<Devector>(8, b);
BOOST_TEST((a >= b));
}
{ // greater than
Devector a; get_range<Devector>(8, a);
Devector b; get_range<Devector>(7, b);
BOOST_TEST((a >= b));
}
}
template <class Devector> void test_op_le()
{
{ // little than
Devector a; get_range<Devector>(7, a);
Devector b; get_range<Devector>(8, b);
BOOST_TEST((a <= b));
}
{ // equal
Devector a; get_range<Devector>(8, a);
Devector b; get_range<Devector>(8, b);
BOOST_TEST((a <= b));
}
{ // greater than
Devector a; get_range<Devector>(8, a);
Devector b; get_range<Devector>(7, b);
BOOST_TEST(!(a <= b));
}
}
template <class Devector>
void test_devector_default_constructible(dtl::true_)
{
test_constructor_n<Devector>();
test_resize_front<Devector>();
test_resize_back<Devector>();
}
template <class Devector>
void test_devector_default_constructible(dtl::false_)
{}
template <class Devector>
void test_devector_copy_constructible(dtl::false_)
{}
template <class Devector>
void test_devector_copy_constructible(dtl::true_)
{
test_constructor_n_copy<Devector>();
test_constructor_input_range<Devector>();
test_constructor_forward_range<Devector>();
test_constructor_pointer_range<Devector>();
test_copy_constructor<Devector>();
test_assignment<Devector>();
test_assign_input_range<Devector>();
test_assign_pointer_range<Devector>();
test_assign_n<Devector>();
test_resize_front_copy<Devector>();
test_push_back<Devector>();
//test_unsafe_push_back<Devector>();
test_push_front<Devector>();
//test_unsafe_push_front<Devector>();
test_resize_back_copy<Devector>();
test_insert<Devector>();
test_insert_n<Devector>();
test_insert_input_range<Devector>();
test_insert_range<Devector>();
test_insert_init_list<Devector>();
}
template <class Devector>
void test_devector()
{
test_devector_default_constructible<Devector>(dtl::bool_<boost::is_default_constructible<typename Devector::value_type>::value>());
test_devector_copy_constructible<Devector>(dtl::bool_<boost::move_detail::is_copy_constructible<typename Devector::value_type>::value>());
test_constructor_default<Devector>();
test_constructor_allocator<Devector>();
test_constructor_reserve_only<Devector>();
test_constructor_reserve_only_front_back<Devector>();
//test_constructor_unsafe_uninitialized<Devector>();
test_move_constructor<Devector>();
test_destructor<Devector>();
test_move_assignment<Devector>();
test_get_allocator<Devector>();
test_begin_end<Devector>();
test_empty<Devector>();
test_size<Devector>();
test_capacity<Devector>();
//test_unsafe_uninitialized_resize_front<Devector>();
//test_unsafe_uninitialized_resize_back<Devector>();
test_reserve_front<Devector>();
test_reserve_back<Devector>();
test_index_operator<Devector>();
test_at<Devector>();
test_front<Devector>();
test_back<Devector>();
test_emplace_front<Devector>();
test_push_front_rvalue<Devector>();
//test_unsafe_push_front_rvalue<Devector>();
test_pop_front<Devector>();
test_emplace_back<Devector>();
test_push_back_rvalue<Devector>();
//test_unsafe_push_back_rvalue<Devector>();
test_pop_back<Devector>();
test_emplace<Devector>();
test_insert_rvalue<Devector>();
test_erase<Devector>();
test_erase_range<Devector>();
test_swap<Devector>();
test_clear<Devector>();
test_op_eq<Devector>();
test_op_lt<Devector>();
test_op_ne<Devector>();
test_op_gt<Devector>();
test_op_ge<Devector>();
test_op_le<Devector>();
}
class recursive_devector
{
public:
recursive_devector(const recursive_devector &x)
: devector_(x.devector_)
{}
recursive_devector & operator=(const recursive_devector &x)
{ this->devector_ = x.devector_; return *this; }
int id_;
devector<recursive_devector> devector_;
devector<recursive_devector>::iterator it_;
devector<recursive_devector>::const_iterator cit_;
devector<recursive_devector>::reverse_iterator rit_;
devector<recursive_devector>::const_reverse_iterator crit_;
};
void test_recursive_devector()//Test for recursive types
{
devector<recursive_devector> rdv;
BOOST_TEST(rdv.empty());
BOOST_TEST(rdv.get_alloc_count() == 0u);
BOOST_TEST(rdv.capacity() == 0u);
}
template<class VoidAllocator>
struct GetAllocatorCont
{
template<class ValueType>
struct apply
{
typedef vector< ValueType
, typename allocator_traits<VoidAllocator>
::template portable_rebind_alloc<ValueType>::type
> type;
};
};
#ifdef _MSC_VER
#pragma warning (pop)
#endif
void test_all()
{/*
test_recursive_devector();
test_max_size();
test_exceeding_max_size();
shrink_to_fit();
test_data();
test_il_assignment< devector<int> >();
test_assign_forward_range< devector<int> >();
test_assign_il<devector<int> >();
*/
//test_devector< devector<int> >();
test_devector< devector<regular_elem> >();
test_devector< devector<noex_move> >();
test_devector< devector<noex_copy> >();
test_devector< devector<only_movable> >();
test_devector< devector<no_default_ctor> >();
////////////////////////////////////
// Allocator propagation testing
////////////////////////////////////
(void)boost::container::test::test_propagate_allocator<boost_container_devector>();
}
boost::container::vector<only_movable> getom()
{
typedef boost::container::vector<only_movable> V;
V v;
return BOOST_MOVE_RET(V, v);
}
boost::container::vector<boost::container::test::movable_int> get()
{
typedef boost::container::vector<boost::container::test::movable_int> V;
V v;
return BOOST_MOVE_RET(V, v);
}
int main()
{
// boost::container::vector<boost::container::test::movable_int>a(get());
//boost::container::vector<only_movable> b(getom());
//boost::container::vector<only_movable> c(get_range< boost::container::vector<only_movable> >(1, 5, 5, 9));
test_all();
return boost::report_errors();
}