Chris@16: /*============================================================================= Chris@16: Copyright (c) 2007 Tobias Schwinger Chris@16: Chris@16: Use modification and distribution are subject to the Boost Software Chris@16: License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at Chris@16: http://www.boost.org/LICENSE_1_0.txt). Chris@16: ==============================================================================*/ Chris@16: Chris@16: #ifndef BOOST_FUNCTIONAL_FACTORY_HPP_INCLUDED Chris@16: # ifndef BOOST_PP_IS_ITERATING Chris@16: Chris@16: # include Chris@16: # include Chris@16: # include Chris@16: Chris@16: # include Chris@16: # include Chris@16: # include Chris@16: # include Chris@16: # include Chris@16: Chris@101: # if defined(BOOST_FUNCTIONAL_FACTORY_SUPPORT_NONE_T) Chris@101: # include Chris@101: # endif Chris@101: Chris@16: # ifndef BOOST_FUNCTIONAL_FACTORY_MAX_ARITY Chris@16: # define BOOST_FUNCTIONAL_FACTORY_MAX_ARITY 10 Chris@16: # elif BOOST_FUNCTIONAL_FACTORY_MAX_ARITY < 3 Chris@16: # undef BOOST_FUNCTIONAL_FACTORY_MAX_ARITY Chris@16: # define BOOST_FUNCTIONAL_FACTORY_MAX_ARITY 3 Chris@16: # endif Chris@16: Chris@16: namespace boost Chris@16: { Chris@16: enum factory_alloc_propagation Chris@16: { Chris@16: factory_alloc_for_pointee_and_deleter, Chris@16: factory_passes_alloc_to_smart_pointer Chris@16: }; Chris@16: Chris@101: #if defined(BOOST_FUNCTIONAL_FACTORY_SUPPORT_NONE_T) Chris@16: template< typename Pointer, class Allocator = boost::none_t, Chris@16: factory_alloc_propagation AP = factory_alloc_for_pointee_and_deleter > Chris@16: class factory; Chris@101: #else Chris@101: template< typename Pointer, class Allocator = void, Chris@101: factory_alloc_propagation AP = factory_alloc_for_pointee_and_deleter > Chris@101: class factory; Chris@101: #endif Chris@16: Chris@16: //----- ---- --- -- - - - - Chris@16: Chris@16: template< typename Pointer, factory_alloc_propagation AP > Chris@101: class factory Chris@16: { Chris@16: public: Chris@16: typedef typename boost::remove_cv::type result_type; Chris@16: typedef typename boost::pointee::type value_type; Chris@16: Chris@16: factory() Chris@16: { } Chris@16: Chris@16: # define BOOST_PP_FILENAME_1 Chris@16: # define BOOST_PP_ITERATION_LIMITS (0,BOOST_FUNCTIONAL_FACTORY_MAX_ARITY) Chris@16: # include BOOST_PP_ITERATE() Chris@16: }; Chris@16: Chris@101: #if defined(BOOST_FUNCTIONAL_FACTORY_SUPPORT_NONE_T) Chris@101: template< typename Pointer, factory_alloc_propagation AP > Chris@101: class factory Chris@101: : public factory Chris@101: {}; Chris@101: #endif Chris@101: Chris@16: template< class Pointer, class Allocator, factory_alloc_propagation AP > Chris@16: class factory Chris@16: : private Allocator::template rebind< typename boost::pointee< Chris@16: typename boost::remove_cv::type >::type >::other Chris@16: { Chris@16: public: Chris@16: typedef typename boost::remove_cv::type result_type; Chris@16: typedef typename boost::pointee::type value_type; Chris@16: Chris@16: typedef typename Allocator::template rebind::other Chris@16: allocator_type; Chris@16: Chris@16: explicit factory(allocator_type const & a = allocator_type()) Chris@16: : allocator_type(a) Chris@16: { } Chris@16: Chris@16: private: Chris@16: Chris@16: struct deleter Chris@16: : allocator_type Chris@16: { Chris@16: inline deleter(allocator_type const& that) Chris@16: : allocator_type(that) Chris@16: { } Chris@16: Chris@16: allocator_type& get_allocator() const Chris@16: { Chris@16: return *const_cast( Chris@16: static_cast(this)); Chris@16: } Chris@16: Chris@16: void operator()(value_type* ptr) const Chris@16: { Chris@16: if (!! ptr) ptr->~value_type(); Chris@16: const_cast(static_cast( Chris@16: this))->deallocate(ptr,1); Chris@16: } Chris@16: }; Chris@16: Chris@16: inline allocator_type& get_allocator() const Chris@16: { Chris@16: return *const_cast( Chris@16: static_cast(this)); Chris@16: } Chris@16: Chris@16: inline result_type make_pointer(value_type* ptr, boost::non_type< Chris@16: factory_alloc_propagation,factory_passes_alloc_to_smart_pointer>) Chris@16: const Chris@16: { Chris@16: return result_type(ptr,deleter(this->get_allocator())); Chris@16: } Chris@16: inline result_type make_pointer(value_type* ptr, boost::non_type< Chris@16: factory_alloc_propagation,factory_alloc_for_pointee_and_deleter>) Chris@16: const Chris@16: { Chris@16: return result_type(ptr,deleter(this->get_allocator()), Chris@16: this->get_allocator()); Chris@16: } Chris@16: Chris@16: public: Chris@16: Chris@16: # define BOOST_TMP_MACRO Chris@16: # define BOOST_PP_FILENAME_1 Chris@16: # define BOOST_PP_ITERATION_LIMITS (0,BOOST_FUNCTIONAL_FACTORY_MAX_ARITY) Chris@16: # include BOOST_PP_ITERATE() Chris@16: # undef BOOST_TMP_MACRO Chris@16: }; Chris@16: Chris@16: template< typename Pointer, class Allocator, factory_alloc_propagation AP > Chris@16: class factory; Chris@16: // forbidden, would create a dangling reference Chris@16: } Chris@16: Chris@16: # define BOOST_FUNCTIONAL_FACTORY_HPP_INCLUDED Chris@16: # else // defined(BOOST_PP_IS_ITERATING) Chris@16: # define N BOOST_PP_ITERATION() Chris@16: # if !defined(BOOST_TMP_MACRO) Chris@16: # if N > 0 Chris@16: template< BOOST_PP_ENUM_PARAMS(N, typename T) > Chris@16: # endif Chris@16: inline result_type operator()(BOOST_PP_ENUM_BINARY_PARAMS(N,T,& a)) const Chris@16: { Chris@16: return result_type( new value_type(BOOST_PP_ENUM_PARAMS(N,a)) ); Chris@16: } Chris@16: # else // defined(BOOST_TMP_MACRO) Chris@16: # if N > 0 Chris@16: template< BOOST_PP_ENUM_PARAMS(N, typename T) > Chris@16: # endif Chris@16: inline result_type operator()(BOOST_PP_ENUM_BINARY_PARAMS(N,T,& a)) const Chris@16: { Chris@16: value_type* memory = this->get_allocator().allocate(1); Chris@16: try Chris@16: { Chris@16: return make_pointer( Chris@16: new(memory) value_type(BOOST_PP_ENUM_PARAMS(N,a)), Chris@16: boost::non_type() ); Chris@16: } Chris@16: catch (...) { this->get_allocator().deallocate(memory,1); throw; } Chris@16: } Chris@16: # endif Chris@16: # undef N Chris@16: # endif // defined(BOOST_PP_IS_ITERATING) Chris@16: Chris@16: #endif // include guard Chris@16: