[phoenix][units] make boost.phoenix play well with boost.units

I have and expression of type
arg1*arg1
which is contained in a deduced type LambdaExp (more preciselly
composite

On 6/3/10 6:11 PM, alfC wrote:
I have and expression of type
arg1*arg1
which is contained in a deduced type LambdaExp (more preciselly composite
, argument<0> >) when trying to see what is the phoenix-deduced return type when input is double
typename LambdaExp::template result
::type naturally, it gives 'double' (double*double)
but when the input type is a boost::units::quantity
typename LambdaExp::template result
si::length > >::type it gives:
error_cant_deduce_type (instread of the equivalent of quantitysi::area, like in quantitysi::area a = quantitysi::length()*quantitysi::length() )
this is strange since it seemed that Phoenix worked out of the box with Units.
What is going on? How can we help Phoenix deduce the return type? Does Phoenix need this help, like Boost.Lambda does by means of boost/ units/lambda.hpp?
Could you please post a minimal cpp file for this one too? You are right, it should work out of the box. Not sure, but it might be a bug. Phoenix2 type deduction, while better than Lambda, is still unwieldy. This will all be fixed in 3.0. Regards, -- Joel de Guzman http://www.boostpro.com http://spirit.sf.net

typename LambdaExp::template result
si::length > >::type it gives:
error_cant_deduce_type (instread of the equivalent of quantitysi::area, like in quantitysi::area a = quantitysi::length()*quantitysi::length() )
Could you please post a minimal cpp file for this one too?
this is a minimal example:
#include ::type
).name()< int main(){
expression_analizer(arg1*arg1);
return 0;
}
/*************end of example**************************/

On 6/4/10 9:02 AM, alfC wrote:
typename LambdaExp::template result
si::length > >::type it gives:
error_cant_deduce_type (instread of the equivalent of quantitysi::area, like in quantitysi::area a = quantitysi::length()*quantitysi::length() )
Could you please post a minimal cpp file for this one too?
this is a minimal example:
[snip] When you do a*a with quantitysi::length, what is the expected return type? (looks like a phoenix-2 limitation. hopefully, this will all get sorted out with phoenix-3). Regards, -- Joel de Guzman http://www.boostpro.com http://spirit.sf.net

AMDG Joel de Guzman wrote:
When you do a*a with quantitysi::length, what is the expected return type?
quantitysi::area
(looks like a phoenix-2 limitation. hopefully, this will all get sorted out with phoenix-3).
In Christ, Steven Watanabe

On Jun 3, 7:16 pm, Steven Watanabe
Joel de Guzman wrote:
When you do a*a with quantitysi::length, what is the expected return type?
quantitysi::area rigth.
and in case you wonder, Boost.Units has a bunch of template functions
to obtain
the result type of arithmetic operations. For example
boost::units::multiply_typeof_helper
(looks like a phoenix-2 limitation. hopefully, this will all get sorted out with phoenix-3).
so, there is no hope with phoenix-2? can't we do something temporary like boost/units/lambda.hpp to help phoenix-2 to deduce the type? is it possible? Thank you, Alfredo

On 6/4/10 10:31 AM, alfC wrote:
On Jun 3, 7:16 pm, Steven Watanabe
wrote: Joel de Guzman wrote:
When you do a*a with quantitysi::length, what is the expected return type?
quantitysi::area rigth.
and in case you wonder, Boost.Units has a bunch of template functions to obtain the result type of arithmetic operations. For example boost::units::multiply_typeof_helper
::type, these are heavily used in boost/units/lambda.hpp, which makes lambda play well with units. (looks like a phoenix-2 limitation. hopefully, this will all get sorted out with phoenix-3).
so, there is no hope with phoenix-2? can't we do something temporary like boost/units/lambda.hpp to help phoenix-2 to deduce the type? is it possible?
There is hope. Just specialize boost::phoenix::result_of_xxx
(e.g. boost::phoenix::result_of_plus

On Jun 3, 7:52 pm, Joel de Guzman
On 6/4/10 10:31 AM, alfC wrote: There is hope. Just specialize boost::phoenix::result_of_xxx (e.g. boost::phoenix::result_of_plus
).
I specilized result_of_multiplies and still no luck:
#include
{ typedef quantitysi::area type; }; }}
using namespace boost::phoenix;
using namespace boost::phoenix::arg_names;
using namespace boost::units;
template<class LambdaExp>
void expression_analizer(actor<LambdaExp> l){
std::clog
<<"type of argument expression: "
<

On 6/5/10 6:01 AM, alfC wrote:
On Jun 3, 7:52 pm, Joel de Guzman
wrote: On 6/4/10 10:31 AM, alfC wrote: There is hope. Just specialize boost::phoenix::result_of_xxx (e.g. boost::phoenix::result_of_plus
). I specilized result_of_multiplies and still no luck: #include
#include<iostream> #include<typeinfo> #include namespace boost{ namespace phoenix{ using namespace boost::units; template<> //in general template
struct result_of_multiplies si::length, quantitysi::length { typedef quantitysi::area type; }; }}
The type-deduction respects references. Phoenix2 passes in references.
The code should be:
template<> //in general template

The type-deduction respects references. Phoenix2 passes in references. The code should be:
template<> //in general template
struct result_of_multiplies si::length&, quantitysi::length&> { typedef quantitysi::area type; };
::type type; }; template
struct result_of_multiplies &, Y&>{ typedef typename multiply_typeof_helper &,Y& ::type type; }; template struct result_of_divides { typedef typename
can you believe it?, I tried with 'const &' but not '&'!!!
Thank you so much for your help. Boost.Units and Boost.Interval will
be good benchmark test for the type deduction of Phoenix3
(what will be the magic of P3? use of typeof?)
Below it is a bridge code between phoenix2 and units.
Notes:
1) Not sure about the reference '&' in the typedefs, put them there
for symmetry.
2) result_of_plus/minus don't seem to be necessary
3) todo: overload operator*(actor<T>, quantity<...>) and
operator*(actor<T>, unit<...>) and reversed to overcome ambiguity on
operator*.
4) todo: specialize *=, /=
5) I wish this be in boost/units/phoenix2.hpp.
// phoenix2 units bridge, result_of_plus/minus don't seem to be
necesary, todo: *=, /=
namespace boost{
namespace phoenix{
using namespace boost::units;
template
::type type; }; template
struct result_of_divides &, Y&>{ typedef typename divide_typeof_helper &, Y&>::type type; }; }}

On 6/4/2010 8:55 PM, alfC wrote:
Thank you so much for your help. Boost.Units and Boost.Interval will be good benchmark test for the type deduction of Phoenix3 (what will be the magic of P3? use of typeof?)
Yes. Phoenix 3 will be forward-looking in this regard. Most compilers at least support Boost.Typeof, and many now have decltype. Type deduction will be automatic in most cases; at worst, you may need to register your user-defined types with Boost.Typeof. -- Eric Niebler BoostPro Computing http://www.boostpro.com

On Jun 4, 5:55 pm, alfC
The type-deduction respects references. Phoenix2 passes in references. The code should be:
template<> //in general template
struct result_of_multiplies si::length&, quantitysi::length&> { typedef quantitysi::area type; };
Actually (unfortunately) it seems that all 4 combinations of reference/
no reference are needed.
This is the only way I managed to make these expression work with type
deduction:
arg1*arg1
(arg1*arg1)*arg1
arg1*(arg1*arg1)
(arg1*arg1)*(arg1*arg1)
So, I have to implement this kind of macro sorcery to bridge
Boost.Units and Boost.Phoenix. Not sure if I will find another bump in
the road:
namespace boost{
namespace phoenix{
using namespace boost::units;
#define RESULT_OF_GEN( PhoenixnamE, UnitsnamE, RefQ1, RefQ2 ) \
template
::type type; \ }; RESULT_OF_GEN(multiplies, multiply, &, ) RESULT_OF_GEN(multiplies, multiply, &, &) RESULT_OF_GEN(multiplies, multiply, , ) RESULT_OF_GEN(multiplies, multiply, , &) RESULT_OF_GEN(divides , divide , &, ) RESULT_OF_GEN(divides , divide , &, &) RESULT_OF_GEN(divides , divide , , ) RESULT_OF_GEN(divides , divide , , &) #undef RESULT_OF_GEN }}

On Jun 4, 5:55 pm, alfC
wrote: So, I have to implement this kind of macro sorcery to bridge Boost.Units and Boost.Phoenix. Not sure if I will find another bump in the road: namespace boost{ namespace phoenix{ using namespace boost::units; #define RESULT_OF_GEN( PhoenixnamE, UnitsnamE, RefQ1, RefQ2 ) \ template
\ struct result_of_##PhoenixnamE RefQ1, quantity RefQ2>{ \ typedef typename UnitsnamE##_typeof_helper &,quantity & ::type type; \ }; RESULT_OF_GEN(multiplies, multiply, &, ) RESULT_OF_GEN(multiplies, multiply, &, &) RESULT_OF_GEN(multiplies, multiply, , ) RESULT_OF_GEN(multiplies, multiply, , &) RESULT_OF_GEN(divides , divide , &, ) RESULT_OF_GEN(divides , divide , &, &) RESULT_OF_GEN(divides , divide , , ) RESULT_OF_GEN(divides , divide , , &) #undef RESULT_OF_GEN }}
On top of what is above, I had to add the code below in order to be
able to use Phoenix in this context:
using namespace boost::units;
using namespace boost::phoenix;
using namespace boost::phoenix::arg_names;
...
boost::function
{ \ typedef \ typename boost::units::UnitsopnamE##_typeof_helper< \ boost::units::quantity
, boost::units::unit \ >::type type; \ }; RESULT_OF_QUANTITY_UNITS_GEN(multiplies, multiply) RESULT_OF_QUANTITY_UNITS_GEN(divides , divide ) #undef RESULT_OF_QUANTITY_UNITS_GEN
// this refines the operator* so the phoenix:;operator* is used instead of units::operator* #define REFINE_ARITHMETIC_OPERATORS(PhoenixopnamE, CsymboL) \ template< \ class PhoenixExpr, \ class System, \ class Dim \
\ actor< \ composite< \ PhoenixopnamE##_eval, \ boost::fusion::vector< \ PhoenixExpr, \ value< \ boost::units::unit
\ > \ > \ \ \ operator CsymboL (const actor<PhoenixExpr>& lhs, const unit
& rhs){ \ return compose (lhs, rhs); \ } REFINE_ARITHMETIC_OPERATORS(multiplies, *) REFINE_ARITHMETIC_OPERATORS(divides, /) #undef REFINE_ARITHMETIC_OPERATORS }}

On Jul 16, 3:09 am, Alfredo Correa
namespace boost{ namespacephoenix{ #define RESULT_OF_QUANTITY_UNITS_GEN( PhoenixopnamE, UnitsopnamE ) \ template
\ struct result_of_##PhoenixopnamE < \ boost::units::quantity &, \ boost::units::unit \>{ \ typedef \ typename boost::units::UnitsopnamE##_typeof_helper< \ boost::units::quantity
, boost::units::unit \ >::type type; \}; RESULT_OF_QUANTITY_UNITS_GEN(multiplies, multiply) RESULT_OF_QUANTITY_UNITS_GEN(divides , divide ) #undef RESULT_OF_QUANTITY_UNITS_GEN
this is a bit more generic:
#define RESULT_OF_QUANTITY_UNITS_GEN( PhoenixopnamE, UnitsopnamE ) \
template< \
typename X, \
class Dim, class System> \
struct result_of_##PhoenixopnamE < \
X&, \
boost::units::unit
{ \ typedef \ typename boost::units::UnitsopnamE##_typeof_helper< \ X, \ boost::units::unit
\ >::type type; \ }; RESULT_OF_QUANTITY_UNITS_GEN(multiplies, multiply) RESULT_OF_QUANTITY_UNITS_GEN(divides , divide ) #undef RESULT_OF_QUANTITY_UNITS_GEN

On 6/4/10 10:16 AM, Steven Watanabe wrote:
AMDG
Joel de Guzman wrote:
When you do a*a with quantitysi::length, what is the expected return type?
quantitysi::area
(looks like a phoenix-2 limitation. hopefully, this will all get sorted out with phoenix-3).
Ok, phoenix-2's type deduction can't deduce that alright. Sorry. Best you can do is specialize boost::phoenix::result_of_xxx for your types. Regards, -- Joel de Guzman http://www.boostpro.com http://spirit.sf.net
participants (5)
-
alfC
-
Alfredo Correa
-
Eric Niebler
-
Joel de Guzman
-
Steven Watanabe