2 Copyright 2007 Tobias Schwinger
4 Copyright 2019 Glen Joseph Fernandes
7 Distributed under the Boost Software License, Version 1.0.
8 (http://www.boost.org/LICENSE_1_0.txt)
10 #ifndef BOOST_FUNCTIONAL_FACTORY_HPP
11 #define BOOST_FUNCTIONAL_FACTORY_HPP
13 #include <boost/config.hpp>
14 #include <boost/core/empty_value.hpp>
15 #include <boost/core/pointer_traits.hpp>
16 #include <boost/type_traits/remove_cv.hpp>
17 #if !defined(BOOST_NO_CXX11_ALLOCATOR)
21 #if !defined(BOOST_NO_CXX11_RVALUE_REFERENCES) && \
22 !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
28 enum factory_alloc_propagation {
29 factory_alloc_for_pointee_and_deleter,
30 factory_passes_alloc_to_smart_pointer
35 template<factory_alloc_propagation>
38 #if !defined(BOOST_NO_CXX11_ALLOCATOR)
39 template<class A, class T>
41 typedef typename std::allocator_traits<A>::template rebind_alloc<T> type;
46 typedef typename std::allocator_traits<A>::pointer type;
49 template<class A, class T>
51 typedef typename A::template rebind<T>::other type;
56 typedef typename A::pointer type;
60 #if !defined(BOOST_NO_CXX11_ALLOCATOR) && \
61 !defined(BOOST_NO_CXX11_RVALUE_REFERENCES) && \
62 !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
63 template<class A, class T>
65 fc_destroy(A& a, T* p)
67 std::allocator_traits<A>::destroy(a, p);
70 template<class A, class T>
78 #if !defined(BOOST_NO_CXX11_RVALUE_REFERENCES) && \
79 !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
80 #if !defined(BOOST_NO_CXX11_ALLOCATOR)
81 template<class A, class T, class... Args>
83 fc_construct(A& a, T* p, Args&&... args)
85 std::allocator_traits<A>::construct(a, p, std::forward<Args>(args)...);
88 template<class A, class T, class... Args>
90 fc_construct(A&, T* p, Args&&... args)
92 ::new((void*)p) T(std::forward<Args>(args)...);
99 : boost::empty_value<A> {
100 typedef boost::empty_value<A> base;
103 explicit fc_delete(const A& a) BOOST_NOEXCEPT
104 : base(boost::empty_init_t(), a) { }
106 void operator()(typename fc_pointer<A>::type p) {
107 boost::detail::fc_destroy(base::get(), boost::to_address(p));
108 base::get().deallocate(p, 1);
112 template<class R, class A>
115 explicit fc_allocate(const A& a)
117 , p_(a_.allocate(1)) { }
121 a_.deallocate(p_, 1);
125 A& state() BOOST_NOEXCEPT {
129 typename A::value_type* get() const BOOST_NOEXCEPT {
130 return boost::to_address(p_);
133 R release(fc_tag<factory_alloc_for_pointee_and_deleter>) {
134 return R(release(), fc_delete<A>(a_), a_);
137 R release(fc_tag<factory_passes_alloc_to_smart_pointer>) {
138 return R(release(), fc_delete<A>(a_));
142 typedef typename fc_pointer<A>::type pointer;
144 pointer release() BOOST_NOEXCEPT {
150 fc_allocate(const fc_allocate&);
151 fc_allocate& operator=(const fc_allocate&);
159 template<class Pointer, class Allocator = void,
160 factory_alloc_propagation Policy = factory_alloc_for_pointee_and_deleter>
163 template<class Pointer, factory_alloc_propagation Policy>
164 class factory<Pointer, void, Policy> {
166 typedef typename remove_cv<Pointer>::type result_type;
169 typedef typename pointer_traits<result_type>::element_type type;
172 #if !defined(BOOST_NO_CXX11_RVALUE_REFERENCES) && \
173 !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
174 template<class... Args>
175 result_type operator()(Args&&... args) const {
176 return result_type(new type(std::forward<Args>(args)...));
179 result_type operator()() const {
180 return result_type(new type());
184 result_type operator()(A0& a0) const {
185 return result_type(new type(a0));
188 template<class A0, class A1>
189 result_type operator()(A0& a0, A1& a1) const {
190 return result_type(new type(a0, a1));
193 template<class A0, class A1, class A2>
194 result_type operator()(A0& a0, A1& a1, A2& a2) const {
195 return result_type(new type(a0, a1, a2));
198 template<class A0, class A1, class A2, class A3>
199 result_type operator()(A0& a0, A1& a1, A2& a2, A3& a3) const {
200 return result_type(new type(a0, a1, a2, a3));
203 template<class A0, class A1, class A2, class A3, class A4>
204 result_type operator()(A0& a0, A1& a1, A2& a2, A3& a3, A4& a4) const {
205 return result_type(new type(a0, a1, a2, a3, a4));
208 template<class A0, class A1, class A2, class A3, class A4, class A5>
209 result_type operator()(A0& a0, A1& a1, A2& a2, A3& a3, A4& a4,
211 return result_type(new type(a0, a1, a2, a3, a4, a5));
214 template<class A0, class A1, class A2, class A3, class A4, class A5,
216 result_type operator()(A0& a0, A1& a1, A2& a2, A3& a3, A4& a4, A5& a5,
218 return result_type(new type(a0, a1, a2, a3, a4, a5, a6));
221 template<class A0, class A1, class A2, class A3, class A4, class A5,
223 result_type operator()(A0& a0, A1& a1, A2& a2, A3& a3, A4& a4, A5& a5,
224 A6& a6, A7& a7) const {
225 return result_type(new type(a0, a1, a2, a3, a4, a5, a6, a7));
228 template<class A0, class A1, class A2, class A3, class A4, class A5,
229 class A6, class A7, class A8>
230 result_type operator()(A0& a0, A1& a1, A2& a2, A3& a3, A4& a4, A5& a5,
231 A6& a6, A7& a7, A8& a8) const {
232 return result_type(new type(a0, a1, a2, a3, a4, a5, a6, a7, a8));
235 template<class A0, class A1, class A2, class A3, class A4, class A5,
236 class A6, class A7, class A8, class A9>
237 result_type operator()(A0& a0, A1& a1, A2& a2, A3& a3, A4& a4, A5& a5,
238 A6& a6, A7& a7, A8& a8, A9& a9) const {
239 return result_type(new type(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9));
244 template<class Pointer, class Allocator, factory_alloc_propagation Policy>
246 : empty_value<typename detail::fc_rebind<Allocator,
247 typename pointer_traits<typename
248 remove_cv<Pointer>::type>::element_type>::type> {
250 typedef typename remove_cv<Pointer>::type result_type;
253 typedef typename pointer_traits<result_type>::element_type type;
254 typedef typename detail::fc_rebind<Allocator, type>::type allocator;
255 typedef empty_value<allocator> base;
258 factory() BOOST_NOEXCEPT
259 : base(empty_init_t()) { }
261 explicit factory(const Allocator& a) BOOST_NOEXCEPT
262 : base(empty_init_t(), a) { }
264 #if !defined(BOOST_NO_CXX11_RVALUE_REFERENCES) && \
265 !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
266 template<class... Args>
267 result_type operator()(Args&&... args) const {
268 detail::fc_allocate<result_type, allocator> s(base::get());
269 detail::fc_construct(s.state(), s.get(), std::forward<Args>(args)...);
270 return s.release(detail::fc_tag<Policy>());
273 result_type operator()() const {
274 detail::fc_allocate<result_type, allocator> s(base::get());
275 ::new((void*)s.get()) type();
276 return s.release(detail::fc_tag<Policy>());
280 result_type operator()(A0& a0) const {
281 detail::fc_allocate<result_type, allocator> s(base::get());
282 ::new((void*)s.get()) type(a0);
283 return s.release(detail::fc_tag<Policy>());
286 template<class A0, class A1>
287 result_type operator()(A0& a0, A1& a1) const {
288 detail::fc_allocate<result_type, allocator> s(base::get());
289 ::new((void*)s.get()) type(a0, a1);
290 return s.release(detail::fc_tag<Policy>());
293 template<class A0, class A1, class A2>
294 result_type operator()(A0& a0, A1& a1, A2& a2) const {
295 detail::fc_allocate<result_type, allocator> s(base::get());
296 ::new((void*)s.get()) type(a0, a1, a2);
297 return s.release(detail::fc_tag<Policy>());
300 template<class A0, class A1, class A2, class A3>
301 result_type operator()(A0& a0, A1& a1, A2& a2, A3& a3) const {
302 detail::fc_allocate<result_type, allocator> s(base::get());
303 ::new((void*)s.get()) type(a0, a1, a2, a3);
304 return s.release(detail::fc_tag<Policy>());
307 template<class A0, class A1, class A2, class A3, class A4>
308 result_type operator()(A0& a0, A1& a1, A2& a2, A3& a3, A4& a4) const {
309 detail::fc_allocate<result_type, allocator> s(base::get());
310 ::new((void*)s.get()) type(a0, a1, a2, a3, a4);
311 return s.release(detail::fc_tag<Policy>());
314 template<class A0, class A1, class A2, class A3, class A4, class A5>
315 result_type operator()(A0& a0, A1& a1, A2& a2, A3& a3, A4& a4,
317 detail::fc_allocate<result_type, allocator> s(base::get());
318 ::new((void*)s.get()) type(a0, a1, a2, a3, a4, a5);
319 return s.release(detail::fc_tag<Policy>());
322 template<class A0, class A1, class A2, class A3, class A4, class A5,
324 result_type operator()(A0& a0, A1& a1, A2& a2, A3& a3, A4& a4, A5& a5,
326 detail::fc_allocate<result_type, allocator> s(base::get());
327 ::new((void*)s.get()) type(a0, a1, a2, a3, a4, a5, a6);
328 return s.release(detail::fc_tag<Policy>());
331 template<class A0, class A1, class A2, class A3, class A4, class A5,
333 result_type operator()(A0& a0, A1& a1, A2& a2, A3& a3, A4& a4, A5& a5,
334 A6& a6, A7& a7) const {
335 detail::fc_allocate<result_type, allocator> s(base::get());
336 ::new((void*)s.get()) type(a0, a1, a2, a3, a4, a5, a6, a7);
337 return s.release(detail::fc_tag<Policy>());
340 template<class A0, class A1, class A2, class A3, class A4, class A5,
341 class A6, class A7, class A8>
342 result_type operator()(A0& a0, A1& a1, A2& a2, A3& a3, A4& a4, A5& a5,
343 A6& a6, A7& a7, A8& a8) const {
344 detail::fc_allocate<result_type, allocator> s(base::get());
345 ::new((void*)s.get()) type(a0, a1, a2, a3, a4, a5, a6, a7, a8);
346 return s.release(detail::fc_tag<Policy>());
349 template<class A0, class A1, class A2, class A3, class A4, class A5,
350 class A6, class A7, class A8, class A9>
351 result_type operator()(A0& a0, A1& a1, A2& a2, A3& a3, A4& a4, A5& a5,
352 A6& a6, A7& a7, A8& a8, A9& a9) const {
353 detail::fc_allocate<result_type, allocator> s(base::get());
354 ::new((void*)s.get()) type(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9);
355 return s.release(detail::fc_tag<Policy>());
360 template<class Pointer, class Allocator, factory_alloc_propagation Policy>
361 class factory<Pointer&, Allocator, Policy> { };