On Jun 4, 5:55 pm, alfC <alfredo.cor...@gmail.com> 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<class XUnit, class YUnit, class TX, class TY> \ struct result_of_##PhoenixnamE <quantity<XUnit,TX> RefQ1, quantity<YUnit,TY> RefQ2>{ \ typedef typename UnitsnamE##_typeof_helper<quantity<XUnit,TX>&,quantity<YUnit,TY>&
::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<quantity<si::area>(quantity<si::length>)> f = arg1 * si::meter; cout << f(4.*si::meter) <<endl; note that the improvement is that now I can use boost units names (not only quantities) directly in a phoenix expression, not only that the overload operator* is deduced in favor of operator* in the phoenix (lambda sense) instead of generating quantity<unit, actor< > > (which may or may not make sense, seems not to). (I used boost::function just to make the example clear). Here is the code to make this work, i.e. use phoenix and units in a expression, (sorry again if I am not supposed to mess with phoenix internals in this way): namespace boost{ namespace phoenix{ #define RESULT_OF_QUANTITY_UNITS_GEN( PhoenixopnamE, UnitsopnamE ) \ template<class XUnit, typename TX, class Dim, class System> \ struct result_of_##PhoenixopnamE < \ boost::units::quantity<XUnit,TX> &, \ boost::units::unit<Dim, System> \
{ \ typedef \ typename boost::units::UnitsopnamE##_typeof_helper< \ boost::units::quantity<XUnit,TX>, boost::units::unit<Dim, System> \ >::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<Dim, System> \ > \ > \
\ \ operator CsymboL (const actor<PhoenixExpr>& lhs, const unit<Dim,System>& rhs){ \ return compose<PhoenixopnamE##_eval>(lhs, rhs); \ } REFINE_ARITHMETIC_OPERATORS(multiplies, *) REFINE_ARITHMETIC_OPERATORS(divides, /) #undef REFINE_ARITHMETIC_OPERATORS }}