File indexing completed on 2025-01-18 09:31:06
0001
0002
0003
0004
0005
0006
0007
0008
0009
0010 #ifndef BOOST_FUNCTIONAL_FACTORY_HPP
0011 #define BOOST_FUNCTIONAL_FACTORY_HPP
0012
0013 #include <boost/config.hpp>
0014 #include <boost/core/empty_value.hpp>
0015 #include <boost/core/pointer_traits.hpp>
0016 #include <boost/type_traits/remove_cv.hpp>
0017 #if !defined(BOOST_NO_CXX11_ALLOCATOR)
0018 #include <memory>
0019 #endif
0020 #include <new>
0021 #if !defined(BOOST_NO_CXX11_RVALUE_REFERENCES) && \
0022 !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
0023 #include <utility>
0024 #endif
0025
0026 namespace boost {
0027
0028 enum factory_alloc_propagation {
0029 factory_alloc_for_pointee_and_deleter,
0030 factory_passes_alloc_to_smart_pointer
0031 };
0032
0033 namespace detail {
0034
0035 template<factory_alloc_propagation>
0036 struct fc_tag { };
0037
0038 #if !defined(BOOST_NO_CXX11_ALLOCATOR)
0039 template<class A, class T>
0040 struct fc_rebind {
0041 typedef typename std::allocator_traits<A>::template rebind_alloc<T> type;
0042 };
0043
0044 template<class A>
0045 struct fc_pointer {
0046 typedef typename std::allocator_traits<A>::pointer type;
0047 };
0048 #else
0049 template<class A, class T>
0050 struct fc_rebind {
0051 typedef typename A::template rebind<T>::other type;
0052 };
0053
0054 template<class A>
0055 struct fc_pointer {
0056 typedef typename A::pointer type;
0057 };
0058 #endif
0059
0060 #if !defined(BOOST_NO_CXX11_ALLOCATOR) && \
0061 !defined(BOOST_NO_CXX11_RVALUE_REFERENCES) && \
0062 !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
0063 template<class A, class T>
0064 inline void
0065 fc_destroy(A& a, T* p)
0066 {
0067 std::allocator_traits<A>::destroy(a, p);
0068 }
0069 #else
0070 template<class A, class T>
0071 inline void
0072 fc_destroy(A&, T* p)
0073 {
0074 p->~T();
0075 }
0076 #endif
0077
0078 #if !defined(BOOST_NO_CXX11_RVALUE_REFERENCES) && \
0079 !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
0080 #if !defined(BOOST_NO_CXX11_ALLOCATOR)
0081 template<class A, class T, class... Args>
0082 inline void
0083 fc_construct(A& a, T* p, Args&&... args)
0084 {
0085 std::allocator_traits<A>::construct(a, p, std::forward<Args>(args)...);
0086 }
0087 #else
0088 template<class A, class T, class... Args>
0089 inline void
0090 fc_construct(A&, T* p, Args&&... args)
0091 {
0092 ::new((void*)p) T(std::forward<Args>(args)...);
0093 }
0094 #endif
0095 #endif
0096
0097 template<class A>
0098 class fc_delete
0099 : boost::empty_value<A> {
0100 typedef boost::empty_value<A> base;
0101
0102 public:
0103 explicit fc_delete(const A& a) BOOST_NOEXCEPT
0104 : base(boost::empty_init_t(), a) { }
0105
0106 void operator()(typename fc_pointer<A>::type p) {
0107 boost::detail::fc_destroy(base::get(), boost::to_address(p));
0108 base::get().deallocate(p, 1);
0109 }
0110 };
0111
0112 template<class R, class A>
0113 class fc_allocate {
0114 public:
0115 explicit fc_allocate(const A& a)
0116 : a_(a)
0117 , p_(a_.allocate(1)) { }
0118
0119 ~fc_allocate() {
0120 if (p_) {
0121 a_.deallocate(p_, 1);
0122 }
0123 }
0124
0125 A& state() BOOST_NOEXCEPT {
0126 return a_;
0127 }
0128
0129 typename A::value_type* get() const BOOST_NOEXCEPT {
0130 return boost::to_address(p_);
0131 }
0132
0133 R release(fc_tag<factory_alloc_for_pointee_and_deleter>) {
0134 return R(release(), fc_delete<A>(a_), a_);
0135 }
0136
0137 R release(fc_tag<factory_passes_alloc_to_smart_pointer>) {
0138 return R(release(), fc_delete<A>(a_));
0139 }
0140
0141 private:
0142 typedef typename fc_pointer<A>::type pointer;
0143
0144 pointer release() BOOST_NOEXCEPT {
0145 pointer p = p_;
0146 p_ = pointer();
0147 return p;
0148 }
0149
0150 fc_allocate(const fc_allocate&);
0151 fc_allocate& operator=(const fc_allocate&);
0152
0153 A a_;
0154 pointer p_;
0155 };
0156
0157 }
0158
0159 template<class Pointer, class Allocator = void,
0160 factory_alloc_propagation Policy = factory_alloc_for_pointee_and_deleter>
0161 class factory;
0162
0163 template<class Pointer, factory_alloc_propagation Policy>
0164 class factory<Pointer, void, Policy> {
0165 public:
0166 typedef typename remove_cv<Pointer>::type result_type;
0167
0168 private:
0169 typedef typename pointer_traits<result_type>::element_type type;
0170
0171 public:
0172 #if !defined(BOOST_NO_CXX11_RVALUE_REFERENCES) && \
0173 !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
0174 template<class... Args>
0175 result_type operator()(Args&&... args) const {
0176 return result_type(new type(std::forward<Args>(args)...));
0177 }
0178 #else
0179 result_type operator()() const {
0180 return result_type(new type());
0181 }
0182
0183 template<class A0>
0184 result_type operator()(A0& a0) const {
0185 return result_type(new type(a0));
0186 }
0187
0188 template<class A0, class A1>
0189 result_type operator()(A0& a0, A1& a1) const {
0190 return result_type(new type(a0, a1));
0191 }
0192
0193 template<class A0, class A1, class A2>
0194 result_type operator()(A0& a0, A1& a1, A2& a2) const {
0195 return result_type(new type(a0, a1, a2));
0196 }
0197
0198 template<class A0, class A1, class A2, class A3>
0199 result_type operator()(A0& a0, A1& a1, A2& a2, A3& a3) const {
0200 return result_type(new type(a0, a1, a2, a3));
0201 }
0202
0203 template<class A0, class A1, class A2, class A3, class A4>
0204 result_type operator()(A0& a0, A1& a1, A2& a2, A3& a3, A4& a4) const {
0205 return result_type(new type(a0, a1, a2, a3, a4));
0206 }
0207
0208 template<class A0, class A1, class A2, class A3, class A4, class A5>
0209 result_type operator()(A0& a0, A1& a1, A2& a2, A3& a3, A4& a4,
0210 A5& a5) const {
0211 return result_type(new type(a0, a1, a2, a3, a4, a5));
0212 }
0213
0214 template<class A0, class A1, class A2, class A3, class A4, class A5,
0215 class A6>
0216 result_type operator()(A0& a0, A1& a1, A2& a2, A3& a3, A4& a4, A5& a5,
0217 A6& a6) const {
0218 return result_type(new type(a0, a1, a2, a3, a4, a5, a6));
0219 }
0220
0221 template<class A0, class A1, class A2, class A3, class A4, class A5,
0222 class A6, class A7>
0223 result_type operator()(A0& a0, A1& a1, A2& a2, A3& a3, A4& a4, A5& a5,
0224 A6& a6, A7& a7) const {
0225 return result_type(new type(a0, a1, a2, a3, a4, a5, a6, a7));
0226 }
0227
0228 template<class A0, class A1, class A2, class A3, class A4, class A5,
0229 class A6, class A7, class A8>
0230 result_type operator()(A0& a0, A1& a1, A2& a2, A3& a3, A4& a4, A5& a5,
0231 A6& a6, A7& a7, A8& a8) const {
0232 return result_type(new type(a0, a1, a2, a3, a4, a5, a6, a7, a8));
0233 }
0234
0235 template<class A0, class A1, class A2, class A3, class A4, class A5,
0236 class A6, class A7, class A8, class A9>
0237 result_type operator()(A0& a0, A1& a1, A2& a2, A3& a3, A4& a4, A5& a5,
0238 A6& a6, A7& a7, A8& a8, A9& a9) const {
0239 return result_type(new type(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9));
0240 }
0241 #endif
0242 };
0243
0244 template<class Pointer, class Allocator, factory_alloc_propagation Policy>
0245 class factory
0246 : empty_value<typename detail::fc_rebind<Allocator,
0247 typename pointer_traits<typename
0248 remove_cv<Pointer>::type>::element_type>::type> {
0249 public:
0250 typedef typename remove_cv<Pointer>::type result_type;
0251
0252 private:
0253 typedef typename pointer_traits<result_type>::element_type type;
0254 typedef typename detail::fc_rebind<Allocator, type>::type allocator;
0255 typedef empty_value<allocator> base;
0256
0257 public:
0258 factory() BOOST_NOEXCEPT
0259 : base(empty_init_t()) { }
0260
0261 explicit factory(const Allocator& a) BOOST_NOEXCEPT
0262 : base(empty_init_t(), a) { }
0263
0264 #if !defined(BOOST_NO_CXX11_RVALUE_REFERENCES) && \
0265 !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
0266 template<class... Args>
0267 result_type operator()(Args&&... args) const {
0268 detail::fc_allocate<result_type, allocator> s(base::get());
0269 detail::fc_construct(s.state(), s.get(), std::forward<Args>(args)...);
0270 return s.release(detail::fc_tag<Policy>());
0271 }
0272 #else
0273 result_type operator()() const {
0274 detail::fc_allocate<result_type, allocator> s(base::get());
0275 ::new((void*)s.get()) type();
0276 return s.release(detail::fc_tag<Policy>());
0277 }
0278
0279 template<class A0>
0280 result_type operator()(A0& a0) const {
0281 detail::fc_allocate<result_type, allocator> s(base::get());
0282 ::new((void*)s.get()) type(a0);
0283 return s.release(detail::fc_tag<Policy>());
0284 }
0285
0286 template<class A0, class A1>
0287 result_type operator()(A0& a0, A1& a1) const {
0288 detail::fc_allocate<result_type, allocator> s(base::get());
0289 ::new((void*)s.get()) type(a0, a1);
0290 return s.release(detail::fc_tag<Policy>());
0291 }
0292
0293 template<class A0, class A1, class A2>
0294 result_type operator()(A0& a0, A1& a1, A2& a2) const {
0295 detail::fc_allocate<result_type, allocator> s(base::get());
0296 ::new((void*)s.get()) type(a0, a1, a2);
0297 return s.release(detail::fc_tag<Policy>());
0298 }
0299
0300 template<class A0, class A1, class A2, class A3>
0301 result_type operator()(A0& a0, A1& a1, A2& a2, A3& a3) const {
0302 detail::fc_allocate<result_type, allocator> s(base::get());
0303 ::new((void*)s.get()) type(a0, a1, a2, a3);
0304 return s.release(detail::fc_tag<Policy>());
0305 }
0306
0307 template<class A0, class A1, class A2, class A3, class A4>
0308 result_type operator()(A0& a0, A1& a1, A2& a2, A3& a3, A4& a4) const {
0309 detail::fc_allocate<result_type, allocator> s(base::get());
0310 ::new((void*)s.get()) type(a0, a1, a2, a3, a4);
0311 return s.release(detail::fc_tag<Policy>());
0312 }
0313
0314 template<class A0, class A1, class A2, class A3, class A4, class A5>
0315 result_type operator()(A0& a0, A1& a1, A2& a2, A3& a3, A4& a4,
0316 A5& a5) const {
0317 detail::fc_allocate<result_type, allocator> s(base::get());
0318 ::new((void*)s.get()) type(a0, a1, a2, a3, a4, a5);
0319 return s.release(detail::fc_tag<Policy>());
0320 }
0321
0322 template<class A0, class A1, class A2, class A3, class A4, class A5,
0323 class A6>
0324 result_type operator()(A0& a0, A1& a1, A2& a2, A3& a3, A4& a4, A5& a5,
0325 A6& a6) const {
0326 detail::fc_allocate<result_type, allocator> s(base::get());
0327 ::new((void*)s.get()) type(a0, a1, a2, a3, a4, a5, a6);
0328 return s.release(detail::fc_tag<Policy>());
0329 }
0330
0331 template<class A0, class A1, class A2, class A3, class A4, class A5,
0332 class A6, class A7>
0333 result_type operator()(A0& a0, A1& a1, A2& a2, A3& a3, A4& a4, A5& a5,
0334 A6& a6, A7& a7) const {
0335 detail::fc_allocate<result_type, allocator> s(base::get());
0336 ::new((void*)s.get()) type(a0, a1, a2, a3, a4, a5, a6, a7);
0337 return s.release(detail::fc_tag<Policy>());
0338 }
0339
0340 template<class A0, class A1, class A2, class A3, class A4, class A5,
0341 class A6, class A7, class A8>
0342 result_type operator()(A0& a0, A1& a1, A2& a2, A3& a3, A4& a4, A5& a5,
0343 A6& a6, A7& a7, A8& a8) const {
0344 detail::fc_allocate<result_type, allocator> s(base::get());
0345 ::new((void*)s.get()) type(a0, a1, a2, a3, a4, a5, a6, a7, a8);
0346 return s.release(detail::fc_tag<Policy>());
0347 }
0348
0349 template<class A0, class A1, class A2, class A3, class A4, class A5,
0350 class A6, class A7, class A8, class A9>
0351 result_type operator()(A0& a0, A1& a1, A2& a2, A3& a3, A4& a4, A5& a5,
0352 A6& a6, A7& a7, A8& a8, A9& a9) const {
0353 detail::fc_allocate<result_type, allocator> s(base::get());
0354 ::new((void*)s.get()) type(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9);
0355 return s.release(detail::fc_tag<Policy>());
0356 }
0357 #endif
0358 };
0359
0360 template<class Pointer, class Allocator, factory_alloc_propagation Policy>
0361 class factory<Pointer&, Allocator, Policy> { };
0362
0363 }
0364
0365 #endif