Boost logo

Boost Users :

Subject: Re: [Boost-users] [phoenix] v2 to v3 transition of extension mechanism
From: alfC (alfredo.correa_at_[hidden])
Date: 2011-04-14 02:26:48


Hi Tomas,

On Apr 13, 12:13 pm, Thomas Heller <thom.hel..._at_[hidden]> wrote:
> I moved the Context argument to the end of the argument list so it gets more
> consistent to the eval function. eval takes the context as the last argument
> because its the proto state, thus its the second parameter.
>

With your changes now it works. I post the complete code below, to
document this for others. (be advises that this is an example only,
the lazy cos is implemented in boost/phoenix/stl/cmath.hpp)

The code has a couple of comments on obscure points that I still don't
understand. For example,
1) I tried to use decltype so to have the generic return type of the
function but it didn't work.
2) Can the std (for std::cos) specification be omitted so a context
dependent 'cos' in an arbitrary namesapce is called? (depending on the
return type of the nested eval()? In such case the lazy cos can be
used for other exotic implementations of eager cos, even in different
namespace.
3) Does it worth to use enable_if to construct the lazy function to
avoid name clashes and horrible errors?, i.e. such that lazy functions
are called only on phoenix expressions

see the numbers below, in the following working code:

#include<boost/phoenix/core.hpp>
#include<cmath>

BOOST_PHOENIX_DEFINE_EXPRESSION(
    (boost)(phoenix)(cos)
  , (meta_grammar) // Arg
)

namespace boost { namespace phoenix
{
        struct cos_eval{
                template<class Sig> struct result;
                template<class This, class Arg, class Cont>
                struct result<This(Arg, Cont)>{
                    typedef
                        double //works, but not generic
                        //decltype(std::cos(eval(Arg(), Cont()))) // (1) doesn't work, why?
                        type;
                };

                template <typename Arg, typename Context>
                typename result<cos_eval(Arg const&, Context const&)>::type
                operator()(Arg const& arg, Context const& ctx) const{
                    using namespace std; // (2) can this be avoided in
order to call a context-namespace-dependent eager 'cos'
                    return cos(eval(arg, ctx));
                }
        };

        template <typename Dummy>
        struct default_actions::when<rule::cos, Dummy>
                : call<cos_eval, Dummy>
        {};

        template <typename Arg>
        typename expression::cos<Arg>::type const
        cos(
                Arg const& arg,
                typename enable_if_c<is_actor<Arg>::value, void*>::type = 0 //worth
it?
        ){
                return expression::cos<Arg>::make(arg);
        }

}}

#include <boost/phoenix/operator.hpp>
#include<iostream>

using namespace boost::phoenix::arg_names;

int main(){
        double r;
        r = cos(arg1 + 1.)(2.);
        std::cout << r << std::endl; //prints -0.989992
        return 0;
}


Boost-users list run by williamkempf at hotmail.com, kalb at libertysoft.com, bjorn.karlsson at readsoft.com, gregod at cs.rpi.edu, wekempf at cox.net