324 lines
7.2 KiB
C++
Executable file
324 lines
7.2 KiB
C++
Executable file
//////////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// \(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://erenon.hu/double_ended for documentation.
|
|
//
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
|
|
#ifndef BOOST_CONTAINER_TEST_TEST_ELEM_HPP
|
|
#define BOOST_CONTAINER_TEST_TEST_ELEM_HPP
|
|
|
|
#include <boost/utility/compare_pointees.hpp>
|
|
#include <cstdlib>
|
|
|
|
namespace boost {
|
|
namespace container {
|
|
|
|
struct test_exception {};
|
|
|
|
struct test_elem_throw
|
|
{
|
|
private:
|
|
static int throw_on_ctor_after /*= -1*/;
|
|
static int throw_on_copy_after /*= -1*/;
|
|
static int throw_on_move_after /*= -1*/;
|
|
|
|
public:
|
|
static void on_ctor_after(int x) { throw_on_ctor_after = x; }
|
|
static void on_copy_after(int x) { throw_on_copy_after = x; }
|
|
static void on_move_after(int x) { throw_on_move_after = x; }
|
|
|
|
static void do_not_throw()
|
|
{
|
|
throw_on_ctor_after = -1;
|
|
throw_on_copy_after = -1;
|
|
throw_on_move_after = -1;
|
|
}
|
|
|
|
static void in_constructor() { maybe_throw(throw_on_ctor_after); }
|
|
static void in_copy() { maybe_throw(throw_on_copy_after); }
|
|
static void in_move() { maybe_throw(throw_on_move_after); }
|
|
|
|
private:
|
|
static void maybe_throw(int& counter)
|
|
{
|
|
if (counter > 0)
|
|
{
|
|
--counter;
|
|
if (counter == 0)
|
|
{
|
|
--counter;
|
|
#ifndef BOOST_NO_EXCEPTIONS
|
|
throw test_exception();
|
|
#else
|
|
std::abort();
|
|
#endif
|
|
}
|
|
}
|
|
}
|
|
};
|
|
|
|
int test_elem_throw::throw_on_ctor_after = -1;
|
|
int test_elem_throw::throw_on_copy_after = -1;
|
|
int test_elem_throw::throw_on_move_after = -1;
|
|
|
|
struct test_elem_base
|
|
{
|
|
private:
|
|
BOOST_COPYABLE_AND_MOVABLE(test_elem_base)
|
|
|
|
public:
|
|
test_elem_base()
|
|
{
|
|
test_elem_throw::in_constructor();
|
|
_index = new int(0);
|
|
++_live_count;
|
|
}
|
|
|
|
test_elem_base(int index)
|
|
{
|
|
test_elem_throw::in_constructor();
|
|
_index = new int(index);
|
|
++_live_count;
|
|
}
|
|
|
|
explicit test_elem_base(const test_elem_base& rhs)
|
|
{
|
|
test_elem_throw::in_copy();
|
|
_index = new int(*rhs._index);
|
|
++_live_count;
|
|
}
|
|
|
|
test_elem_base(BOOST_RV_REF(test_elem_base) rhs)
|
|
{
|
|
test_elem_throw::in_move();
|
|
_index = rhs._index;
|
|
rhs._index = 0;
|
|
++_live_count;
|
|
}
|
|
|
|
test_elem_base &operator=(BOOST_COPY_ASSIGN_REF(test_elem_base) rhs)
|
|
{
|
|
test_elem_throw::in_copy();
|
|
if (_index) { delete _index; }
|
|
_index = new int(*rhs._index);
|
|
return *this;
|
|
}
|
|
|
|
test_elem_base &operator=(BOOST_RV_REF(test_elem_base) rhs)
|
|
{
|
|
test_elem_throw::in_move();
|
|
if (_index) { delete _index; }
|
|
_index = rhs._index;
|
|
rhs._index = 0;
|
|
return *this;
|
|
}
|
|
|
|
~test_elem_base()
|
|
{
|
|
if (_index) { delete _index; }
|
|
--_live_count;
|
|
}
|
|
|
|
friend bool operator==(const test_elem_base& a, const test_elem_base& b)
|
|
{
|
|
return a._index && b._index && *(a._index) == *(b._index);
|
|
}
|
|
|
|
friend bool operator==(int a, const test_elem_base& b)
|
|
{
|
|
return b._index != 0 && a == *(b._index);
|
|
}
|
|
|
|
friend bool operator==(const test_elem_base& a, int b)
|
|
{
|
|
return a._index != 0 && *(a._index) == b;
|
|
}
|
|
|
|
friend bool operator<(const test_elem_base& a, const test_elem_base& b)
|
|
{
|
|
return boost::less_pointees(a._index, b._index);
|
|
}
|
|
|
|
friend std::ostream& operator<<(std::ostream& out, const test_elem_base& elem)
|
|
{
|
|
if (elem._index) { out << *elem._index; }
|
|
else { out << "null"; }
|
|
return out;
|
|
}
|
|
|
|
template <typename Archive>
|
|
void serialize(Archive& ar, unsigned /* version */)
|
|
{
|
|
ar & *_index;
|
|
}
|
|
|
|
static bool no_living_elem()
|
|
{
|
|
return _live_count == 0;
|
|
}
|
|
|
|
private:
|
|
int* _index;
|
|
|
|
static int _live_count;
|
|
};
|
|
|
|
int test_elem_base::_live_count = 0;
|
|
|
|
struct regular_elem : test_elem_base
|
|
{
|
|
private:
|
|
BOOST_COPYABLE_AND_MOVABLE(regular_elem)
|
|
|
|
public:
|
|
regular_elem()
|
|
{}
|
|
|
|
regular_elem(int index) : test_elem_base(index) {}
|
|
|
|
regular_elem(const regular_elem& rhs)
|
|
:test_elem_base(rhs)
|
|
{}
|
|
|
|
regular_elem(BOOST_RV_REF(regular_elem) rhs)
|
|
:test_elem_base(BOOST_MOVE_BASE(test_elem_base, rhs))
|
|
{}
|
|
|
|
regular_elem &operator=(BOOST_COPY_ASSIGN_REF(regular_elem) rhs)
|
|
{
|
|
static_cast<test_elem_base&>(*this) = rhs;
|
|
return *this;
|
|
}
|
|
|
|
regular_elem &operator=(BOOST_RV_REF(regular_elem) rhs)
|
|
{
|
|
regular_elem &r = rhs;
|
|
static_cast<test_elem_base&>(*this) = boost::move(r);
|
|
return *this;
|
|
}
|
|
};
|
|
|
|
struct noex_move : test_elem_base
|
|
{
|
|
private:
|
|
BOOST_COPYABLE_AND_MOVABLE(noex_move)
|
|
|
|
public:
|
|
noex_move()
|
|
{}
|
|
|
|
noex_move(int index) : test_elem_base(index) {}
|
|
|
|
noex_move(const noex_move& rhs)
|
|
:test_elem_base(rhs)
|
|
{}
|
|
|
|
noex_move(BOOST_RV_REF(noex_move) rhs) BOOST_NOEXCEPT
|
|
:test_elem_base(BOOST_MOVE_BASE(test_elem_base, rhs))
|
|
{}
|
|
|
|
noex_move &operator=(BOOST_COPY_ASSIGN_REF(noex_move) rhs)
|
|
{
|
|
static_cast<test_elem_base&>(*this) = rhs;
|
|
return *this;
|
|
}
|
|
|
|
noex_move &operator=(BOOST_RV_REF(noex_move) rhs) BOOST_NOEXCEPT
|
|
{
|
|
noex_move & r = rhs;
|
|
static_cast<test_elem_base&>(*this) = boost::move(r);
|
|
return *this;
|
|
}
|
|
};
|
|
|
|
struct noex_copy : test_elem_base
|
|
{
|
|
private:
|
|
BOOST_COPYABLE_AND_MOVABLE(noex_copy)
|
|
|
|
public:
|
|
noex_copy(){}
|
|
|
|
noex_copy(int index) : test_elem_base(index) {}
|
|
|
|
noex_copy(const noex_copy& rhs) BOOST_NOEXCEPT
|
|
:test_elem_base(rhs)
|
|
{}
|
|
|
|
noex_copy(BOOST_RV_REF(noex_copy) rhs)
|
|
:test_elem_base(BOOST_MOVE_BASE(test_elem_base, rhs))
|
|
{}
|
|
|
|
noex_copy &operator=(BOOST_COPY_ASSIGN_REF(noex_copy) rhs) BOOST_NOEXCEPT
|
|
{
|
|
static_cast<test_elem_base&>(*this) = rhs;
|
|
return *this;
|
|
}
|
|
|
|
noex_copy &operator=(BOOST_RV_REF(noex_copy) rhs)
|
|
{
|
|
noex_copy &r = rhs;
|
|
static_cast<test_elem_base&>(*this) = boost::move(r);
|
|
return *this;
|
|
}
|
|
};
|
|
|
|
struct only_movable : test_elem_base
|
|
{
|
|
private:
|
|
BOOST_MOVABLE_BUT_NOT_COPYABLE(only_movable)
|
|
|
|
public:
|
|
only_movable(){};
|
|
|
|
only_movable(int index) : test_elem_base(index) {}
|
|
|
|
only_movable(BOOST_RV_REF(only_movable) rhs)
|
|
:test_elem_base(BOOST_MOVE_BASE(test_elem_base, rhs))
|
|
{}
|
|
|
|
only_movable &operator=(BOOST_RV_REF(only_movable) rhs)
|
|
{
|
|
static_cast<test_elem_base&>(*this) = boost::move(rhs);
|
|
return *this;
|
|
}
|
|
};
|
|
|
|
struct no_default_ctor : test_elem_base
|
|
{
|
|
|
|
private:
|
|
BOOST_COPYABLE_AND_MOVABLE(no_default_ctor)
|
|
|
|
public:
|
|
no_default_ctor(int index) : test_elem_base(index) {}
|
|
|
|
no_default_ctor(const no_default_ctor& rhs)
|
|
:test_elem_base(rhs)
|
|
{}
|
|
|
|
no_default_ctor(BOOST_RV_REF(no_default_ctor) rhs)
|
|
:test_elem_base(BOOST_MOVE_BASE(test_elem_base, rhs))
|
|
{}
|
|
|
|
no_default_ctor &operator=(BOOST_RV_REF(no_default_ctor) rhs)
|
|
{
|
|
static_cast<test_elem_base&>(*this) = boost::move(rhs);
|
|
return *this;
|
|
}
|
|
|
|
no_default_ctor &operator=(BOOST_COPY_ASSIGN_REF(no_default_ctor) rhs)
|
|
{
|
|
static_cast<test_elem_base&>(*this) = rhs;
|
|
return *this;
|
|
}
|
|
};
|
|
|
|
}}
|
|
|
|
#endif //BOOST_CONTAINER_TEST_TEST_ELEM_HPP
|