Opened 9 years ago

Closed 5 years ago

#8704 closed Patches (fixed)

Using Phoenix lambdas on top of custom Proto expressions

Reported by: ddemidov@… Owned by: Thomas Heller
Milestone: To Be Determined Component: phoenix
Version: Boost 1.53.0 Severity: Problem
Keywords: phoenix proto Cc:

Description

Some prehistory:

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 come up with other solution (e.g. in terms of boost::result_of).

Sorry for the broken links, Trac did not allow me to submit otherwise. Best regards, Denis

Change History (5)

comment:1 by John Fletcher <J.P.Fletcher@…>, 9 years ago

I am applying your patch like this:

#ifdef BOOST_NO_CXX11_DECLTYPE <old code> #else <your patch> #endif

Do you have a test for it?

comment:2 by John Fletcher <J.P.Fletcher@…>, 9 years ago

I have applied the patch and it is on test on develop. The test cmath applies to this.

I had already applied #6665 which corrected an error for functions with more than 1 argument.

comment:3 by ddemidov@…, 9 years ago

Hello,

Thank you very much for looking into this!

The VexCL test for Phoenix cmath functions (github.com/ddemidov/vexcl/blob/b95da14e51387e955ba83fd470f8677f9044c004/tests/generator.cpp#L125-L142) compiles and runs fine against github.com/boostorg/phoenix/commit/1ffca907da5842e2ebbbcf7155288ed60ffb75d8.

I do not know how to run native Boost.Phoenix tests though (in case this breaks anything).

Again, thanks!

comment:4 by John Fletcher <J.P.Fletcher@…>, 9 years ago

Thank you for the feedback. I cannot test your bug directly, so it is very good to know your problem now works. All I can do is run the test cmath and see if it runs on different compilers, both C++03 and C++11. You can see that here:

http://www.boost.org/development/tests/develop/developer/phoenix.html

When it runs O.K. I will move it to master, hopefully in time for 1.56.0.

When I cannot see a general fix I am fixing for C++11 only.

John

comment:5 by Kohei Takahashi, 5 years ago

Resolution: fixed
Status: newclosed
Note: See TracTickets for help on using tickets.