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 11 #ifndef BOOST_PROTO_DETAIL_POLY_FUNCTION_EAN_2008_05_02 12 #define BOOST_PROTO_DETAIL_POLY_FUNCTION_EAN_2008_05_02 13 14 #include <boost/ref.hpp> 15 #include <boost/mpl/bool.hpp> 16 #include <boost/mpl/void.hpp> 17 #include <boost/mpl/size_t.hpp> 18 #include <boost/mpl/eval_if.hpp> 19 #include <boost/preprocessor/cat.hpp> 20 #include <boost/preprocessor/facilities/intercept.hpp> 21 #include <boost/preprocessor/iteration/iterate.hpp> 22 #include <boost/preprocessor/repetition/enum.hpp> 23 #include <boost/preprocessor/repetition/enum_params.hpp> 24 #include <boost/preprocessor/repetition/enum_trailing_params.hpp> 25 #include <boost/preprocessor/repetition/enum_binary_params.hpp> 26 #include <boost/proto/proto_fwd.hpp> 27 #include <boost/proto/detail/is_noncopyable.hpp> 28 29 #ifdef _MSC_VER 30 # pragma warning(push) 31 # pragma warning(disable: 4181) // const applied to reference type 32 #endif 33 34 namespace boost { namespace proto { namespace detail 35 { 36 37 //////////////////////////////////////////////////////////////////////////////////////////////// 38 template<typename T> 39 struct normalize_arg 40 { 41 typedef typename mpl::if_c<is_noncopyable<T>::value, T &, T>::type type; 42 typedef T &reference; 43 }; 44 45 template<typename T> 46 struct normalize_arg<T const> 47 { 48 typedef typename mpl::if_c<is_noncopyable<T>::value, T const &, T>::type type; 49 typedef T const &reference; 50 }; 51 52 template<typename T> 53 struct normalize_arg<T &> 54 { 55 typedef typename mpl::if_c<is_noncopyable<T>::value, T &, T>::type type; 56 typedef T &reference; 57 }; 58 59 template<typename T> 60 struct normalize_arg<T const &> 61 { 62 typedef typename mpl::if_c<is_noncopyable<T>::value, T const &, T>::type type; 63 typedef T const &reference; 64 }; 65 66 template<typename T> 67 struct normalize_arg<boost::reference_wrapper<T> > 68 { 69 typedef T &type; 70 typedef T &reference; 71 }; 72 73 template<typename T> 74 struct normalize_arg<boost::reference_wrapper<T> const> 75 { 76 typedef T &type; 77 typedef T &reference; 78 }; 79 80 template<typename T> 81 struct normalize_arg<boost::reference_wrapper<T> &> 82 { 83 typedef T &type; 84 typedef T &reference; 85 }; 86 87 template<typename T> 88 struct normalize_arg<boost::reference_wrapper<T> const &> 89 { 90 typedef T &type; 91 typedef T &reference; 92 }; 93 94 //////////////////////////////////////////////////////////////////////////////////////////////// 95 template<typename T> 96 struct arg 97 { 98 typedef T const &type; 99 argboost::proto::detail::arg100 arg(type t) 101 : value(t) 102 {} 103 operator typeboost::proto::detail::arg104 operator type() const 105 { 106 return this->value; 107 } 108 operator ()boost::proto::detail::arg109 type operator()() const 110 { 111 return this->value; 112 } 113 114 BOOST_DELETED_FUNCTION(arg &operator =(arg const &)) 115 private: 116 type value; 117 }; 118 119 template<typename T> 120 struct arg<T &> 121 { 122 typedef T &type; 123 argboost::proto::detail::arg124 arg(type t) 125 : value(t) 126 {} 127 operator typeboost::proto::detail::arg128 operator type() const 129 { 130 return this->value; 131 } 132 operator ()boost::proto::detail::arg133 type operator()() const 134 { 135 return this->value; 136 } 137 138 BOOST_DELETED_FUNCTION(arg &operator =(arg const &)) 139 private: 140 type value; 141 }; 142 143 //////////////////////////////////////////////////////////////////////////////////////////////// 144 template<typename T, typename Void = void> 145 struct is_poly_function 146 : mpl::false_ 147 {}; 148 149 template<typename T> 150 struct is_poly_function<T, typename T::is_poly_function_base_> 151 : mpl::true_ 152 {}; 153 154 //////////////////////////////////////////////////////////////////////////////////////////////// 155 #define BOOST_PROTO_POLY_FUNCTION() \ 156 typedef void is_poly_function_base_; \ 157 /**/ 158 159 //////////////////////////////////////////////////////////////////////////////////////////////// 160 struct poly_function_base 161 { 162 /// INTERNAL ONLY 163 BOOST_PROTO_POLY_FUNCTION() 164 }; 165 166 //////////////////////////////////////////////////////////////////////////////////////////////// 167 template<typename Derived, typename NullaryResult = void> 168 struct poly_function 169 : poly_function_base 170 { 171 template<typename Sig> 172 struct result; 173 174 template<typename This> 175 struct result<This()> 176 : Derived::template impl<> 177 { 178 typedef typename result::result_type type; 179 }; 180 operator ()boost::proto::detail::poly_function181 NullaryResult operator()() const 182 { 183 result<Derived const()> impl; 184 return impl(); 185 } 186 187 #include <boost/proto/detail/poly_function_funop.hpp> 188 }; 189 190 template<typename T> 191 struct wrap_t; 192 193 typedef char poly_function_t; 194 typedef char (&mono_function_t)[2]; 195 typedef char (&unknown_function_t)[3]; 196 197 template<typename T> poly_function_t test_poly_function(T *, wrap_t<typename T::is_poly_function_base_> * = 0); 198 template<typename T> mono_function_t test_poly_function(T *, wrap_t<typename T::result_type> * = 0); 199 template<typename T> unknown_function_t test_poly_function(T *, ...); 200 201 //////////////////////////////////////////////////////////////////////////////////////////////// 202 template<typename Fun, typename Sig, typename Switch = mpl::size_t<sizeof(test_poly_function<Fun>(0,0))> > 203 struct poly_function_traits 204 { 205 typedef typename Fun::template result<Sig>::type result_type; 206 typedef Fun function_type; 207 }; 208 209 //////////////////////////////////////////////////////////////////////////////////////////////// 210 template<typename Fun, typename Sig> 211 struct poly_function_traits<Fun, Sig, mpl::size_t<sizeof(mono_function_t)> > 212 { 213 typedef typename Fun::result_type result_type; 214 typedef Fun function_type; 215 }; 216 217 //////////////////////////////////////////////////////////////////////////////////////////////// 218 template<typename PolyFunSig, bool IsPolyFunction> 219 struct as_mono_function_impl; 220 221 //////////////////////////////////////////////////////////////////////////////////////////////// 222 template<typename PolyFunSig> 223 struct as_mono_function; 224 225 #include <boost/proto/detail/poly_function_traits.hpp> 226 227 }}} // namespace boost::proto::detail 228 229 #ifdef _MSC_VER 230 # pragma warning(pop) 231 #endif 232 233 #endif 234 235