1 | /*============================================================================= |
2 | Copyright (c) 2007 Tobias Schwinger |
3 | |
4 | Use modification and distribution are subject to the Boost Software |
5 | License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at |
6 | http://www.boost.org/LICENSE_1_0.txt). |
7 | ==============================================================================*/ |
8 | |
9 | #ifndef BOOST_FUNCTIONAL_FACTORY_HPP_INCLUDED |
10 | # ifndef BOOST_PP_IS_ITERATING |
11 | |
12 | # include <boost/preprocessor/iteration/iterate.hpp> |
13 | # include <boost/preprocessor/repetition/enum_params.hpp> |
14 | # include <boost/preprocessor/repetition/enum_binary_params.hpp> |
15 | |
16 | # include <new> |
17 | # include <boost/pointee.hpp> |
18 | # include <boost/get_pointer.hpp> |
19 | # include <boost/non_type.hpp> |
20 | # include <boost/type_traits/remove_cv.hpp> |
21 | |
22 | # if defined(BOOST_FUNCTIONAL_FACTORY_SUPPORT_NONE_T) |
23 | # include <boost/none_t.hpp> |
24 | # endif |
25 | |
26 | # ifndef BOOST_FUNCTIONAL_FACTORY_MAX_ARITY |
27 | # define BOOST_FUNCTIONAL_FACTORY_MAX_ARITY 10 |
28 | # elif BOOST_FUNCTIONAL_FACTORY_MAX_ARITY < 3 |
29 | # undef BOOST_FUNCTIONAL_FACTORY_MAX_ARITY |
30 | # define BOOST_FUNCTIONAL_FACTORY_MAX_ARITY 3 |
31 | # endif |
32 | |
33 | namespace boost |
34 | { |
35 | enum factory_alloc_propagation |
36 | { |
37 | factory_alloc_for_pointee_and_deleter, |
38 | factory_passes_alloc_to_smart_pointer |
39 | }; |
40 | |
41 | #if defined(BOOST_FUNCTIONAL_FACTORY_SUPPORT_NONE_T) |
42 | template< typename Pointer, class Allocator = boost::none_t, |
43 | factory_alloc_propagation AP = factory_alloc_for_pointee_and_deleter > |
44 | class factory; |
45 | #else |
46 | template< typename Pointer, class Allocator = void, |
47 | factory_alloc_propagation AP = factory_alloc_for_pointee_and_deleter > |
48 | class factory; |
49 | #endif |
50 | |
51 | //----- ---- --- -- - - - - |
52 | |
53 | template< typename Pointer, factory_alloc_propagation AP > |
54 | class factory<Pointer, void, AP> |
55 | { |
56 | public: |
57 | typedef typename boost::remove_cv<Pointer>::type result_type; |
58 | typedef typename boost::pointee<result_type>::type value_type; |
59 | |
60 | factory() |
61 | { } |
62 | |
63 | # define BOOST_PP_FILENAME_1 <boost/functional/factory.hpp> |
64 | # define BOOST_PP_ITERATION_LIMITS (0,BOOST_FUNCTIONAL_FACTORY_MAX_ARITY) |
65 | # include BOOST_PP_ITERATE() |
66 | }; |
67 | |
68 | #if defined(BOOST_FUNCTIONAL_FACTORY_SUPPORT_NONE_T) |
69 | template< typename Pointer, factory_alloc_propagation AP > |
70 | class factory<Pointer, boost::none_t, AP> |
71 | : public factory<Pointer, void, AP> |
72 | {}; |
73 | #endif |
74 | |
75 | template< class Pointer, class Allocator, factory_alloc_propagation AP > |
76 | class factory |
77 | : private Allocator::template rebind< typename boost::pointee< |
78 | typename boost::remove_cv<Pointer>::type >::type >::other |
79 | { |
80 | public: |
81 | typedef typename boost::remove_cv<Pointer>::type result_type; |
82 | typedef typename boost::pointee<result_type>::type value_type; |
83 | |
84 | typedef typename Allocator::template rebind<value_type>::other |
85 | allocator_type; |
86 | |
87 | explicit factory(allocator_type const & a = allocator_type()) |
88 | : allocator_type(a) |
89 | { } |
90 | |
91 | private: |
92 | |
93 | struct deleter |
94 | : allocator_type |
95 | { |
96 | inline deleter(allocator_type const& that) |
97 | : allocator_type(that) |
98 | { } |
99 | |
100 | allocator_type& get_allocator() const |
101 | { |
102 | return *const_cast<allocator_type*>( |
103 | static_cast<allocator_type const*>(this)); |
104 | } |
105 | |
106 | void operator()(value_type* ptr) const |
107 | { |
108 | if (!! ptr) ptr->~value_type(); |
109 | const_cast<allocator_type*>(static_cast<allocator_type const*>( |
110 | this))->deallocate(ptr,1); |
111 | } |
112 | }; |
113 | |
114 | inline allocator_type& get_allocator() const |
115 | { |
116 | return *const_cast<allocator_type*>( |
117 | static_cast<allocator_type const*>(this)); |
118 | } |
119 | |
120 | inline result_type make_pointer(value_type* ptr, boost::non_type< |
121 | factory_alloc_propagation,factory_passes_alloc_to_smart_pointer>) |
122 | const |
123 | { |
124 | return result_type(ptr,deleter(this->get_allocator())); |
125 | } |
126 | inline result_type make_pointer(value_type* ptr, boost::non_type< |
127 | factory_alloc_propagation,factory_alloc_for_pointee_and_deleter>) |
128 | const |
129 | { |
130 | return result_type(ptr,deleter(this->get_allocator()), |
131 | this->get_allocator()); |
132 | } |
133 | |
134 | public: |
135 | |
136 | # define BOOST_TMP_MACRO |
137 | # define BOOST_PP_FILENAME_1 <boost/functional/factory.hpp> |
138 | # define BOOST_PP_ITERATION_LIMITS (0,BOOST_FUNCTIONAL_FACTORY_MAX_ARITY) |
139 | # include BOOST_PP_ITERATE() |
140 | # undef BOOST_TMP_MACRO |
141 | }; |
142 | |
143 | template< typename Pointer, class Allocator, factory_alloc_propagation AP > |
144 | class factory<Pointer&, Allocator, AP>; |
145 | // forbidden, would create a dangling reference |
146 | } |
147 | |
148 | # define BOOST_FUNCTIONAL_FACTORY_HPP_INCLUDED |
149 | # else // defined(BOOST_PP_IS_ITERATING) |
150 | # define N BOOST_PP_ITERATION() |
151 | # if !defined(BOOST_TMP_MACRO) |
152 | # if N > 0 |
153 | template< BOOST_PP_ENUM_PARAMS(N, typename T) > |
154 | # endif |
155 | inline result_type operator()(BOOST_PP_ENUM_BINARY_PARAMS(N,T,& a)) const |
156 | { |
157 | return result_type( new value_type(BOOST_PP_ENUM_PARAMS(N,a)) ); |
158 | } |
159 | # else // defined(BOOST_TMP_MACRO) |
160 | # if N > 0 |
161 | template< BOOST_PP_ENUM_PARAMS(N, typename T) > |
162 | # endif |
163 | inline result_type operator()(BOOST_PP_ENUM_BINARY_PARAMS(N,T,& a)) const |
164 | { |
165 | value_type* memory = this->get_allocator().allocate(1); |
166 | try |
167 | { |
168 | return make_pointer( |
169 | new(memory) value_type(BOOST_PP_ENUM_PARAMS(N,a)), |
170 | boost::non_type<factory_alloc_propagation,AP>() ); |
171 | } |
172 | catch (...) { this->get_allocator().deallocate(memory,1); throw; } |
173 | } |
174 | # endif |
175 | # undef N |
176 | # endif // defined(BOOST_PP_IS_ITERATING) |
177 | |
178 | #endif // include guard |
179 | |
180 | |