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/container/pmr/polymorphic_allocator.hpp>
18
19
20 template<class T, unsigned int Id, bool HasTrueTypes = false>
21 class propagation_test_allocator
22 {
23 BOOST_COPYABLE_AND_MOVABLE(propagation_test_allocator)
24 public:
25
26 template<class U>
27 struct rebind
28 {
29 typedef propagation_test_allocator<U, Id, HasTrueTypes> other;
30 };
31
32 typedef boost::container::dtl::bool_<HasTrueTypes> propagate_on_container_copy_assignment;
33 typedef boost::container::dtl::bool_<HasTrueTypes> propagate_on_container_move_assignment;
34 typedef boost::container::dtl::bool_<HasTrueTypes> propagate_on_container_swap;
35 typedef boost::container::dtl::bool_<HasTrueTypes> is_always_equal;
36 typedef T value_type;
37
propagation_test_allocator()38 propagation_test_allocator()
39 : m_default_contructed(true), m_move_contructed(false), m_move_assigned(false)
40 {}
41
propagation_test_allocator(const propagation_test_allocator &)42 propagation_test_allocator(const propagation_test_allocator&)
43 : m_default_contructed(false), m_move_contructed(false), m_move_assigned(false)
44 {}
45
propagation_test_allocator(BOOST_RV_REF (propagation_test_allocator))46 propagation_test_allocator(BOOST_RV_REF(propagation_test_allocator) )
47 : m_default_contructed(false), m_move_contructed(true), m_move_assigned(false)
48 {}
49
50 template<class U>
propagation_test_allocator(BOOST_RV_REF_BEG propagation_test_allocator<U,Id,HasTrueTypes> BOOST_RV_REF_END)51 propagation_test_allocator(BOOST_RV_REF_BEG propagation_test_allocator<U, Id, HasTrueTypes> BOOST_RV_REF_END)
52 : m_default_contructed(false), m_move_contructed(true), m_move_assigned(false)
53 {}
54
55 template<class U>
propagation_test_allocator(const propagation_test_allocator<U,Id,HasTrueTypes> &)56 propagation_test_allocator(const propagation_test_allocator<U, Id, HasTrueTypes> &)
57 {}
58
operator =(BOOST_COPY_ASSIGN_REF (propagation_test_allocator))59 propagation_test_allocator & operator=(BOOST_COPY_ASSIGN_REF(propagation_test_allocator))
60 { return *this; }
61
operator =(BOOST_RV_REF (propagation_test_allocator))62 propagation_test_allocator & operator=(BOOST_RV_REF(propagation_test_allocator))
63 {
64 m_move_assigned = true;
65 return *this;
66 }
67
max_size() const68 std::size_t max_size() const
69 { return std::size_t(-1); }
70
allocate(std::size_t n)71 T* allocate(std::size_t n)
72 { return (T*)::new char[n*sizeof(T)]; }
73
deallocate(T * p,std::size_t)74 void deallocate(T*p, std::size_t)
75 { delete []static_cast<char*>(static_cast<void*>(p)); }
76
77 bool m_default_contructed;
78 bool m_move_contructed;
79 bool m_move_assigned;
80 };
81
82 template <class T1, class T2, unsigned int Id, bool HasTrueTypes>
operator ==(const propagation_test_allocator<T1,Id,HasTrueTypes> &,const propagation_test_allocator<T2,Id,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>
operator !=(const propagation_test_allocator<T1,Id,HasTrueTypes> &,const propagation_test_allocator<T2,Id,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 ErasedTypePrefix,
99 ErasedTypeSuffix,
100 NotUsesAllocator
101 };
102
103 //This base class provices types for
104 //the derived class to implement each construction
105 //type. If a construction type does not apply
106 //the typedef is set to an internal nat
107 //so that the class is not constructible from
108 //the user arguments.
109 template<ConstructionTypeEnum ConstructionType, unsigned int AllocatorTag>
110 struct uses_allocator_base;
111
112 template<unsigned int AllocatorTag>
113 struct uses_allocator_base<ConstructibleSuffix, AllocatorTag>
114 {
115 typedef propagation_test_allocator<int, AllocatorTag> allocator_type;
116 typedef allocator_type allocator_constructor_type;
117 struct nat{};
118 typedef nat allocator_arg_type;
119 };
120
121 template<unsigned int AllocatorTag>
122 struct uses_allocator_base<ConstructiblePrefix, AllocatorTag>
123 {
124 typedef propagation_test_allocator<int, AllocatorTag> allocator_type;
125 typedef allocator_type allocator_constructor_type;
126 typedef boost::container::allocator_arg_t allocator_arg_type;
127 };
128
129 template<unsigned int AllocatorTag>
130 struct uses_allocator_base<ErasedTypePrefix, AllocatorTag>
131 {
132 typedef boost::container::erased_type allocator_type;
133 typedef boost::container::pmr::polymorphic_allocator<int> allocator_constructor_type;
134 typedef boost::container::allocator_arg_t allocator_arg_type;
135 };
136
137 template<unsigned int AllocatorTag>
138 struct uses_allocator_base<ErasedTypeSuffix, AllocatorTag>
139 {
140 typedef boost::container::erased_type allocator_type;
141 typedef boost::container::pmr::polymorphic_allocator<int> allocator_constructor_type;
142 struct nat{};
143 typedef nat allocator_arg_type;
144 };
145
146 template<unsigned int AllocatorTag>
147 struct uses_allocator_base<NotUsesAllocator, AllocatorTag>
148 {
149 struct nat{};
150 typedef nat allocator_constructor_type;
151 typedef nat allocator_arg_type;
152 };
153
154 template<ConstructionTypeEnum ConstructionType, unsigned int AllocatorTag>
155 struct allocator_argument_tester
156 : uses_allocator_base<ConstructionType, AllocatorTag>
157 {
158 private:
159 BOOST_COPYABLE_AND_MOVABLE(allocator_argument_tester)
160
161 public:
162
163 typedef uses_allocator_base<ConstructionType, AllocatorTag> base_type;
164
165 //0 user argument constructors
allocator_argument_testerallocator_argument_tester166 allocator_argument_tester()
167 : construction_type(NotUsesAllocator), value(0)
168 {}
169
allocator_argument_testerallocator_argument_tester170 explicit allocator_argument_tester
171 (typename base_type::allocator_constructor_type)
172 : construction_type(ConstructibleSuffix), value(0)
173 {}
174
allocator_argument_testerallocator_argument_tester175 explicit allocator_argument_tester
176 (typename base_type::allocator_arg_type, typename base_type::allocator_constructor_type)
177 : construction_type(ConstructiblePrefix), value(0)
178 {}
179
180 //1 user argument constructors
allocator_argument_testerallocator_argument_tester181 explicit allocator_argument_tester(int i)
182 : construction_type(NotUsesAllocator), value(i)
183 {}
184
allocator_argument_testerallocator_argument_tester185 allocator_argument_tester
186 (int i, typename base_type::allocator_constructor_type)
187 : construction_type(ConstructibleSuffix), value(i)
188 {}
189
allocator_argument_testerallocator_argument_tester190 allocator_argument_tester
191 ( typename base_type::allocator_arg_type
192 , typename base_type::allocator_constructor_type
193 , int i)
194 : construction_type(ConstructiblePrefix), value(i)
195 {}
196
197 //Copy constructors
allocator_argument_testerallocator_argument_tester198 allocator_argument_tester(const allocator_argument_tester &other)
199 : construction_type(NotUsesAllocator), value(other.value)
200 {}
201
allocator_argument_testerallocator_argument_tester202 allocator_argument_tester( const allocator_argument_tester &other
203 , typename base_type::allocator_constructor_type)
204 : construction_type(ConstructibleSuffix), value(other.value)
205 {}
206
allocator_argument_testerallocator_argument_tester207 allocator_argument_tester( typename base_type::allocator_arg_type
208 , typename base_type::allocator_constructor_type
209 , const allocator_argument_tester &other)
210 : construction_type(ConstructiblePrefix), value(other.value)
211 {}
212
213 //Move constructors
allocator_argument_testerallocator_argument_tester214 allocator_argument_tester(BOOST_RV_REF(allocator_argument_tester) other)
215 : construction_type(NotUsesAllocator), value(other.value)
216 { other.value = 0; other.construction_type = NotUsesAllocator; }
217
allocator_argument_testerallocator_argument_tester218 allocator_argument_tester( BOOST_RV_REF(allocator_argument_tester) other
219 , typename base_type::allocator_constructor_type)
220 : construction_type(ConstructibleSuffix), value(other.value)
221 { other.value = 0; other.construction_type = ConstructibleSuffix; }
222
allocator_argument_testerallocator_argument_tester223 allocator_argument_tester( typename base_type::allocator_arg_type
224 , typename base_type::allocator_constructor_type
225 , BOOST_RV_REF(allocator_argument_tester) other)
226 : construction_type(ConstructiblePrefix), value(other.value)
227 { other.value = 0; other.construction_type = ConstructiblePrefix; }
228
229 ConstructionTypeEnum construction_type;
230 int value;
231 };
232
233 namespace boost {
234 namespace container {
235
236 template<unsigned int AllocatorTag>
237 struct constructible_with_allocator_prefix
238 < ::allocator_argument_tester<ConstructiblePrefix, AllocatorTag> >
239 {
240 static const bool value = true;
241 };
242
243 template<unsigned int AllocatorTag>
244 struct constructible_with_allocator_prefix
245 < ::allocator_argument_tester<ErasedTypePrefix, AllocatorTag> >
246 {
247 static const bool value = true;
248 };
249
250
251 template<unsigned int AllocatorTag>
252 struct constructible_with_allocator_suffix
253 < ::allocator_argument_tester<ConstructibleSuffix, AllocatorTag> >
254 {
255 static const bool value = true;
256 };
257
258 template<unsigned int AllocatorTag>
259 struct constructible_with_allocator_suffix
260 < ::allocator_argument_tester<ErasedTypeSuffix, AllocatorTag> >
261 {
262 static const bool value = true;
263 };
264
265 } //namespace container {
266 } //namespace boost {
267
268 #endif //BOOST_CONTAINER_TEST_ALLOCATOR_ARGUMENT_TESTER_HPP
269