2

I have the following:

class Foo
{
public:
   std::string const& Value() const { return /*Return some string*/; }
};

typedef std::list<Foo> FooList;
FooList foos; // Assume it has some valid entities inside

std::vector<int> ints;

FooList::const_iterator it, iend = foos.end();
for (it = foos.begin(); it != iend; ++it)
{
   ints.push_back(boost::lexical_cast<int>(it->Value()));
}

How can I implement the for loop using std::for_each and boost::phoenix? I tried a few approaches but it gets really really ugly (I had a ton of nested bind() statements). I basically just want to see how clean & readable boost phoenix can make this for loop, so I'm not writing so much boilerplate code to iterate containers that have 1-2 lines of specialized logic.

Sometimes, doing lambdas pre-C++11 just seems too unreadable and unmaintainable to be worth the trouble.

void.pointer
  • 24,859
  • 31
  • 132
  • 243

1 Answers1

1

Assuming you prepare a Phoenix-friendly function object:

namespace lexical_casts
{
    template <typename T> struct to_
    {
        template <typename/*V*/> struct result { typedef T type; };
        template <typename V>
        T operator()(V const& v) const { return boost::lexical_cast<T>(v); }
    };

    boost::phoenix::function<to_<int> > to_int;
}

You can write things like:

BOOST_AUTO(value_of, phx::lambda[ phx::bind(&Foo::Value, arg1) ]);

std::vector<int> ints;
boost::transform(
        foolist,
        back_inserter(ints), 
        lexical_casts::to_int(value_of(arg1)));

See it Live On Coliru

sehe
  • 374,641
  • 47
  • 450
  • 633
  • I'm not familiar with your syntax for the nested result struct. Is it a typo that you left out the template parameter name? Also what is the nested struct for anyway? Your solution overall looks clean! – void.pointer Mar 12 '14 at 04:23
  • @RobertDailey The nested typedef is [the Boost result-of protocol](http://www.boost.org/doc/libs/1_55_0/libs/utility/utility.htm#result_of) and it is commonly used for Phoenix-friendly [Lazy functions](http://www.boost.org/doc/libs/1_55_0/libs/spirit/phoenix/doc/html/phoenix/starter_kit.html#phoenix.starter_kit.lazy_functions) (see also [Functions](http://www.boost.org/doc/libs/1_55_0/libs/spirit/phoenix/doc/html/phoenix/composite.html#phoenix.composite.function) docs) – sehe Mar 12 '14 at 08:10
  • Thanks, could you modify your solution to work pre-C++11? I won't have the new `auto` keyword. – void.pointer Mar 12 '14 at 14:29
  • 1
    @RobertDailey Sure, here goes: http://coliru.stacked-crooked.com/a/4c592a4063c96110 – sehe Mar 12 '14 at 22:13