factory.hpp 5.3 KB

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