Boost logo

Boost :

Subject: Re: [boost] [local] Help for the Alternatives section
From: lcaminiti (lorcaminiti_at_[hidden])
Date: 2011-05-04 15:04:40


Mathias Gaunard-2 wrote:
>
> On 03/05/2011 21:44, lcaminiti wrote:
>> Is there a way to do this or something similar with Boost.Phoenix (or
>> Boost.Lambda)?
>
> std::vector<double> v(3);
> std::for_each(v.begin(), v.end(), ref(sum) += factor * _1);
>
> std::vector<int> w(3);
> std::for_each(w.begin(), w.end(), ref(sum) += factor * _1);
>
> or if you want to avoid repetition,
>
> auto local_add = ref(sum) += factor * _1;
>
> std::vector<double> v(3);
> std::for_each(v.begin(), v.end(), local_add);
>
> std::vector<int> w(3);
> std::for_each(w.begin(), w.end(), local_add);
>
> Note you need auto, since using type erasure would force the function
> object to be monomorphic.
>

I think I can do this also without auto so it compiles on ISO C++. The
following works (even if the type expression that replaces auto is very ugly
-- perfect example of why C++0x's auto is useful):

#include &lt;boost/spirit/include/phoenix.hpp&gt;
#include <iostream>
#include <vector>

int main() {
    using boost::phoenix::arg_names::_1;

   
boost::phoenix::actor&lt;boost::phoenix::composite&lt;boost::phoenix::shift_left_eval,
boost::fusion::vector&lt;boost::phoenix::composite&lt;boost::phoenix::shift_left_eval,
boost::fusion::vector&lt;boost::phoenix::reference&lt;std::basic_ostream&lt;char,
std::char_traits&lt;char&gt; > >, boost::phoenix::argument<0>,
boost::fusion::void_, boost::fusion::void_, boost::fusion::void_,
boost::fusion::void_, boost::fusion::void_, boost::fusion::void_,
boost::fusion::void_, boost::fusion::void_> >, boost::phoenix::value<const
char*>, boost::fusion::void_, boost::fusion::void_, boost::fusion::void_,
boost::fusion::void_, boost::fusion::void_, boost::fusion::void_,
boost::fusion::void_, boost::fusion::void_> > >
        f = std::cout << _1 << "\n";

    std::vector<double> v(3);
    v[0] = -1.0; v[1] = -2.0; v[2] = -3.0;
    std::for_each(v.begin(), v.end(), f);

    std::vector<std::string> s(3);
    s[0] = "aa"; s[1] = "bb"; s[2] = "cc";
    std::for_each(s.begin(), s.end(), f);

    return 0;
}

This does what I was looking for:
1) Compiles on ISO C++.
2) Declares f locally (information hiding).
3) Does not repeat f declaration multiple times (avoid code duplication).
4) f is polymorphic in its argument type _1 (it accepts both doubles and
std::strings).

I am thinking that I will add the monomorphic (Boost.Local, Local Functors,
and C++0x lambdas*) vs. polymorphic (Boost.Phoenix, Boost.Local, and Global
Functors) comparison to the Alternatives section.

(*) BTW, as I understand it, C++0x lambdas are monomorphic in their argument
types -- correct?

Thanks.
--Lorenzo

--
View this message in context: http://boost.2283326.n4.nabble.com/local-Help-for-the-Alternatives-section-tp3408469p3496507.html
Sent from the Boost - Dev mailing list archive at Nabble.com.

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