Hi Tomas, On Apr 13, 12:13 pm, Thomas Heller <thom.hel...@googlemail.com> 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; }