Boost logo

Boost Users :

Subject: Re: [Boost-users] [phoenix] function with reference implementation
From: Alfredo Correa (correaa_at_[hidden])
Date: 2010-09-10 21:31:32


On Fri, Sep 10, 2010 at 5:47 PM, Joel de Guzman
<joel_at_[hidden]> wrote:
> On 9/11/10 8:31 AM, alfC wrote:
>>
>>
>> On Sep 10, 4:36 pm, Joel de Guzman<j..._at_[hidden]>  wrote:
>>>
>>> On 9/11/10 4:37 AM, alfC wrote:
>>>
>>>
>>>
>>>> I noticed that in some contexts I have both the object class and the
>>>> corresponding phoenix function
>>>
>>>>    class impl;
>>>>    ...
>>>
>>>>    impl f_impl;
>>>>    boost::phoenix::function<impl>    f(f_impl);
>>>
>>>> now to avoid the copying I could use:
>>>
>>>>    boost::phoenix::function<impl&>    f(f_impl);
>>>
>>>> which works. Although
>>>>    boost::phoenix::function<impl const&>    f(f_impl); //doesn't work.
>>>> (error below)
>>>
>>>> Is there any problem with using references at all, in the first place?
>>>
>>> I'm not sure. Could you provide a minimal cpp file I can try?
>>
>> Yes, see below. Althougth now that I made this example I realize that
>> the underlying object implementation is copied many times anyway (at
>> least 4 times in the example), I guess during the building up of the
>> expression template. [The final objective was to make an object
>> function that not only evaluates but also is able to take expression
>> and build expression templates].
>
> Here's my suggestion: write a proxy function object that holds
> the target function object by reference, pointer, or boost.ref
> and use that to wrap your phoenix function.
>

I see, so once phoenix::function takes charge everything is copied by
value and I have to provide an extra layer of reference.
I think this is a general problem with template code, that wants to assume that
the type is a non-reference and suddenly everything is copied by
value, although it is
clear from the intention that everything should be treated by reference.
In fact template code is full of remove_reference and remove_cv, it
make the life easier for the template coder but at the cost of certain
loss of flexibilty. My point is that most template code should honor
const and reference qualifiers and not just get rid of them. (If it
can't honor it then the code should not compile).

Anyway this is the final code for a funciton object that binds itself
upon evaluation on phoenix expression. Although not related to the
initial question of the post I would welcome any feedback:
(I am not sure if really need the inheritance part)

#include<boost/spirit/home/phoenix.hpp>
#include<iostream>
using namespace boost::phoenix;
struct F : function<F&>{
        double a_;
        F(double a) : function<F&>(*this), a_(a){std::cout << "F constructed"
<<std::endl;}
        F(F const& other) : function<F&>(*this), a_(other.a_){std::cout << "F
copied" <<std::endl;}
        template <typename Arg> struct result{
                typedef double type;
        };
        result<double>::type operator()(double d) const{
                return a_*d*d;
        }
        //magic code starts here
        template<class PhoenixExpression>
        actor<composite<
                        detail::function_eval<1>,
                        boost::fusion::vector<
                                value<F>,
                                PhoenixExpression
> >
>
        operator()(actor<PhoenixExpression> const& a) const{
                return function<F&>::operator()(a);
        }
};

int main(){
        using boost::phoenix::function;
        using namespace boost::phoenix::arg_names;
        {
                F f(4.);
                std::cout << "normal call " << f(5. + 1.) << std::endl;
                std::cout << "delayed call " << f(arg1+1.)((double const&)5.) << std::endl;
        }
        return 0;
}

output:
F constructed
normal call 144
F copied
F copied
F copied
F copied
delayed call 144


Boost-users list run by williamkempf at hotmail.com, kalb at libertysoft.com, bjorn.karlsson at readsoft.com, gregod at cs.rpi.edu, wekempf at cox.net