[Phoenix][v3] Argument/State dependent return type of actors?
Hi Recently I made myself familiar with Phoenix v3, more specifically with actors. I did a few test implementations, and I wondered if there is a way to access the argument types (nested in the context's environment) and/or the type of the state(s) (nested in the proto expression) for the actor's result type declaration. Have a look at the following actor dummy implementation, especially at the line ''typedef int result_type;'': (for the sake of completeness, the complete actor implementation is provided) ------------------------------------------------------------ BOOST_PHOENIX_DEFINE_EXPRESSION( (boost)(phoenix)(myactor) , (boost::phoenix::meta_grammar) ) struct myactor_eval { // ------------------------ // the result type can not be made dependable from // one of the actors argument types .. it is // typedef int result_type; // ------------------------ template <typename StateExpr, typename Context> result_type operator()(StateExpr const& state_expr, Context & ctx) const { return -1; } }; namespace boost { namespace phoenix { template <> struct default_actions::when< rule::myactor> : boost::phoenix::call< ::myactor_eval> {}; template <typename T> typename expression::myactor<T>::type const inline myactor(T& t) { return expression::myactor<T>::make(t); } }} ------------------------------------------------------------ As I already stated, I wonder if there is a way to have access to the argument and state types for the result type, maybe as it was possible in Phoenix v2 via a nested template struct which got the same template parameters as the functor, like the simple example in the following: ------------------------------------------------------------ struct myactor_eval { template <typename StateExpr, typename Context> struct result { typedef typename result_of::env<Context>::type Environment; typedef typename remove_reference< Environment>::type::args_type Args; typedef typename result_of::value_at_c< Args, 0>::type Parameter; // make the result type argument dependent! typedef typename Parameter::value_type type; }; ... }; ------------------------------------------------------------ I do hope that I haven't overlooked something in the docs, sorry if I did. Thanks for your support! Cheers, Josef Weinbub
On 01/-10/-28163 08:59 PM, Josef Weinbub wrote:
Hi
Recently I made myself familiar with Phoenix v3, more specifically with actors. I did a few test implementations, and I wondered if there is a way to access the argument types (nested in the context's environment) and/or the type of the state(s) (nested in the proto expression) for the actor's result type declaration.
.... Hi again! Indeed I have overlooked something, being 'result_of' ... as provided by the Boost Utility library and adopted by the C++11 standard. Sorry for that, should have known .. In case someone else wonders how to approach my problem, checkout the Boost.Utility::result_of documentation: http://www.boost.org/doc/libs/1_48_0/libs/utility/utility.htm#result_of One has to nest a result struct with the functors parameter types in the Boost.Phoenix actor's evaluation functor. For the sake of completeness, in the following my previous evaluation functor is depicted again, but instead of the static "typedef int result_type; " we now use the nested result struct: struct myactor_eval { template<class> struct result; template<class F, typename StateExpr, typename Context> struct result<F(StateExpr, Context)> { // here we can relate the return type both to the state type // and to the functor's argument types ... typedef ..... type; }; template <typename StateExpr, typename Context> typename myactor_eval::result< myactor_eval(StateExpr, Context) >::type operator()(StateExpr const& state_expr, Context & ctx) const { return ...; } }; Best, Josef PS: Thank you, Joel, for noticing my post and forwarding it to Thomas - much appreciated!
On 01/03/2012 09:17 AM, Josef Weinbub wrote:
On 01/-10/-28163 08:59 PM, Josef Weinbub wrote:
Hi
Recently I made myself familiar with Phoenix v3, more specifically with actors. I did a few test implementations, and I wondered if there is a way to access the argument types (nested in the context's environment) and/or the type of the state(s) (nested in the proto expression) for the actor's result type declaration.
....
Hi again!
Indeed I have overlooked something, being 'result_of' ... as provided by the Boost Utility library and adopted by the C++11 standard. Sorry for that, should have known ..
In case someone else wonders how to approach my problem, checkout the Boost.Utility::result_of documentation: http://www.boost.org/doc/libs/1_48_0/libs/utility/utility.htm#result_of
One has to nest a result struct with the functors parameter types in the Boost.Phoenix actor's evaluation functor. For the sake of completeness, in the following my previous evaluation functor is depicted again, but instead of the static "typedef int result_type; " we now use the nested result struct:
struct myactor_eval {
template<class> struct result;
template<class F, typename StateExpr, typename Context> struct result<F(StateExpr, Context)> { // here we can relate the return type both to the state type // and to the functor's argument types ... typedef ..... type; };
template <typename StateExpr, typename Context> typename myactor_eval::result< myactor_eval(StateExpr, Context) >::type operator()(StateExpr const& state_expr, Context & ctx) const { return ...; } };
Best, Josef
PS: Thank you, Joel, for noticing my post and forwarding it to Thomas - much appreciated!
Sorry I missed it, yes, the result_of protocol is used throughout the library. Additionally you can access the context with special meta functions. Looks like the documentation of those is currently incomplete ... Have a look here: http://www.boost.org/doc/libs/1_48_0/libs/phoenix/doc/html/phoenix/inside/ac... At the bottom of this page is a list of functions and proto transforms to access the environment inside the context. For every function, there exists a boost::phoenix::result_of::*name* metafunction, where *name* stands for thing you want to extract. Let's say you want to compute the type of the first passed parameter: // Extract the Environment, which is a fusion vector ... typedef typename boost::phoenix::result_of::env<Context>::type env_type; // Or using result_of: typedef typename boost::result_of< boost::phoenix::functional::env(Context) >::type env_type; // ... and extract the first argument: typedef typename boost::fusion::result_of::at_c<env_type, 1>::type arg_type; Best regards, Thomas
On 01/-10/-28163 08:59 PM, Thomas Heller wrote:
Sorry I missed it, yes, the result_of protocol is used throughout the library.
not a problem, I figured it out, finally ;-) thanks for coming back to me, though
At the bottom of this page is a list of functions and proto transforms to access the environment inside the context. For every function, there exists a boost::phoenix::result_of::*name* metafunction, where *name* stands for thing you want to extract. Let's say you want to compute the type of the first passed parameter:
// Extract the Environment, which is a fusion vector ... typedef typename boost::phoenix::result_of::env<Context>::type env_type;
ya, this I know - works fine ;-)
// ... and extract the first argument: typedef typename boost::fusion::result_of::at_c<env_type, 1>::type arg_type;
here is a problem: the environment is a phoenix::vector2 sequence, so the sequence has two elements. afaik, the first is the actor, and the second seems to be the argument type. (as there is atm only one argument, it's a two-element vector ..) however, in my case the environment type has a reference modifier attached, so I first have to remove it, prior to accessing it via fusion::at_c<>: typedef typename boost::fusion::result_of::at_c< typename boost::remove_reference<env_type>::type , 1
::type arg0;
do you know where this reference modifier is coming from? ------ btw: for the sake of completeness, I figured out another way to access the arguments, by accessing the argument sequence of the environment, have a look at the following: // access the args_type member .. // no free meta-function is used here, so apparently I exploit some unintentional stuff ?! // afaik, the args_type member type is nested in the basic_environment coming from spirit/home/phoenix .. // typedef typename boost::remove_reference<env_type>::type::args_type Arguments; Arguments const& args = env.args(); // now I access the first argumet, which corresponds to the direct approach via the access // to the 1. element of the environment .. // typedef typename boost::fusion::result_of::value_at_c<Arguments, 0>::type Argument0; Argument0 arg0 = boost::fusion::at_c<0>(args); tbh I also like this approach, as it is straightforward: one extracts the environment from the context, and afterwards the argument sequence is extracted from the environment.
Best regards, Thomas
thanks! cheers, josef
participants (2)
-
Josef Weinbub
-
Thomas Heller