1 /////////////////////////////////////////////////////////////////////////////// 2 /// \file arg.hpp 3 /// Contains definition of the argN transforms. 4 // 5 // Copyright 2008 Eric Niebler. Distributed under the Boost 6 // Software License, Version 1.0. (See accompanying file 7 // LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) 8 9 #ifndef BOOST_PROTO_TRANSFORM_ARG_HPP_EAN_11_01_2007 10 #define BOOST_PROTO_TRANSFORM_ARG_HPP_EAN_11_01_2007 11 12 #include <boost/mpl/if.hpp> 13 #include <boost/proto/proto_fwd.hpp> 14 #include <boost/proto/traits.hpp> 15 #include <boost/proto/transform/impl.hpp> 16 #include <boost/type_traits/is_array.hpp> 17 #include <boost/proto/transform/env.hpp> 18 19 namespace boost { namespace proto 20 { 21 22 /// \brief A PrimitiveTransform that returns the current expression 23 /// unmodified 24 /// 25 /// Example: 26 /// 27 /// \code 28 /// proto::terminal<int>::type i = {42}; 29 /// proto::terminal<int>::type & j = proto::_expr()(i); 30 /// assert( boost::addressof(i) == boost::addressof(j) ); 31 /// \endcode 32 struct _expr : transform<_expr> 33 { 34 template<typename Expr, typename State, typename Data> 35 struct impl : transform_impl<Expr, State, Data> 36 { 37 typedef Expr result_type; 38 39 /// Returns the current expression. 40 /// \param e The current expression. 41 /// \return \c e 42 /// \throw nothrow BOOST_PROTO_RETURN_TYPE_STRICT_LOOSEboost::proto::_expr::impl43 BOOST_PROTO_RETURN_TYPE_STRICT_LOOSE(result_type, typename impl::expr_param) 44 operator()( 45 typename impl::expr_param e 46 , typename impl::state_param 47 , typename impl::data_param 48 ) const 49 { 50 return e; 51 } 52 }; 53 }; 54 55 /// \brief A PrimitiveTransform that returns the current state 56 /// unmodified 57 /// 58 /// Example: 59 /// 60 /// \code 61 /// proto::terminal<int>::type i = {42}; 62 /// char ch = proto::_state()(i, 'a'); 63 /// assert( ch == 'a' ); 64 /// \endcode 65 struct _state : transform<_state> 66 { 67 template<typename Expr, typename State, typename Data> 68 struct impl : transform_impl<Expr, State, Data> 69 { 70 typedef State result_type; 71 72 /// Returns the current state. 73 /// \param s The current state. 74 /// \return \c s 75 /// \throw nothrow BOOST_PROTO_RETURN_TYPE_STRICT_LOOSEboost::proto::_state::impl76 BOOST_PROTO_RETURN_TYPE_STRICT_LOOSE(result_type, typename impl::state_param) 77 operator ()( 78 typename impl::expr_param 79 , typename impl::state_param s 80 , typename impl::data_param 81 ) const 82 { 83 return s; 84 } 85 }; 86 }; 87 88 /// \brief A PrimitiveTransform that returns the current data 89 /// unmodified 90 /// 91 /// Example: 92 /// 93 /// \code 94 /// proto::terminal<int>::type i = {42}; 95 /// std::string str("hello"); 96 /// std::string & data = proto::_data()(i, 'a', str); 97 /// assert( &str == &data ); 98 /// \endcode 99 struct _data : transform<_data> 100 { 101 template<typename Expr, typename State, typename Data> 102 struct impl 103 : mpl::if_c< 104 is_env<Data>::value 105 , _env_var<data_type> 106 , _env 107 >::type::template impl<Expr, State, Data> 108 {}; 109 }; 110 111 /// \brief A PrimitiveTransform that returns N-th child of the current 112 /// expression. 113 /// 114 /// Example: 115 /// 116 /// \code 117 /// proto::terminal<int>::type i = {42}; 118 /// proto::terminal<int>::type & j = proto::_child_c<0>()(-i); 119 /// assert( boost::addressof(i) == boost::addressof(j) ); 120 /// \endcode 121 template<int N> 122 struct _child_c : transform<_child_c<N> > 123 { 124 template<typename Expr, typename State, typename Data> 125 struct impl : transform_impl<Expr, State, Data> 126 { 127 typedef 128 typename result_of::child_c<Expr, N>::type 129 result_type; 130 131 /// Returns the N-th child of \c e 132 /// \pre <tt>arity_of\<Expr\>::value \> N</tt> 133 /// \param e The current expression. 134 /// \return <tt>proto::child_c\<N\>(e)</tt> 135 /// \throw nothrow 136 #ifdef BOOST_PROTO_STRICT_RESULT_OF 137 result_type 138 #else 139 typename result_of::child_c<typename impl::expr_param, N>::type 140 #endif operator ()boost::proto::_child_c::impl141 operator ()( 142 typename impl::expr_param e 143 , typename impl::state_param 144 , typename impl::data_param 145 ) const 146 { 147 return proto::child_c<N>(e); 148 } 149 }; 150 }; 151 152 /// \brief A PrimitiveTransform that returns the value of the 153 /// current terminal expression. 154 /// 155 /// Example: 156 /// 157 /// \code 158 /// proto::terminal<int>::type i = {42}; 159 /// int j = proto::_value()(i); 160 /// assert( 42 == j ); 161 /// \endcode 162 struct _value : transform<_value> 163 { 164 template<typename Expr, typename State, typename Data> 165 struct impl : transform_impl<Expr, State, Data> 166 { 167 typedef 168 typename result_of::value<Expr>::type 169 result_type; 170 171 /// Returns the value of the specified terminal expression. 172 /// \pre <tt>arity_of\<Expr\>::value == 0</tt>. 173 /// \param e The current expression. 174 /// \return <tt>proto::value(e)</tt> 175 /// \throw nothrow 176 #ifdef BOOST_PROTO_STRICT_RESULT_OF 177 typename mpl::if_c<is_array<result_type>::value, result_type &, result_type>::type 178 #else 179 typename result_of::value<typename impl::expr_param>::type 180 #endif operator ()boost::proto::_value::impl181 operator ()( 182 typename impl::expr_param e 183 , typename impl::state_param 184 , typename impl::data_param 185 ) const 186 { 187 return proto::value(e); 188 } 189 }; 190 }; 191 192 /// \brief A PrimitiveTransform that does nothing 193 /// and returns void. 194 struct _void : transform<_void> 195 { 196 template<typename Expr, typename State, typename Data> 197 struct impl : transform_impl<Expr, State, Data> 198 { 199 typedef void result_type; 200 201 /// Does nothing and returns void operator ()boost::proto::_void::impl202 void operator ()( 203 typename impl::expr_param 204 , typename impl::state_param 205 , typename impl::data_param 206 ) const 207 {} 208 }; 209 }; 210 211 /// \brief A unary CallableTransform that wraps its argument 212 /// in a \c boost::reference_wrapper\<\>. 213 /// 214 /// Example: 215 /// 216 /// \code 217 /// proto::terminal<int>::type i = {42}; 218 /// boost::reference_wrapper<proto::terminal<int>::type> j 219 /// = proto::when<_, proto::_byref(_)>()(i); 220 /// assert( boost::addressof(i) == boost::addressof(j.get()) ); 221 /// \endcode 222 struct _byref : callable 223 { 224 template<typename Sig> 225 struct result; 226 227 template<typename This, typename T> 228 struct result<This(T)> 229 { 230 typedef boost::reference_wrapper<T const> const type; 231 }; 232 233 template<typename This, typename T> 234 struct result<This(T &)> 235 { 236 typedef boost::reference_wrapper<T> const type; 237 }; 238 239 /// Wrap the parameter \c t in a \c boost::reference_wrapper\<\> 240 /// \param t The object to wrap 241 /// \return <tt>boost::ref(t)</tt> 242 /// \throw nothrow 243 template<typename T> operator ()boost::proto::_byref244 boost::reference_wrapper<T> const operator ()(T &t) const 245 { 246 return boost::reference_wrapper<T>(t); 247 } 248 249 /// \overload 250 /// 251 template<typename T> operator ()boost::proto::_byref252 boost::reference_wrapper<T const> const operator ()(T const &t) const 253 { 254 return boost::reference_wrapper<T const>(t); 255 } 256 }; 257 258 /// \brief A unary CallableTransform that strips references 259 /// and \c boost::reference_wrapper\<\> from its argument. 260 /// 261 /// Example: 262 /// 263 /// \code 264 /// proto::terminal<int>::type i = {42}; 265 /// int j = 67; 266 /// int k = proto::when<_, proto::_byval(proto::_state)>()(i, boost::ref(j)); 267 /// assert( 67 == k ); 268 /// \endcode 269 struct _byval : callable 270 { 271 template<typename Sig> 272 struct result; 273 274 template<typename This, typename T> 275 struct result<This(T)> 276 { 277 typedef T type; 278 }; 279 280 template<typename This, typename T> 281 struct result<This(T &)> 282 : result<This(T)> 283 {}; 284 285 template<typename This, typename T> 286 struct result<This(boost::reference_wrapper<T>)> 287 : result<This(T)> 288 {}; 289 290 /// \param t The object to unref 291 /// \return <tt>t</tt> 292 /// \throw nothrow 293 template<typename T> operator ()boost::proto::_byval294 T operator ()(T const &t) const 295 { 296 return t; 297 } 298 299 /// \overload 300 /// 301 template<typename T> operator ()boost::proto::_byval302 T operator ()(boost::reference_wrapper<T> const &t) const 303 { 304 return t; 305 } 306 }; 307 308 /// INTERNAL ONLY 309 /// 310 template<> 311 struct is_callable<_expr> 312 : mpl::true_ 313 {}; 314 315 /// INTERNAL ONLY 316 /// 317 template<> 318 struct is_callable<_state> 319 : mpl::true_ 320 {}; 321 322 /// INTERNAL ONLY 323 /// 324 template<> 325 struct is_callable<_data> 326 : mpl::true_ 327 {}; 328 329 /// INTERNAL ONLY 330 /// 331 template<int N> 332 struct is_callable<_child_c<N> > 333 : mpl::true_ 334 {}; 335 336 /// INTERNAL ONLY 337 /// 338 template<> 339 struct is_callable<_value> 340 : mpl::true_ 341 {}; 342 343 /// INTERNAL ONLY 344 /// 345 template<> 346 struct is_callable<_byref> 347 : mpl::true_ 348 {}; 349 350 /// INTERNAL ONLY 351 /// 352 template<> 353 struct is_callable<_byval> 354 : mpl::true_ 355 {}; 356 357 }} 358 359 #endif 360