annotate DEPENDENCIES/generic/include/boost/proto/transform/call.hpp @ 133:4acb5d8d80b6 tip

Don't fail environmental check if README.md exists (but .txt and no-suffix don't)
author Chris Cannam
date Tue, 30 Jul 2019 12:25:44 +0100
parents c530137014c0
children
rev   line source
Chris@16 1 ///////////////////////////////////////////////////////////////////////////////
Chris@16 2 /// \file call.hpp
Chris@16 3 /// Contains definition of the call<> transform.
Chris@16 4 //
Chris@16 5 // Copyright 2008 Eric Niebler. Distributed under the Boost
Chris@16 6 // Software License, Version 1.0. (See accompanying file
Chris@16 7 // LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
Chris@16 8
Chris@16 9 #ifndef BOOST_PROTO_TRANSFORM_CALL_HPP_EAN_11_02_2007
Chris@16 10 #define BOOST_PROTO_TRANSFORM_CALL_HPP_EAN_11_02_2007
Chris@16 11
Chris@101 12 #if defined(_MSC_VER)
Chris@16 13 # pragma warning(push)
Chris@16 14 # pragma warning(disable: 4714) // function 'xxx' marked as __forceinline not inlined
Chris@16 15 #endif
Chris@16 16
Chris@16 17 #include <boost/preprocessor/cat.hpp>
Chris@16 18 #include <boost/preprocessor/facilities/intercept.hpp>
Chris@16 19 #include <boost/preprocessor/iteration/iterate.hpp>
Chris@16 20 #include <boost/preprocessor/repetition/enum.hpp>
Chris@16 21 #include <boost/preprocessor/repetition/repeat.hpp>
Chris@16 22 #include <boost/preprocessor/repetition/enum_params.hpp>
Chris@16 23 #include <boost/preprocessor/repetition/enum_binary_params.hpp>
Chris@16 24 #include <boost/preprocessor/repetition/enum_trailing_params.hpp>
Chris@16 25 #include <boost/ref.hpp>
Chris@16 26 #include <boost/utility/result_of.hpp>
Chris@16 27 #include <boost/proto/proto_fwd.hpp>
Chris@16 28 #include <boost/proto/traits.hpp>
Chris@16 29 #include <boost/proto/transform/impl.hpp>
Chris@16 30 #include <boost/proto/detail/as_lvalue.hpp>
Chris@16 31 #include <boost/proto/detail/poly_function.hpp>
Chris@16 32 #include <boost/proto/transform/detail/pack.hpp>
Chris@16 33
Chris@16 34 namespace boost { namespace proto
Chris@16 35 {
Chris@16 36 /// \brief Wrap \c PrimitiveTransform so that <tt>when\<\></tt> knows
Chris@16 37 /// it is callable. Requires that the parameter is actually a
Chris@16 38 /// PrimitiveTransform.
Chris@16 39 ///
Chris@16 40 /// This form of <tt>call\<\></tt> is useful for annotating an
Chris@16 41 /// arbitrary PrimitiveTransform as callable when using it with
Chris@16 42 /// <tt>when\<\></tt>. Consider the following transform, which
Chris@16 43 /// is parameterized with another transform.
Chris@16 44 ///
Chris@16 45 /// \code
Chris@16 46 /// template<typename Grammar>
Chris@16 47 /// struct Foo
Chris@16 48 /// : when<
Chris@16 49 /// unary_plus<Grammar>
Chris@16 50 /// , Grammar(_child) // May or may not work.
Chris@16 51 /// >
Chris@16 52 /// {};
Chris@16 53 /// \endcode
Chris@16 54 ///
Chris@16 55 /// The problem with the above is that <tt>when\<\></tt> may or
Chris@16 56 /// may not recognize \c Grammar as callable, depending on how
Chris@16 57 /// \c Grammar is implemented. (See <tt>is_callable\<\></tt> for
Chris@16 58 /// a discussion of this issue.) You can guard against
Chris@16 59 /// the issue by wrapping \c Grammar in <tt>call\<\></tt>, such
Chris@16 60 /// as:
Chris@16 61 ///
Chris@16 62 /// \code
Chris@16 63 /// template<typename Grammar>
Chris@16 64 /// struct Foo
Chris@16 65 /// : when<
Chris@16 66 /// unary_plus<Grammar>
Chris@16 67 /// , call<Grammar>(_child) // OK, this works
Chris@16 68 /// >
Chris@16 69 /// {};
Chris@16 70 /// \endcode
Chris@16 71 ///
Chris@16 72 /// The above could also have been written as:
Chris@16 73 ///
Chris@16 74 /// \code
Chris@16 75 /// template<typename Grammar>
Chris@16 76 /// struct Foo
Chris@16 77 /// : when<
Chris@16 78 /// unary_plus<Grammar>
Chris@16 79 /// , call<Grammar(_child)> // OK, this works, too
Chris@16 80 /// >
Chris@16 81 /// {};
Chris@16 82 /// \endcode
Chris@16 83 template<typename PrimitiveTransform>
Chris@16 84 struct call
Chris@16 85 : PrimitiveTransform
Chris@16 86 {};
Chris@16 87
Chris@16 88 /// \brief A specialization that treats function pointer Transforms as
Chris@16 89 /// if they were function type Transforms.
Chris@16 90 ///
Chris@16 91 /// This specialization requires that \c Fun is actually a function type.
Chris@16 92 ///
Chris@16 93 /// This specialization is required for nested transforms such as
Chris@16 94 /// <tt>call\<T0(T1(_))\></tt>. In C++, functions that are used as
Chris@16 95 /// parameters to other functions automatically decay to funtion
Chris@16 96 /// pointer types. In other words, the type <tt>T0(T1(_))</tt> is
Chris@16 97 /// indistinguishable from <tt>T0(T1(*)(_))</tt>. This specialization
Chris@16 98 /// is required to handle these nested function pointer type transforms
Chris@16 99 /// properly.
Chris@16 100 template<typename Fun>
Chris@16 101 struct call<Fun *>
Chris@16 102 : call<Fun>
Chris@16 103 {};
Chris@16 104
Chris@16 105 /// INTERNAL ONLY
Chris@16 106 template<typename Fun>
Chris@16 107 struct call<detail::msvc_fun_workaround<Fun> >
Chris@16 108 : call<Fun>
Chris@16 109 {};
Chris@16 110
Chris@16 111 /// \brief Either call the PolymorphicFunctionObject with 0
Chris@16 112 /// arguments, or invoke the PrimitiveTransform with 3
Chris@16 113 /// arguments.
Chris@16 114 template<typename Fun>
Chris@16 115 struct call<Fun()> : transform<call<Fun()> >
Chris@16 116 {
Chris@16 117 /// INTERNAL ONLY
Chris@16 118 template<typename Expr, typename State, typename Data, bool B>
Chris@16 119 struct impl2
Chris@16 120 : transform_impl<Expr, State, Data>
Chris@16 121 {
Chris@16 122 typedef typename BOOST_PROTO_RESULT_OF<Fun()>::type result_type;
Chris@16 123
Chris@16 124 BOOST_FORCEINLINE
Chris@16 125 result_type operator()(
Chris@16 126 typename impl2::expr_param
Chris@16 127 , typename impl2::state_param
Chris@16 128 , typename impl2::data_param
Chris@16 129 ) const
Chris@16 130 {
Chris@16 131 return Fun()();
Chris@16 132 }
Chris@16 133 };
Chris@16 134
Chris@16 135 /// INTERNAL ONLY
Chris@16 136 template<typename Expr, typename State, typename Data>
Chris@16 137 struct impl2<Expr, State, Data, true>
Chris@16 138 : Fun::template impl<Expr, State, Data>
Chris@16 139 {};
Chris@16 140
Chris@16 141 /// Either call the PolymorphicFunctionObject \c Fun with 0 arguments; or
Chris@16 142 /// invoke the PrimitiveTransform \c Fun with 3 arguments: the current
Chris@16 143 /// expression, state, and data.
Chris@16 144 ///
Chris@16 145 /// If \c Fun is a nullary PolymorphicFunctionObject, return <tt>Fun()()</tt>.
Chris@16 146 /// Otherwise, return <tt>Fun()(e, s, d)</tt>.
Chris@16 147 ///
Chris@16 148 /// \param e The current expression
Chris@16 149 /// \param s The current state
Chris@16 150 /// \param d An arbitrary data
Chris@16 151
Chris@16 152 /// If \c Fun is a nullary PolymorphicFunctionObject, \c type is a typedef
Chris@16 153 /// for <tt>boost::result_of\<Fun()\>::type</tt>. Otherwise, it is
Chris@16 154 /// a typedef for <tt>boost::result_of\<Fun(Expr, State, Data)\>::type</tt>.
Chris@16 155 template<typename Expr, typename State, typename Data>
Chris@16 156 struct impl
Chris@16 157 : impl2<Expr, State, Data, detail::is_transform_<Fun>::value>
Chris@16 158 {};
Chris@16 159 };
Chris@16 160
Chris@16 161 /// \brief Either call the PolymorphicFunctionObject with 1
Chris@16 162 /// argument, or invoke the PrimitiveTransform with 3
Chris@16 163 /// arguments.
Chris@16 164 template<typename Fun, typename A0>
Chris@16 165 struct call<Fun(A0)> : transform<call<Fun(A0)> >
Chris@16 166 {
Chris@16 167 template<typename Expr, typename State, typename Data, bool B>
Chris@16 168 struct impl2
Chris@16 169 : transform_impl<Expr, State, Data>
Chris@16 170 {
Chris@16 171 typedef typename when<_, A0>::template impl<Expr, State, Data>::result_type a0;
Chris@16 172 typedef typename detail::poly_function_traits<Fun, Fun(a0)>::result_type result_type;
Chris@16 173
Chris@16 174 BOOST_FORCEINLINE
Chris@16 175 result_type operator ()(
Chris@16 176 typename impl2::expr_param e
Chris@16 177 , typename impl2::state_param s
Chris@16 178 , typename impl2::data_param d
Chris@16 179 ) const
Chris@16 180 {
Chris@16 181 return typename detail::poly_function_traits<Fun, Fun(a0)>::function_type()(
Chris@16 182 detail::as_lvalue(typename when<_, A0>::template impl<Expr, State, Data>()(e, s, d))
Chris@16 183 );
Chris@16 184 }
Chris@16 185 };
Chris@16 186
Chris@16 187 template<typename Expr, typename State, typename Data>
Chris@16 188 struct impl2<Expr, State, Data, true>
Chris@16 189 : transform_impl<Expr, State, Data>
Chris@16 190 {
Chris@16 191 typedef typename when<_, A0>::template impl<Expr, State, Data>::result_type a0;
Chris@16 192 typedef typename Fun::template impl<a0, State, Data>::result_type result_type;
Chris@16 193
Chris@16 194 BOOST_FORCEINLINE
Chris@16 195 result_type operator ()(
Chris@16 196 typename impl2::expr_param e
Chris@16 197 , typename impl2::state_param s
Chris@16 198 , typename impl2::data_param d
Chris@16 199 ) const
Chris@16 200 {
Chris@16 201 return typename Fun::template impl<a0, State, Data>()(
Chris@16 202 typename when<_, A0>::template impl<Expr, State, Data>()(e, s, d)
Chris@16 203 , s
Chris@16 204 , d
Chris@16 205 );
Chris@16 206 }
Chris@16 207 };
Chris@16 208 /// Let \c x be <tt>when\<_, A0\>()(e, s, d)</tt> and \c X
Chris@16 209 /// be the type of \c x.
Chris@16 210 /// If \c Fun is a unary PolymorphicFunctionObject that accepts \c x,
Chris@16 211 /// then \c type is a typedef for <tt>boost::result_of\<Fun(X)\>::type</tt>.
Chris@16 212 /// Otherwise, it is a typedef for <tt>boost::result_of\<Fun(X, State, Data)\>::type</tt>.
Chris@16 213
Chris@16 214 /// Either call the PolymorphicFunctionObject with 1 argument:
Chris@16 215 /// the result of applying the \c A0 transform; or
Chris@16 216 /// invoke the PrimitiveTransform with 3 arguments:
Chris@16 217 /// result of applying the \c A0 transform, the state, and the
Chris@16 218 /// data.
Chris@16 219 ///
Chris@16 220 /// Let \c x be <tt>when\<_, A0\>()(e, s, d)</tt>.
Chris@16 221 /// If \c Fun is a unary PolymorphicFunctionObject that accepts \c x,
Chris@16 222 /// then return <tt>Fun()(x)</tt>. Otherwise, return
Chris@16 223 /// <tt>Fun()(x, s, d)</tt>.
Chris@16 224 ///
Chris@16 225 /// \param e The current expression
Chris@16 226 /// \param s The current state
Chris@16 227 /// \param d An arbitrary data
Chris@16 228 template<typename Expr, typename State, typename Data>
Chris@16 229 struct impl
Chris@16 230 : impl2<Expr, State, Data, detail::is_transform_<Fun>::value>
Chris@16 231 {};
Chris@16 232 };
Chris@16 233
Chris@16 234 /// \brief Either call the PolymorphicFunctionObject with 2
Chris@16 235 /// arguments, or invoke the PrimitiveTransform with 3
Chris@16 236 /// arguments.
Chris@16 237 template<typename Fun, typename A0, typename A1>
Chris@16 238 struct call<Fun(A0, A1)> : transform<call<Fun(A0, A1)> >
Chris@16 239 {
Chris@16 240 template<typename Expr, typename State, typename Data, bool B>
Chris@16 241 struct impl2
Chris@16 242 : transform_impl<Expr, State, Data>
Chris@16 243 {
Chris@16 244 typedef typename when<_, A0>::template impl<Expr, State, Data>::result_type a0;
Chris@16 245 typedef typename when<_, A1>::template impl<Expr, State, Data>::result_type a1;
Chris@16 246 typedef typename detail::poly_function_traits<Fun, Fun(a0, a1)>::result_type result_type;
Chris@16 247
Chris@16 248 BOOST_FORCEINLINE
Chris@16 249 result_type operator ()(
Chris@16 250 typename impl2::expr_param e
Chris@16 251 , typename impl2::state_param s
Chris@16 252 , typename impl2::data_param d
Chris@16 253 ) const
Chris@16 254 {
Chris@16 255 return typename detail::poly_function_traits<Fun, Fun(a0, a1)>::function_type()(
Chris@16 256 detail::as_lvalue(typename when<_, A0>::template impl<Expr, State, Data>()(e, s, d))
Chris@16 257 , detail::as_lvalue(typename when<_, A1>::template impl<Expr, State, Data>()(e, s, d))
Chris@16 258 );
Chris@16 259 }
Chris@16 260 };
Chris@16 261
Chris@16 262 template<typename Expr, typename State, typename Data>
Chris@16 263 struct impl2<Expr, State, Data, true>
Chris@16 264 : transform_impl<Expr, State, Data>
Chris@16 265 {
Chris@16 266 typedef typename when<_, A0>::template impl<Expr, State, Data>::result_type a0;
Chris@16 267 typedef typename when<_, A1>::template impl<Expr, State, Data>::result_type a1;
Chris@16 268 typedef typename Fun::template impl<a0, a1, Data>::result_type result_type;
Chris@16 269
Chris@16 270 BOOST_FORCEINLINE
Chris@16 271 result_type operator ()(
Chris@16 272 typename impl2::expr_param e
Chris@16 273 , typename impl2::state_param s
Chris@16 274 , typename impl2::data_param d
Chris@16 275 ) const
Chris@16 276 {
Chris@16 277 return typename Fun::template impl<a0, a1, Data>()(
Chris@16 278 typename when<_, A0>::template impl<Expr, State, Data>()(e, s, d)
Chris@16 279 , typename when<_, A1>::template impl<Expr, State, Data>()(e, s, d)
Chris@16 280 , d
Chris@16 281 );
Chris@16 282 }
Chris@16 283 };
Chris@16 284
Chris@16 285 /// Let \c x be <tt>when\<_, A0\>()(e, s, d)</tt> and \c X
Chris@16 286 /// be the type of \c x.
Chris@16 287 /// Let \c y be <tt>when\<_, A1\>()(e, s, d)</tt> and \c Y
Chris@16 288 /// be the type of \c y.
Chris@16 289 /// If \c Fun is a binary PolymorphicFunction object that accepts \c x
Chris@16 290 /// and \c y, then \c type is a typedef for
Chris@16 291 /// <tt>boost::result_of\<Fun(X, Y)\>::type</tt>. Otherwise, it is
Chris@16 292 /// a typedef for <tt>boost::result_of\<Fun(X, Y, Data)\>::type</tt>.
Chris@16 293
Chris@16 294 /// Either call the PolymorphicFunctionObject with 2 arguments:
Chris@16 295 /// the result of applying the \c A0 transform, and the
Chris@16 296 /// result of applying the \c A1 transform; or invoke the
Chris@16 297 /// PrimitiveTransform with 3 arguments: the result of applying
Chris@16 298 /// the \c A0 transform, the result of applying the \c A1
Chris@16 299 /// transform, and the data.
Chris@16 300 ///
Chris@16 301 /// Let \c x be <tt>when\<_, A0\>()(e, s, d)</tt>.
Chris@16 302 /// Let \c y be <tt>when\<_, A1\>()(e, s, d)</tt>.
Chris@16 303 /// If \c Fun is a binary PolymorphicFunction object that accepts \c x
Chris@16 304 /// and \c y, return <tt>Fun()(x, y)</tt>. Otherwise, return
Chris@16 305 /// <tt>Fun()(x, y, d)</tt>.
Chris@16 306 ///
Chris@16 307 /// \param e The current expression
Chris@16 308 /// \param s The current state
Chris@16 309 /// \param d An arbitrary data
Chris@16 310 template<typename Expr, typename State, typename Data>
Chris@16 311 struct impl
Chris@16 312 : impl2<Expr, State, Data, detail::is_transform_<Fun>::value>
Chris@16 313 {};
Chris@16 314 };
Chris@16 315
Chris@16 316 /// \brief Call the PolymorphicFunctionObject or the
Chris@16 317 /// PrimitiveTransform with the current expression, state
Chris@16 318 /// and data, transformed according to \c A0, \c A1, and
Chris@16 319 /// \c A2, respectively.
Chris@16 320 template<typename Fun, typename A0, typename A1, typename A2>
Chris@16 321 struct call<Fun(A0, A1, A2)> : transform<call<Fun(A0, A1, A2)> >
Chris@16 322 {
Chris@16 323 template<typename Expr, typename State, typename Data, bool B>
Chris@16 324 struct impl2
Chris@16 325 : transform_impl<Expr, State, Data>
Chris@16 326 {
Chris@16 327 typedef typename when<_, A0>::template impl<Expr, State, Data>::result_type a0;
Chris@16 328 typedef typename when<_, A1>::template impl<Expr, State, Data>::result_type a1;
Chris@16 329 typedef typename when<_, A2>::template impl<Expr, State, Data>::result_type a2;
Chris@16 330 typedef typename detail::poly_function_traits<Fun, Fun(a0, a1, a2)>::result_type result_type;
Chris@16 331
Chris@16 332 BOOST_FORCEINLINE
Chris@16 333 result_type operator ()(
Chris@16 334 typename impl2::expr_param e
Chris@16 335 , typename impl2::state_param s
Chris@16 336 , typename impl2::data_param d
Chris@16 337 ) const
Chris@16 338 {
Chris@16 339 return typename detail::poly_function_traits<Fun, Fun(a0, a1, a2)>::function_type()(
Chris@16 340 detail::as_lvalue(typename when<_, A0>::template impl<Expr, State, Data>()(e, s, d))
Chris@16 341 , detail::as_lvalue(typename when<_, A1>::template impl<Expr, State, Data>()(e, s, d))
Chris@16 342 , detail::as_lvalue(typename when<_, A2>::template impl<Expr, State, Data>()(e, s, d))
Chris@16 343 );
Chris@16 344 }
Chris@16 345 };
Chris@16 346
Chris@16 347 template<typename Expr, typename State, typename Data>
Chris@16 348 struct impl2<Expr, State, Data, true>
Chris@16 349 : transform_impl<Expr, State, Data>
Chris@16 350 {
Chris@16 351 typedef typename when<_, A0>::template impl<Expr, State, Data>::result_type a0;
Chris@16 352 typedef typename when<_, A1>::template impl<Expr, State, Data>::result_type a1;
Chris@16 353 typedef typename when<_, A2>::template impl<Expr, State, Data>::result_type a2;
Chris@16 354 typedef typename Fun::template impl<a0, a1, a2>::result_type result_type;
Chris@16 355
Chris@16 356 BOOST_FORCEINLINE
Chris@16 357 result_type operator ()(
Chris@16 358 typename impl2::expr_param e
Chris@16 359 , typename impl2::state_param s
Chris@16 360 , typename impl2::data_param d
Chris@16 361 ) const
Chris@16 362 {
Chris@16 363 return typename Fun::template impl<a0, a1, a2>()(
Chris@16 364 typename when<_, A0>::template impl<Expr, State, Data>()(e, s, d)
Chris@16 365 , typename when<_, A1>::template impl<Expr, State, Data>()(e, s, d)
Chris@16 366 , typename when<_, A2>::template impl<Expr, State, Data>()(e, s, d)
Chris@16 367 );
Chris@16 368 }
Chris@16 369 };
Chris@16 370
Chris@16 371 /// Let \c x be <tt>when\<_, A0\>()(e, s, d)</tt>.
Chris@16 372 /// Let \c y be <tt>when\<_, A1\>()(e, s, d)</tt>.
Chris@16 373 /// Let \c z be <tt>when\<_, A2\>()(e, s, d)</tt>.
Chris@16 374 /// Return <tt>Fun()(x, y, z)</tt>.
Chris@16 375 ///
Chris@16 376 /// \param e The current expression
Chris@16 377 /// \param s The current state
Chris@16 378 /// \param d An arbitrary data
Chris@16 379
Chris@16 380 template<typename Expr, typename State, typename Data>
Chris@16 381 struct impl
Chris@16 382 : impl2<Expr, State, Data, detail::is_transform_<Fun>::value>
Chris@16 383 {};
Chris@16 384 };
Chris@16 385
Chris@16 386 #include <boost/proto/transform/detail/call.hpp>
Chris@16 387
Chris@16 388 /// INTERNAL ONLY
Chris@16 389 ///
Chris@16 390 template<typename Fun>
Chris@16 391 struct is_callable<call<Fun> >
Chris@16 392 : mpl::true_
Chris@16 393 {};
Chris@16 394
Chris@16 395 }} // namespace boost::proto
Chris@16 396
Chris@101 397 #if defined(_MSC_VER)
Chris@16 398 # pragma warning(pop)
Chris@16 399 #endif
Chris@16 400
Chris@16 401 #endif