poly_function.hpp 6.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234
  1. ///////////////////////////////////////////////////////////////////////////////
  2. /// \file poly_function.hpp
  3. /// A wrapper that makes a tr1-style function object that handles const
  4. /// and non-const refs and reference_wrapper arguments, too, and forwards
  5. /// the arguments on to the specified implementation.
  6. //
  7. // Copyright 2008 Eric Niebler. Distributed under the Boost
  8. // Software License, Version 1.0. (See accompanying file
  9. // LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
  10. #ifndef BOOST_PROTO_DETAIL_POLY_FUNCTION_EAN_2008_05_02
  11. #define BOOST_PROTO_DETAIL_POLY_FUNCTION_EAN_2008_05_02
  12. #include <boost/ref.hpp>
  13. #include <boost/mpl/bool.hpp>
  14. #include <boost/mpl/void.hpp>
  15. #include <boost/mpl/size_t.hpp>
  16. #include <boost/mpl/eval_if.hpp>
  17. #include <boost/preprocessor/cat.hpp>
  18. #include <boost/preprocessor/facilities/intercept.hpp>
  19. #include <boost/preprocessor/iteration/iterate.hpp>
  20. #include <boost/preprocessor/repetition/enum.hpp>
  21. #include <boost/preprocessor/repetition/enum_params.hpp>
  22. #include <boost/preprocessor/repetition/enum_trailing_params.hpp>
  23. #include <boost/preprocessor/repetition/enum_binary_params.hpp>
  24. #include <boost/proto/proto_fwd.hpp>
  25. #include <boost/proto/detail/is_noncopyable.hpp>
  26. #ifdef _MSC_VER
  27. # pragma warning(push)
  28. # pragma warning(disable: 4181) // const applied to reference type
  29. #endif
  30. namespace boost { namespace proto { namespace detail
  31. {
  32. ////////////////////////////////////////////////////////////////////////////////////////////////
  33. template<typename T>
  34. struct normalize_arg
  35. {
  36. typedef typename mpl::if_c<is_noncopyable<T>::value, T &, T>::type type;
  37. typedef T &reference;
  38. };
  39. template<typename T>
  40. struct normalize_arg<T const>
  41. {
  42. typedef typename mpl::if_c<is_noncopyable<T>::value, T const &, T>::type type;
  43. typedef T const &reference;
  44. };
  45. template<typename T>
  46. struct normalize_arg<T &>
  47. {
  48. typedef typename mpl::if_c<is_noncopyable<T>::value, T &, T>::type type;
  49. typedef T &reference;
  50. };
  51. template<typename T>
  52. struct normalize_arg<T const &>
  53. {
  54. typedef typename mpl::if_c<is_noncopyable<T>::value, T const &, T>::type type;
  55. typedef T const &reference;
  56. };
  57. template<typename T>
  58. struct normalize_arg<boost::reference_wrapper<T> >
  59. {
  60. typedef T &type;
  61. typedef T &reference;
  62. };
  63. template<typename T>
  64. struct normalize_arg<boost::reference_wrapper<T> const>
  65. {
  66. typedef T &type;
  67. typedef T &reference;
  68. };
  69. template<typename T>
  70. struct normalize_arg<boost::reference_wrapper<T> &>
  71. {
  72. typedef T &type;
  73. typedef T &reference;
  74. };
  75. template<typename T>
  76. struct normalize_arg<boost::reference_wrapper<T> const &>
  77. {
  78. typedef T &type;
  79. typedef T &reference;
  80. };
  81. ////////////////////////////////////////////////////////////////////////////////////////////////
  82. template<typename T>
  83. struct arg
  84. {
  85. typedef T const &type;
  86. arg(type t)
  87. : value(t)
  88. {}
  89. operator type() const
  90. {
  91. return this->value;
  92. }
  93. type operator()() const
  94. {
  95. return this->value;
  96. }
  97. private:
  98. arg &operator =(arg const &);
  99. type value;
  100. };
  101. template<typename T>
  102. struct arg<T &>
  103. {
  104. typedef T &type;
  105. arg(type t)
  106. : value(t)
  107. {}
  108. operator type() const
  109. {
  110. return this->value;
  111. }
  112. type operator()() const
  113. {
  114. return this->value;
  115. }
  116. private:
  117. arg &operator =(arg const &);
  118. type value;
  119. };
  120. ////////////////////////////////////////////////////////////////////////////////////////////////
  121. template<typename T, typename Void = void>
  122. struct is_poly_function
  123. : mpl::false_
  124. {};
  125. template<typename T>
  126. struct is_poly_function<T, typename T::is_poly_function_base_>
  127. : mpl::true_
  128. {};
  129. ////////////////////////////////////////////////////////////////////////////////////////////////
  130. #define BOOST_PROTO_POLY_FUNCTION() \
  131. typedef void is_poly_function_base_; \
  132. /**/
  133. ////////////////////////////////////////////////////////////////////////////////////////////////
  134. struct poly_function_base
  135. {
  136. /// INTERNAL ONLY
  137. BOOST_PROTO_POLY_FUNCTION()
  138. };
  139. ////////////////////////////////////////////////////////////////////////////////////////////////
  140. template<typename Derived, typename NullaryResult = void>
  141. struct poly_function
  142. : poly_function_base
  143. {
  144. template<typename Sig>
  145. struct result;
  146. template<typename This>
  147. struct result<This()>
  148. : Derived::template impl<>
  149. {
  150. typedef typename result::result_type type;
  151. };
  152. NullaryResult operator()() const
  153. {
  154. result<Derived const()> impl;
  155. return impl();
  156. }
  157. #include <boost/proto/detail/poly_function_funop.hpp>
  158. };
  159. template<typename T>
  160. struct wrap_t;
  161. typedef char poly_function_t;
  162. typedef char (&mono_function_t)[2];
  163. typedef char (&unknown_function_t)[3];
  164. template<typename T> poly_function_t test_poly_function(T *, wrap_t<typename T::is_poly_function_base_> * = 0);
  165. template<typename T> mono_function_t test_poly_function(T *, wrap_t<typename T::result_type> * = 0);
  166. template<typename T> unknown_function_t test_poly_function(T *, ...);
  167. ////////////////////////////////////////////////////////////////////////////////////////////////
  168. template<typename Fun, typename Sig, typename Switch = mpl::size_t<sizeof(test_poly_function<Fun>(0,0))> >
  169. struct poly_function_traits
  170. {
  171. typedef typename Fun::template result<Sig>::type result_type;
  172. typedef Fun function_type;
  173. };
  174. ////////////////////////////////////////////////////////////////////////////////////////////////
  175. template<typename Fun, typename Sig>
  176. struct poly_function_traits<Fun, Sig, mpl::size_t<sizeof(mono_function_t)> >
  177. {
  178. typedef typename Fun::result_type result_type;
  179. typedef Fun function_type;
  180. };
  181. ////////////////////////////////////////////////////////////////////////////////////////////////
  182. template<typename PolyFunSig, bool IsPolyFunction>
  183. struct as_mono_function_impl;
  184. ////////////////////////////////////////////////////////////////////////////////////////////////
  185. template<typename PolyFunSig>
  186. struct as_mono_function;
  187. #include <boost/proto/detail/poly_function_traits.hpp>
  188. }}} // namespace boost::proto::detail
  189. #ifdef _MSC_VER
  190. # pragma warning(pop)
  191. #endif
  192. #endif