| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365 | /*Copyright 2007 Tobias SchwingerCopyright 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>#endifnamespace 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;};#elsetemplate<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 voidfc_destroy(A& a, T* p){    std::allocator_traits<A>::destroy(a, p);}#elsetemplate<class A, class T>inline voidfc_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 voidfc_construct(A& a, T* p, Args&&... args){    std::allocator_traits<A>::construct(a, p, std::forward<Args>(args)...);}#elsetemplate<class A, class T, class... Args>inline voidfc_construct(A&, T* p, Args&&... args){    ::new((void*)p) T(std::forward<Args>(args)...);}#endif#endiftemplate<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
 |