1 | ////////////////////////////////////////////////////////////////////////////// |
2 | // |
3 | // (C) Copyright Ion Gaztanaga 2015-2015. Distributed under the Boost |
4 | // Software License, Version 1.0. (See accompanying file |
5 | // LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) |
6 | // |
7 | // See http://www.boost.org/libs/container for documentation. |
8 | // |
9 | ////////////////////////////////////////////////////////////////////////////// |
10 | |
11 | #ifndef BOOST_CONTAINER_TEST_ALLOCATOR_ARGUMENT_TESTER_HPP |
12 | #define BOOST_CONTAINER_TEST_ALLOCATOR_ARGUMENT_TESTER_HPP |
13 | |
14 | #include <boost/container/uses_allocator.hpp> |
15 | #include <boost/container/detail/mpl.hpp> |
16 | #include <boost/move/core.hpp> |
17 | #include <boost/move/detail/force_ptr.hpp> |
18 | |
19 | template<class T, unsigned int Id, bool HasTrueTypes = false> |
20 | class propagation_test_allocator |
21 | { |
22 | BOOST_COPYABLE_AND_MOVABLE(propagation_test_allocator) |
23 | public: |
24 | |
25 | template<class U> |
26 | struct rebind |
27 | { |
28 | typedef propagation_test_allocator<U, Id, HasTrueTypes> other; |
29 | }; |
30 | |
31 | typedef boost::container::dtl::bool_<HasTrueTypes> propagate_on_container_copy_assignment; |
32 | typedef boost::container::dtl::bool_<HasTrueTypes> propagate_on_container_move_assignment; |
33 | typedef boost::container::dtl::bool_<HasTrueTypes> propagate_on_container_swap; |
34 | typedef boost::container::dtl::bool_<HasTrueTypes> is_always_equal; |
35 | typedef T value_type; |
36 | |
37 | propagation_test_allocator() |
38 | : m_move_contructed(false), m_move_assigned(false) |
39 | {} |
40 | |
41 | propagation_test_allocator(const propagation_test_allocator&) |
42 | : m_move_contructed(false), m_move_assigned(false) |
43 | {} |
44 | |
45 | propagation_test_allocator(BOOST_RV_REF(propagation_test_allocator) ) |
46 | : m_move_contructed(true), m_move_assigned(false) |
47 | {} |
48 | |
49 | template<class U> |
50 | propagation_test_allocator(BOOST_RV_REF_BEG propagation_test_allocator<U, Id, HasTrueTypes> BOOST_RV_REF_END) |
51 | : m_move_contructed(true), m_move_assigned(false) |
52 | {} |
53 | |
54 | template<class U> |
55 | propagation_test_allocator(const propagation_test_allocator<U, Id, HasTrueTypes> &) |
56 | {} |
57 | |
58 | propagation_test_allocator & operator=(BOOST_COPY_ASSIGN_REF(propagation_test_allocator)) |
59 | { |
60 | return *this; |
61 | } |
62 | |
63 | propagation_test_allocator & operator=(BOOST_RV_REF(propagation_test_allocator)) |
64 | { |
65 | m_move_assigned = true; |
66 | return *this; |
67 | } |
68 | |
69 | std::size_t max_size() const |
70 | { return std::size_t(-1); } |
71 | |
72 | T* allocate(std::size_t n) |
73 | { return boost::move_detail::force_ptr<T*>(::new char[n*sizeof(T)]); } |
74 | |
75 | void deallocate(T*p, std::size_t) |
76 | { delete []static_cast<char*>(static_cast<void*>(p)); } |
77 | |
78 | bool m_move_contructed; |
79 | bool m_move_assigned; |
80 | }; |
81 | |
82 | template <class T1, class T2, unsigned int Id, bool HasTrueTypes> |
83 | bool operator==( const propagation_test_allocator<T1, Id, HasTrueTypes>& |
84 | , const propagation_test_allocator<T2, Id, HasTrueTypes>&) |
85 | { return true; } |
86 | |
87 | template <class T1, class T2, unsigned int Id, bool HasTrueTypes> |
88 | bool operator!=( const propagation_test_allocator<T1, Id, HasTrueTypes>& |
89 | , const propagation_test_allocator<T2, Id, HasTrueTypes>&) |
90 | { return false; } |
91 | |
92 | //This enum lists the construction options |
93 | //for an allocator-aware type |
94 | enum ConstructionTypeEnum |
95 | { |
96 | ConstructiblePrefix, |
97 | ConstructibleSuffix, |
98 | NotUsesAllocator |
99 | }; |
100 | |
101 | //This base class provices types for |
102 | //the derived class to implement each construction |
103 | //type. If a construction type does not apply |
104 | //the typedef is set to an internal nat |
105 | //so that the class is not constructible from |
106 | //the user arguments. |
107 | template<ConstructionTypeEnum ConstructionType, unsigned int AllocatorTag> |
108 | struct uses_allocator_base; |
109 | |
110 | template<unsigned int AllocatorTag> |
111 | struct uses_allocator_base<ConstructibleSuffix, AllocatorTag> |
112 | { |
113 | typedef propagation_test_allocator<int, AllocatorTag> allocator_type; |
114 | typedef allocator_type allocator_constructor_type; |
115 | struct nat{}; |
116 | typedef nat allocator_arg_type; |
117 | }; |
118 | |
119 | template<unsigned int AllocatorTag> |
120 | struct uses_allocator_base<ConstructiblePrefix, AllocatorTag> |
121 | { |
122 | typedef propagation_test_allocator<int, AllocatorTag> allocator_type; |
123 | typedef allocator_type allocator_constructor_type; |
124 | typedef boost::container::allocator_arg_t allocator_arg_type; |
125 | }; |
126 | |
127 | template<unsigned int AllocatorTag> |
128 | struct uses_allocator_base<NotUsesAllocator, AllocatorTag> |
129 | { |
130 | struct nat{}; |
131 | typedef nat allocator_constructor_type; |
132 | typedef nat allocator_arg_type; |
133 | }; |
134 | |
135 | template<ConstructionTypeEnum ConstructionType, unsigned int AllocatorTag> |
136 | struct allocator_argument_tester |
137 | : uses_allocator_base<ConstructionType, AllocatorTag> |
138 | { |
139 | private: |
140 | BOOST_COPYABLE_AND_MOVABLE(allocator_argument_tester) |
141 | |
142 | public: |
143 | |
144 | typedef uses_allocator_base<ConstructionType, AllocatorTag> base_type; |
145 | |
146 | //0 user argument constructors |
147 | allocator_argument_tester() |
148 | : construction_type(NotUsesAllocator), value(0) |
149 | {} |
150 | |
151 | explicit allocator_argument_tester |
152 | (typename base_type::allocator_constructor_type) |
153 | : construction_type(ConstructibleSuffix), value(0) |
154 | {} |
155 | |
156 | explicit allocator_argument_tester |
157 | (typename base_type::allocator_arg_type, typename base_type::allocator_constructor_type) |
158 | : construction_type(ConstructiblePrefix), value(0) |
159 | {} |
160 | |
161 | //1 user argument constructors |
162 | explicit allocator_argument_tester(int i) |
163 | : construction_type(NotUsesAllocator), value(i) |
164 | {} |
165 | |
166 | allocator_argument_tester |
167 | (int i, typename base_type::allocator_constructor_type) |
168 | : construction_type(ConstructibleSuffix), value(i) |
169 | {} |
170 | |
171 | allocator_argument_tester |
172 | ( typename base_type::allocator_arg_type |
173 | , typename base_type::allocator_constructor_type |
174 | , int i) |
175 | : construction_type(ConstructiblePrefix), value(i) |
176 | {} |
177 | |
178 | //Copy constructors |
179 | allocator_argument_tester(const allocator_argument_tester &other) |
180 | : construction_type(NotUsesAllocator), value(other.value) |
181 | {} |
182 | |
183 | allocator_argument_tester( const allocator_argument_tester &other |
184 | , typename base_type::allocator_constructor_type) |
185 | : construction_type(ConstructibleSuffix), value(other.value) |
186 | {} |
187 | |
188 | allocator_argument_tester( typename base_type::allocator_arg_type |
189 | , typename base_type::allocator_constructor_type |
190 | , const allocator_argument_tester &other) |
191 | : construction_type(ConstructiblePrefix), value(other.value) |
192 | {} |
193 | |
194 | //Move constructors |
195 | allocator_argument_tester(BOOST_RV_REF(allocator_argument_tester) other) |
196 | : construction_type(NotUsesAllocator), value(((allocator_argument_tester &)other).value) |
197 | { |
198 | allocator_argument_tester &o = other; |
199 | o.value = 0; |
200 | o.construction_type = NotUsesAllocator; |
201 | } |
202 | |
203 | allocator_argument_tester( BOOST_RV_REF(allocator_argument_tester) other |
204 | , typename base_type::allocator_constructor_type) |
205 | : construction_type(ConstructibleSuffix), value(((allocator_argument_tester &)other).value) |
206 | { |
207 | allocator_argument_tester &o = other; |
208 | o.value = 0; |
209 | o.construction_type = ConstructibleSuffix; |
210 | } |
211 | |
212 | allocator_argument_tester( typename base_type::allocator_arg_type |
213 | , typename base_type::allocator_constructor_type |
214 | , BOOST_RV_REF(allocator_argument_tester) other) |
215 | : construction_type(ConstructiblePrefix), value(((allocator_argument_tester &)other).value) |
216 | { |
217 | allocator_argument_tester &o = other; |
218 | o.value = 0; |
219 | o.construction_type = ConstructiblePrefix; |
220 | } |
221 | |
222 | ConstructionTypeEnum construction_type; |
223 | int value; |
224 | }; |
225 | |
226 | namespace boost { |
227 | namespace container { |
228 | |
229 | template<unsigned int AllocatorTag> |
230 | struct constructible_with_allocator_prefix |
231 | < ::allocator_argument_tester<ConstructiblePrefix, AllocatorTag> > |
232 | { |
233 | static const bool value = true; |
234 | }; |
235 | |
236 | template<unsigned int AllocatorTag> |
237 | struct constructible_with_allocator_suffix |
238 | < ::allocator_argument_tester<ConstructibleSuffix, AllocatorTag> > |
239 | { |
240 | static const bool value = true; |
241 | }; |
242 | |
243 | } //namespace container { |
244 | } //namespace boost { |
245 | |
246 | #endif //BOOST_CONTAINER_TEST_ALLOCATOR_ARGUMENT_TESTER_HPP |
247 | |