Boost logo

Boost :

Subject: [boost] [phoenix] Using Phoenix lambdas on top of custom Proto expressions
From: Denis Demidov (ddemidov_at_[hidden])
Date: 2013-06-17 01:33:01


Hello,

I am working on VexCL (https://github.com/ddemidov/vexcl) - a vector
expression template library for OpenCL. I have recently added support for
automatic generation of OpenCL kernels from generic functors (description
of the feature: https://github.com/ddemidov/vexcl#function-generator).

In order to implement this, I pass the instances of vex::symbolic<T> class
to the given functor. vex::symbolic<T> dumps to output stream any
arithmetic operations it is being subjected to, and that's how I am able to
construct the OpenCL kernel source. The symbolic<T> class is of course a
Boost.Proto terminal.

Now, it seems natural to use Boost.Phoenix to provide the generic functors
for the function generator. And indeed it is possible with simple
expressions (see
https://github.com/ddemidov/vexcl/blob/a95dfdd68/tests/generator.cpp#L124).
However, if I try to bring cmath functions overloads from
<boost/phoenix/stl/cmath.hpp> and use those (
https://github.com/ddemidov/vexcl/commit/b95da14e51), I get compilation
errors. The reason apparently is that boost::phoenix_impl::<function>_impl
assumes that result of <function>(expr) has the same type as expr itself.
This of course is not true if expr is a Boost.Proto expression.

Everything works as intended with the following patch:

--- a/cmath.hpp
+++ b/cmath.hpp
@@ -25,11 +25,11 @@ namespace boost {
         struct result<This(BOOST_PHOENIX_A(n))> \
         { \
             typedef \
- typename proto::detail::uncvref<A0>::type \
+ decltype( name(typename
proto::detail::uncvref<A0>::type()) ) \
                 type; \
         }; \
         template<BOOST_PHOENIX_typename_A(n)> \
- A0 operator()(BOOST_PHOENIX_A_const_ref_a(n)) const { \
+ auto operator()(BOOST_PHOENIX_A_const_ref_a(n)) const -> decltype(
name(BOOST_PHOENIX_a(n)) ) { \
             using namespace std; \
             return name(BOOST_PHOENIX_a(n)); \
         } \

I understand this is unacceptable in its current form (because it uses
c++11 features), but I could not do this in terms of e.g. boost::result_of.
May be someone has a better idea of how to implement this?

-- 
Best regards,
Denis

Boost list run by bdawes at acm.org, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk