• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 //////////////////////////////////////////////////////////////////////////////
2 //
3 // \(C\) Copyright Benedek Thaler 2015-2016
4 // \(C\) Copyright Ion Gaztanaga 2019-2020. Distributed under the Boost
5 // Software License, Version 1.0. (See accompanying file
6 // LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
7 //
8 // See http://erenon.hu/double_ended for documentation.
9 //
10 //////////////////////////////////////////////////////////////////////////////
11 
12 #ifndef BOOST_CONTAINER_TEST_TEST_ELEM_HPP
13 #define BOOST_CONTAINER_TEST_TEST_ELEM_HPP
14 
15 #include <boost/utility/compare_pointees.hpp>
16 #include <cstdlib>
17 
18 namespace boost {
19 namespace container {
20 
21 struct test_exception {};
22 
23 struct test_elem_throw
24 {
25    private:
26    static int throw_on_ctor_after /*= -1*/;
27    static int throw_on_copy_after /*= -1*/;
28    static int throw_on_move_after /*= -1*/;
29 
30    public:
on_ctor_afterboost::container::test_elem_throw31    static void on_ctor_after(int x) { throw_on_ctor_after = x; }
on_copy_afterboost::container::test_elem_throw32    static void on_copy_after(int x) { throw_on_copy_after = x; }
on_move_afterboost::container::test_elem_throw33    static void on_move_after(int x) { throw_on_move_after = x; }
34 
do_not_throwboost::container::test_elem_throw35    static void do_not_throw()
36    {
37       throw_on_ctor_after = -1;
38       throw_on_copy_after = -1;
39       throw_on_move_after = -1;
40    }
41 
in_constructorboost::container::test_elem_throw42    static void in_constructor() { maybe_throw(throw_on_ctor_after); }
in_copyboost::container::test_elem_throw43    static void in_copy() { maybe_throw(throw_on_copy_after); }
in_moveboost::container::test_elem_throw44    static void in_move() { maybe_throw(throw_on_move_after); }
45 
46    private:
maybe_throwboost::container::test_elem_throw47    static void maybe_throw(int& counter)
48    {
49       if (counter > 0)
50       {
51       --counter;
52       if (counter == 0)
53       {
54          --counter;
55          #ifndef BOOST_NO_EXCEPTIONS
56          throw test_exception();
57          #else
58          std::abort();
59          #endif
60       }
61       }
62    }
63 };
64 
65 int test_elem_throw::throw_on_ctor_after = -1;
66 int test_elem_throw::throw_on_copy_after = -1;
67 int test_elem_throw::throw_on_move_after = -1;
68 
69 struct test_elem_base
70 {
71    private:
72    BOOST_COPYABLE_AND_MOVABLE(test_elem_base)
73 
74    public:
test_elem_baseboost::container::test_elem_base75    test_elem_base()
76    {
77       test_elem_throw::in_constructor();
78       _index = new int(0);
79       ++_live_count;
80    }
81 
test_elem_baseboost::container::test_elem_base82    test_elem_base(int index)
83    {
84       test_elem_throw::in_constructor();
85       _index = new int(index);
86       ++_live_count;
87    }
88 
test_elem_baseboost::container::test_elem_base89    explicit test_elem_base(const test_elem_base& rhs)
90    {
91       test_elem_throw::in_copy();
92       _index = new int(*rhs._index);
93       ++_live_count;
94    }
95 
test_elem_baseboost::container::test_elem_base96    test_elem_base(BOOST_RV_REF(test_elem_base) rhs)
97    {
98       test_elem_throw::in_move();
99       _index = rhs._index;
100       rhs._index = 0;
101       ++_live_count;
102    }
103 
operator =boost::container::test_elem_base104    test_elem_base &operator=(BOOST_COPY_ASSIGN_REF(test_elem_base) rhs)
105    {
106       test_elem_throw::in_copy();
107       if (_index) { delete _index; }
108       _index = new int(*rhs._index);
109       return *this;
110    }
111 
operator =boost::container::test_elem_base112    test_elem_base &operator=(BOOST_RV_REF(test_elem_base) rhs)
113    {
114       test_elem_throw::in_move();
115       if (_index) { delete _index; }
116       _index = rhs._index;
117       rhs._index = 0;
118       return *this;
119    }
120 
~test_elem_baseboost::container::test_elem_base121    ~test_elem_base()
122    {
123       if (_index) { delete _index; }
124       --_live_count;
125    }
126 
operator ==(const test_elem_base & a,const test_elem_base & b)127    friend bool operator==(const test_elem_base& a, const test_elem_base& b)
128    {
129       return a._index && b._index && *(a._index) == *(b._index);
130    }
131 
operator ==(int a,const test_elem_base & b)132    friend bool operator==(int a, const test_elem_base& b)
133    {
134       return b._index != 0 && a == *(b._index);
135    }
136 
operator ==(const test_elem_base & a,int b)137    friend bool operator==(const test_elem_base& a, int b)
138    {
139       return a._index != 0 && *(a._index) == b;
140    }
141 
operator <(const test_elem_base & a,const test_elem_base & b)142    friend bool operator<(const test_elem_base& a, const test_elem_base& b)
143    {
144       return boost::less_pointees(a._index, b._index);
145    }
146 
operator <<(std::ostream & out,const test_elem_base & elem)147    friend std::ostream& operator<<(std::ostream& out, const test_elem_base& elem)
148    {
149       if (elem._index) { out << *elem._index; }
150       else { out << "null"; }
151       return out;
152    }
153 
154    template <typename Archive>
serializeboost::container::test_elem_base155    void serialize(Archive& ar, unsigned /* version */)
156    {
157       ar & *_index;
158    }
159 
no_living_elemboost::container::test_elem_base160    static bool no_living_elem()
161    {
162       return _live_count == 0;
163    }
164 
165    private:
166    int* _index;
167 
168    static int _live_count;
169 };
170 
171 int test_elem_base::_live_count = 0;
172 
173 struct regular_elem : test_elem_base
174 {
175    private:
176    BOOST_COPYABLE_AND_MOVABLE(regular_elem)
177 
178    public:
regular_elemboost::container::regular_elem179    regular_elem()
180    {}
181 
regular_elemboost::container::regular_elem182    regular_elem(int index) : test_elem_base(index) {}
183 
regular_elemboost::container::regular_elem184    regular_elem(const regular_elem& rhs)
185       :test_elem_base(rhs)
186    {}
187 
regular_elemboost::container::regular_elem188    regular_elem(BOOST_RV_REF(regular_elem) rhs)
189       :test_elem_base(BOOST_MOVE_BASE(test_elem_base, rhs))
190    {}
191 
operator =boost::container::regular_elem192    regular_elem &operator=(BOOST_COPY_ASSIGN_REF(regular_elem) rhs)
193    {
194       static_cast<test_elem_base&>(*this) = rhs;
195       return *this;
196    }
197 
operator =boost::container::regular_elem198    regular_elem &operator=(BOOST_RV_REF(regular_elem) rhs)
199    {
200       regular_elem &r = rhs;
201       static_cast<test_elem_base&>(*this) = boost::move(r);
202       return *this;
203    }
204 };
205 
206 struct noex_move : test_elem_base
207 {
208    private:
209    BOOST_COPYABLE_AND_MOVABLE(noex_move)
210 
211    public:
noex_moveboost::container::noex_move212    noex_move()
213    {}
214 
noex_moveboost::container::noex_move215    noex_move(int index) : test_elem_base(index) {}
216 
noex_moveboost::container::noex_move217    noex_move(const noex_move& rhs)
218       :test_elem_base(rhs)
219    {}
220 
noex_moveboost::container::noex_move221    noex_move(BOOST_RV_REF(noex_move) rhs) BOOST_NOEXCEPT
222       :test_elem_base(BOOST_MOVE_BASE(test_elem_base, rhs))
223    {}
224 
operator =boost::container::noex_move225    noex_move &operator=(BOOST_COPY_ASSIGN_REF(noex_move) rhs)
226    {
227       static_cast<test_elem_base&>(*this) = rhs;
228       return *this;
229    }
230 
operator =boost::container::noex_move231    noex_move &operator=(BOOST_RV_REF(noex_move) rhs) BOOST_NOEXCEPT
232    {
233       noex_move & r = rhs;
234       static_cast<test_elem_base&>(*this) = boost::move(r);
235       return *this;
236    }
237 };
238 
239 struct noex_copy : test_elem_base
240 {
241    private:
242    BOOST_COPYABLE_AND_MOVABLE(noex_copy)
243 
244    public:
noex_copyboost::container::noex_copy245    noex_copy(){}
246 
noex_copyboost::container::noex_copy247    noex_copy(int index) : test_elem_base(index) {}
248 
noex_copyboost::container::noex_copy249    noex_copy(const noex_copy& rhs) BOOST_NOEXCEPT
250       :test_elem_base(rhs)
251    {}
252 
noex_copyboost::container::noex_copy253    noex_copy(BOOST_RV_REF(noex_copy) rhs)
254       :test_elem_base(BOOST_MOVE_BASE(test_elem_base, rhs))
255    {}
256 
operator =boost::container::noex_copy257    noex_copy &operator=(BOOST_COPY_ASSIGN_REF(noex_copy) rhs) BOOST_NOEXCEPT
258    {
259       static_cast<test_elem_base&>(*this) = rhs;
260       return *this;
261    }
262 
operator =boost::container::noex_copy263    noex_copy &operator=(BOOST_RV_REF(noex_copy) rhs)
264    {
265       noex_copy &r = rhs;
266       static_cast<test_elem_base&>(*this) = boost::move(r);
267       return *this;
268    }
269 };
270 
271 struct only_movable : test_elem_base
272 {
273    private:
274    BOOST_MOVABLE_BUT_NOT_COPYABLE(only_movable)
275 
276    public:
only_movableboost::container::only_movable277    only_movable(){};
278 
only_movableboost::container::only_movable279    only_movable(int index) : test_elem_base(index) {}
280 
only_movableboost::container::only_movable281    only_movable(BOOST_RV_REF(only_movable) rhs)
282       :test_elem_base(BOOST_MOVE_BASE(test_elem_base, rhs))
283    {}
284 
operator =boost::container::only_movable285    only_movable &operator=(BOOST_RV_REF(only_movable) rhs)
286    {
287       static_cast<test_elem_base&>(*this) = boost::move(rhs);
288       return *this;
289    }
290 };
291 
292 struct no_default_ctor : test_elem_base
293 {
294 
295    private:
296    BOOST_COPYABLE_AND_MOVABLE(no_default_ctor)
297 
298    public:
no_default_ctorboost::container::no_default_ctor299    no_default_ctor(int index) : test_elem_base(index) {}
300 
no_default_ctorboost::container::no_default_ctor301    no_default_ctor(const no_default_ctor& rhs)
302       :test_elem_base(rhs)
303    {}
304 
no_default_ctorboost::container::no_default_ctor305    no_default_ctor(BOOST_RV_REF(no_default_ctor) rhs)
306       :test_elem_base(BOOST_MOVE_BASE(test_elem_base, rhs))
307    {}
308 
operator =boost::container::no_default_ctor309   no_default_ctor &operator=(BOOST_RV_REF(no_default_ctor) rhs)
310   {
311       static_cast<test_elem_base&>(*this) = boost::move(rhs);
312       return *this;
313   }
314 
operator =boost::container::no_default_ctor315   no_default_ctor &operator=(BOOST_COPY_ASSIGN_REF(no_default_ctor) rhs)
316   {
317       static_cast<test_elem_base&>(*this) = rhs;
318       return *this;
319   }
320 };
321 
322 }}
323 
324 #endif   //BOOST_CONTAINER_TEST_TEST_ELEM_HPP
325