123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365 |
- /*
- Copyright 2007 Tobias Schwinger
- Copyright 2019 Glen Joseph Fernandes
- (glenjofe@gmail.com)
- Distributed under the Boost Software License, Version 1.0.
- (http://www.boost.org/LICENSE_1_0.txt)
- */
- #ifndef BOOST_FUNCTIONAL_FACTORY_HPP
- #define BOOST_FUNCTIONAL_FACTORY_HPP
- #include <boost/config.hpp>
- #include <boost/core/empty_value.hpp>
- #include <boost/core/pointer_traits.hpp>
- #include <boost/type_traits/remove_cv.hpp>
- #if !defined(BOOST_NO_CXX11_ALLOCATOR)
- #include <memory>
- #endif
- #include <new>
- #if !defined(BOOST_NO_CXX11_RVALUE_REFERENCES) && \
- !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
- #include <utility>
- #endif
- namespace boost {
- enum factory_alloc_propagation {
- factory_alloc_for_pointee_and_deleter,
- factory_passes_alloc_to_smart_pointer
- };
- namespace detail {
- template<factory_alloc_propagation>
- struct fc_tag { };
- #if !defined(BOOST_NO_CXX11_ALLOCATOR)
- template<class A, class T>
- struct fc_rebind {
- typedef typename std::allocator_traits<A>::template rebind_alloc<T> type;
- };
- template<class A>
- struct fc_pointer {
- typedef typename std::allocator_traits<A>::pointer type;
- };
- #else
- template<class A, class T>
- struct fc_rebind {
- typedef typename A::template rebind<T>::other type;
- };
- template<class A>
- struct fc_pointer {
- typedef typename A::pointer type;
- };
- #endif
- #if !defined(BOOST_NO_CXX11_ALLOCATOR) && \
- !defined(BOOST_NO_CXX11_RVALUE_REFERENCES) && \
- !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
- template<class A, class T>
- inline void
- fc_destroy(A& a, T* p)
- {
- std::allocator_traits<A>::destroy(a, p);
- }
- #else
- template<class A, class T>
- inline void
- fc_destroy(A&, T* p)
- {
- p->~T();
- }
- #endif
- #if !defined(BOOST_NO_CXX11_RVALUE_REFERENCES) && \
- !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
- #if !defined(BOOST_NO_CXX11_ALLOCATOR)
- template<class A, class T, class... Args>
- inline void
- fc_construct(A& a, T* p, Args&&... args)
- {
- std::allocator_traits<A>::construct(a, p, std::forward<Args>(args)...);
- }
- #else
- template<class A, class T, class... Args>
- inline void
- fc_construct(A&, T* p, Args&&... args)
- {
- ::new((void*)p) T(std::forward<Args>(args)...);
- }
- #endif
- #endif
- template<class A>
- class fc_delete
- : boost::empty_value<A> {
- typedef boost::empty_value<A> base;
- public:
- explicit fc_delete(const A& a) BOOST_NOEXCEPT
- : base(boost::empty_init_t(), a) { }
- void operator()(typename fc_pointer<A>::type p) {
- boost::detail::fc_destroy(base::get(), boost::to_address(p));
- base::get().deallocate(p, 1);
- }
- };
- template<class R, class A>
- class fc_allocate {
- public:
- explicit fc_allocate(const A& a)
- : a_(a)
- , p_(a_.allocate(1)) { }
- ~fc_allocate() {
- if (p_) {
- a_.deallocate(p_, 1);
- }
- }
- A& state() BOOST_NOEXCEPT {
- return a_;
- }
- typename A::value_type* get() const BOOST_NOEXCEPT {
- return boost::to_address(p_);
- }
- R release(fc_tag<factory_alloc_for_pointee_and_deleter>) {
- return R(release(), fc_delete<A>(a_), a_);
- }
- R release(fc_tag<factory_passes_alloc_to_smart_pointer>) {
- return R(release(), fc_delete<A>(a_));
- }
- private:
- typedef typename fc_pointer<A>::type pointer;
- pointer release() BOOST_NOEXCEPT {
- pointer p = p_;
- p_ = pointer();
- return p;
- }
- fc_allocate(const fc_allocate&);
- fc_allocate& operator=(const fc_allocate&);
- A a_;
- pointer p_;
- };
- } /* detail */
- template<class Pointer, class Allocator = void,
- factory_alloc_propagation Policy = factory_alloc_for_pointee_and_deleter>
- class factory;
- template<class Pointer, factory_alloc_propagation Policy>
- class factory<Pointer, void, Policy> {
- public:
- typedef typename remove_cv<Pointer>::type result_type;
- private:
- typedef typename pointer_traits<result_type>::element_type type;
- public:
- #if !defined(BOOST_NO_CXX11_RVALUE_REFERENCES) && \
- !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
- template<class... Args>
- result_type operator()(Args&&... args) const {
- return result_type(new type(std::forward<Args>(args)...));
- }
- #else
- result_type operator()() const {
- return result_type(new type());
- }
- template<class A0>
- result_type operator()(A0& a0) const {
- return result_type(new type(a0));
- }
- template<class A0, class A1>
- result_type operator()(A0& a0, A1& a1) const {
- return result_type(new type(a0, a1));
- }
- template<class A0, class A1, class A2>
- result_type operator()(A0& a0, A1& a1, A2& a2) const {
- return result_type(new type(a0, a1, a2));
- }
- template<class A0, class A1, class A2, class A3>
- result_type operator()(A0& a0, A1& a1, A2& a2, A3& a3) const {
- return result_type(new type(a0, a1, a2, a3));
- }
- template<class A0, class A1, class A2, class A3, class A4>
- result_type operator()(A0& a0, A1& a1, A2& a2, A3& a3, A4& a4) const {
- return result_type(new type(a0, a1, a2, a3, a4));
- }
- template<class A0, class A1, class A2, class A3, class A4, class A5>
- result_type operator()(A0& a0, A1& a1, A2& a2, A3& a3, A4& a4,
- A5& a5) const {
- return result_type(new type(a0, a1, a2, a3, a4, a5));
- }
- template<class A0, class A1, class A2, class A3, class A4, class A5,
- class A6>
- result_type operator()(A0& a0, A1& a1, A2& a2, A3& a3, A4& a4, A5& a5,
- A6& a6) const {
- return result_type(new type(a0, a1, a2, a3, a4, a5, a6));
- }
- template<class A0, class A1, class A2, class A3, class A4, class A5,
- class A6, class A7>
- result_type operator()(A0& a0, A1& a1, A2& a2, A3& a3, A4& a4, A5& a5,
- A6& a6, A7& a7) const {
- return result_type(new type(a0, a1, a2, a3, a4, a5, a6, a7));
- }
- template<class A0, class A1, class A2, class A3, class A4, class A5,
- class A6, class A7, class A8>
- result_type operator()(A0& a0, A1& a1, A2& a2, A3& a3, A4& a4, A5& a5,
- A6& a6, A7& a7, A8& a8) const {
- return result_type(new type(a0, a1, a2, a3, a4, a5, a6, a7, a8));
- }
- template<class A0, class A1, class A2, class A3, class A4, class A5,
- class A6, class A7, class A8, class A9>
- result_type operator()(A0& a0, A1& a1, A2& a2, A3& a3, A4& a4, A5& a5,
- A6& a6, A7& a7, A8& a8, A9& a9) const {
- return result_type(new type(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9));
- }
- #endif
- };
- template<class Pointer, class Allocator, factory_alloc_propagation Policy>
- class factory
- : empty_value<typename detail::fc_rebind<Allocator,
- typename pointer_traits<typename
- remove_cv<Pointer>::type>::element_type>::type> {
- public:
- typedef typename remove_cv<Pointer>::type result_type;
- private:
- typedef typename pointer_traits<result_type>::element_type type;
- typedef typename detail::fc_rebind<Allocator, type>::type allocator;
- typedef empty_value<allocator> base;
- public:
- factory() BOOST_NOEXCEPT
- : base(empty_init_t()) { }
- explicit factory(const Allocator& a) BOOST_NOEXCEPT
- : base(empty_init_t(), a) { }
- #if !defined(BOOST_NO_CXX11_RVALUE_REFERENCES) && \
- !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
- template<class... Args>
- result_type operator()(Args&&... args) const {
- detail::fc_allocate<result_type, allocator> s(base::get());
- detail::fc_construct(s.state(), s.get(), std::forward<Args>(args)...);
- return s.release(detail::fc_tag<Policy>());
- }
- #else
- result_type operator()() const {
- detail::fc_allocate<result_type, allocator> s(base::get());
- ::new((void*)s.get()) type();
- return s.release(detail::fc_tag<Policy>());
- }
- template<class A0>
- result_type operator()(A0& a0) const {
- detail::fc_allocate<result_type, allocator> s(base::get());
- ::new((void*)s.get()) type(a0);
- return s.release(detail::fc_tag<Policy>());
- }
- template<class A0, class A1>
- result_type operator()(A0& a0, A1& a1) const {
- detail::fc_allocate<result_type, allocator> s(base::get());
- ::new((void*)s.get()) type(a0, a1);
- return s.release(detail::fc_tag<Policy>());
- }
- template<class A0, class A1, class A2>
- result_type operator()(A0& a0, A1& a1, A2& a2) const {
- detail::fc_allocate<result_type, allocator> s(base::get());
- ::new((void*)s.get()) type(a0, a1, a2);
- return s.release(detail::fc_tag<Policy>());
- }
- template<class A0, class A1, class A2, class A3>
- result_type operator()(A0& a0, A1& a1, A2& a2, A3& a3) const {
- detail::fc_allocate<result_type, allocator> s(base::get());
- ::new((void*)s.get()) type(a0, a1, a2, a3);
- return s.release(detail::fc_tag<Policy>());
- }
- template<class A0, class A1, class A2, class A3, class A4>
- result_type operator()(A0& a0, A1& a1, A2& a2, A3& a3, A4& a4) const {
- detail::fc_allocate<result_type, allocator> s(base::get());
- ::new((void*)s.get()) type(a0, a1, a2, a3, a4);
- return s.release(detail::fc_tag<Policy>());
- }
- template<class A0, class A1, class A2, class A3, class A4, class A5>
- result_type operator()(A0& a0, A1& a1, A2& a2, A3& a3, A4& a4,
- A5& a5) const {
- detail::fc_allocate<result_type, allocator> s(base::get());
- ::new((void*)s.get()) type(a0, a1, a2, a3, a4, a5);
- return s.release(detail::fc_tag<Policy>());
- }
- template<class A0, class A1, class A2, class A3, class A4, class A5,
- class A6>
- result_type operator()(A0& a0, A1& a1, A2& a2, A3& a3, A4& a4, A5& a5,
- A6& a6) const {
- detail::fc_allocate<result_type, allocator> s(base::get());
- ::new((void*)s.get()) type(a0, a1, a2, a3, a4, a5, a6);
- return s.release(detail::fc_tag<Policy>());
- }
- template<class A0, class A1, class A2, class A3, class A4, class A5,
- class A6, class A7>
- result_type operator()(A0& a0, A1& a1, A2& a2, A3& a3, A4& a4, A5& a5,
- A6& a6, A7& a7) const {
- detail::fc_allocate<result_type, allocator> s(base::get());
- ::new((void*)s.get()) type(a0, a1, a2, a3, a4, a5, a6, a7);
- return s.release(detail::fc_tag<Policy>());
- }
- template<class A0, class A1, class A2, class A3, class A4, class A5,
- class A6, class A7, class A8>
- result_type operator()(A0& a0, A1& a1, A2& a2, A3& a3, A4& a4, A5& a5,
- A6& a6, A7& a7, A8& a8) const {
- detail::fc_allocate<result_type, allocator> s(base::get());
- ::new((void*)s.get()) type(a0, a1, a2, a3, a4, a5, a6, a7, a8);
- return s.release(detail::fc_tag<Policy>());
- }
- template<class A0, class A1, class A2, class A3, class A4, class A5,
- class A6, class A7, class A8, class A9>
- result_type operator()(A0& a0, A1& a1, A2& a2, A3& a3, A4& a4, A5& a5,
- A6& a6, A7& a7, A8& a8, A9& a9) const {
- detail::fc_allocate<result_type, allocator> s(base::get());
- ::new((void*)s.get()) type(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9);
- return s.release(detail::fc_tag<Policy>());
- }
- #endif
- };
- template<class Pointer, class Allocator, factory_alloc_propagation Policy>
- class factory<Pointer&, Allocator, Policy> { };
- } /* boost */
- #endif
|