[phoenix] [range] I think I'm missing a couple things w/ these libs

I love the ideas behind these libs, but I think I need to figure out a bit more before I can use them. Here's an example that models what I'm trying to do for real as an experiment w/ using phoenix and range. I can't quite get it to build. I think I'm really close. I tried it w/ lambda before I found phoenix and I had to do some ret<> things to get past some errors, but I'm not sure what the equivalent in phoenix is, or if I should really need them. Also, I think there should be a way to instantiate a vector directly from a range w/o having to use begin() and end() somehow, but I can't find it. I've tried various approaches with <something> including transformed_range<> and any_range<> and haven't gotten them to work. The transformed line gives me errors complaining about missing result_type, iterator_category, value_type, difference_type, pointer, reference. I'm using GCC 4.2 on OS X Thanks! ---- #include <boost/range/adaptor/transformed.hpp> #include <boost/spirit/include/phoenix_core.hpp> #include <boost/spirit/include/phoenix_bind.hpp> #include <vector> class A {}; class B { public: A a; }; class C { public: static B BFromA(const A& a) { return B(); } }; std::vector<C> CsFromBs(std::vector<B> bs) { <something> cs = bs | boost::adaptors::transformed(boost::phoenix::bind(&C::BFromA, boost::phoenix::bind(&B::a, boost::phoenix::arg_names::arg1))); return std::vector<C>(boost::begin(cs), boost::end(cs)); }

AMDG On 04/06/2011 01:50 PM, Jake Brownson wrote:
I love the ideas behind these libs, but I think I need to figure out a bit more before I can use them.
Here's an example that models what I'm trying to do for real as an experiment w/ using phoenix and range. I can't quite get it to build. I think I'm really close. I tried it w/ lambda before I found phoenix and I had to do some ret<> things to get past some errors, but I'm not sure what the equivalent in phoenix is, or if I should really need them.
Also, I think there should be a way to instantiate a vector directly from a range w/o having to use begin() and end() somehow, but I can't find it.
I've tried various approaches with<something> including transformed_range<> and any_range<> and haven't gotten them to work.
If you have a compiler that support C++0x features, <something> can be auto.
The transformed line gives me errors complaining about missing result_type, iterator_category, value_type, difference_type, pointer, reference.
The following works for me with VC++ 2010: Note that if you work through the types, the transform returns a range of B's, not a range of C's. #include <boost/range/adaptor/transformed.hpp> #include <boost/range/algorithm/copy.hpp> #include <boost/spirit/include/phoenix_core.hpp> #include <boost/spirit/include/phoenix_bind.hpp> #include <vector> class A {}; class B { public: A a; }; class C { public: static B BFromA(const A& a) { return B(); } }; std::vector<B> CsFromBs(std::vector<B> bs) { std::vector<B> result; boost::copy( bs | boost::adaptors::transformed(boost::phoenix::bind(&C::BFromA, boost::phoenix::bind(&B::a, boost::phoenix::arg_names::arg1))), std::back_inserter(result)); return result; }
I'm using GCC 4.2 on OS X
Thanks!
----
#include<boost/range/adaptor/transformed.hpp> #include<boost/spirit/include/phoenix_core.hpp> #include<boost/spirit/include/phoenix_bind.hpp> #include<vector>
class A {};
class B { public: A a; };
class C { public: static B BFromA(const A& a) { return B(); } };
std::vector<C> CsFromBs(std::vector<B> bs) { <something> cs = bs | boost::adaptors::transformed(boost::phoenix::bind(&C::BFromA, boost::phoenix::bind(&B::a, boost::phoenix::arg_names::arg1))); return std::vector<C>(boost::begin(cs), boost::end(cs)); }
In Christ, Steven Watanabe

Thanks Steven!
If you have a compiler that support C++0x features, <something> can be auto.
Yeah I was thinking the same thing, I don't think I should stray into 0x land w/ this stuff yet. I thought about using a copy, and not to get too picky but it'd be so much slicker if I could just instantiate the vector inline. If I could write down the type I could at least create a helper that does the begin/end calls. I figure at least the way I was trying to do it was 2 lines instead of 3, and didn't have a non-const var lying around.
The following works for me with VC++ 2010:
I'm getting the same build errors with what you provided... I guess my compiler has issues with this. I'm using XCode 4 w/ GCC 4.2 and boost 1.46.1. I get the same errors when I try LLVM 2.0. I thought I was doing it about right :(. Thanks again, Jake On Wed, Apr 6, 2011 at 2:21 PM, Steven Watanabe <watanabesj@gmail.com> wrote:
AMDG
On 04/06/2011 01:50 PM, Jake Brownson wrote:
I love the ideas behind these libs, but I think I need to figure out a bit more before I can use them.
Here's an example that models what I'm trying to do for real as an experiment w/ using phoenix and range. I can't quite get it to build. I think I'm really close. I tried it w/ lambda before I found phoenix and I had to do some ret<> things to get past some errors, but I'm not sure what the equivalent in phoenix is, or if I should really need them.
Also, I think there should be a way to instantiate a vector directly from a range w/o having to use begin() and end() somehow, but I can't find it.
I've tried various approaches with<something> including transformed_range<> and any_range<> and haven't gotten them to work.
The transformed line gives me errors complaining about missing result_type, iterator_category, value_type, difference_type, pointer, reference.

AMDG On 04/06/2011 02:52 PM, Jake Brownson wrote:
If you have a compiler that support C++0x features, <something> can be auto.
Yeah I was thinking the same thing, I don't think I should stray into 0x land w/ this stuff yet.
I thought about using a copy, and not to get too picky but it'd be so much slicker if I could just instantiate the vector inline. If I could write down the type I could at least create a helper that does the begin/end calls. I figure at least the way I was trying to do it was 2 lines instead of 3, and didn't have a non-const var lying around.
Well, how about this version: tested with msvc 10.0 and gcc 4.5.1 #include <boost/range/adaptor/transformed.hpp> #include <boost/range/any_range.hpp> #include <boost/spirit/include/phoenix_core.hpp> #include <boost/spirit/include/phoenix_bind.hpp> #include <vector> class A {}; class B { public: A a; }; class C { public: static B BFromA(const A& a) { return B(); } }; template<class T, class Range> T construct(const Range& r) { return T(boost::begin(r), boost::end(r)); } std::vector<B> CsFromBs(std::vector<B> bs) { return construct<std::vector<B> >(bs | boost::adaptors::transformed(boost::phoenix::bind(&C::BFromA, boost::phoenix::bind(&B::a, boost::phoenix::arg_names::arg1)))); }
The following works for me with VC++ 2010:
I'm getting the same build errors with what you provided... I guess my compiler has issues with this.
Maybe. I'm using the most recent development trunk.
I'm using XCode 4 w/ GCC 4.2 and boost 1.46.1. I get the same errors when I try LLVM 2.0. I thought I was doing it about right :(.
What version of phoenix are you using? It's obviously not from 1.46.1, since the first official release of Phoenix 3 will be in 1.47. In Christ, Steven Watanabe

Well, how about this version: tested with msvc 10.0 and gcc 4.5.1
Ahh very clever, emulating auto w/ the template... didn't think of that. I get the same errors though. I did some searching just now and I guess Apple does some pretty serious modifications to the gcc they ship w/ XCode, I wonder if that explains anything, or maybe simply because it's an older gcc? It's still the one XCode ships with, they're usually a bit behind because they do so many modifications from what I understand.
Maybe. I'm using the most recent development trunk.
I'll grab that and give these a try there too.
What version of phoenix are you using? It's obviously not from 1.46.1, since the first official release of Phoenix 3 will be in 1.47.
I'm using the Phoenix that comes w/ 1.46.1 as part of spirit. Iirc that means Phoenix 2. I was trying the same thing in a similar way w/ lambda and getting similar errors before I found phoenix and read that it's supposed to be the next thing. Thanks, Jake

AMDG On 04/06/2011 03:25 PM, Jake Brownson wrote:
Well, how about this version: tested with msvc 10.0 and gcc 4.5.1
Ahh very clever, emulating auto w/ the template... didn't think of that. I get the same errors though. I did some searching just now and I guess Apple does some pretty serious modifications to the gcc they ship w/ XCode, I wonder if that explains anything, or maybe simply because it's an older gcc? It's still the one XCode ships with, they're usually a bit behind because they do so many modifications from what I understand.
Maybe. I'm using the most recent development trunk.
I'll grab that and give these a try there too.
I get errors too with 1.46.0. It looks like it's because transform_iterator doesn't use result_of. IIRC, this was fixed /very/ recently.
What version of phoenix are you using? It's obviously not from 1.46.1, since the first official release of Phoenix 3 will be in 1.47.
I'm using the Phoenix that comes w/ 1.46.1 as part of spirit. Iirc that means Phoenix 2. I was trying the same thing in a similar way w/ lambda and getting similar errors before I found phoenix and read that it's supposed to be the next thing.
Right. I should read the code more carefully, before I post. In Christ, Steven Watanabe

On Wed, Apr 6, 2011 at 4:42 PM, Steven Watanabe <watanabesj@gmail.com> wrote:
I get errors too with 1.46.0. It looks like it's because transform_iterator doesn't use result_of. IIRC, this was fixed /very/ recently.
Phoenix v2 is tricky to use with transform due to result_of -- for one, there was the bug Steven mentioned with transform_iterator. For two, Phoenix v2's return type deduction mechanism is different than that used by result_of. Phoenix v3 uses result_of and should then be interoperable with boost::adaptors::transformed. For the time being it may be better to use boost::bind in this case. HTH, Nate

I get errors too with 1.46.0. It looks like it's because transform_iterator doesn't use result_of. IIRC, this was fixed /very/ recently.
Phoenix v2 is tricky to use with transform due to result_of -- for one, there was the bug Steven mentioned with transform_iterator. For two, Phoenix v2's return type deduction mechanism is different than that used by result_of. Phoenix v3 uses result_of and should then be interoperable with boost::adaptors::transformed. For the time being it may be better to use boost::bind in this case.
Thanks for the clarifications. I think I'll just wait for 1.47 to hit and reevaluate using this in production code. Keep up the great work guys, boost is a pretty great set of libraries.

On 4/7/2011 6:57 AM, Nathan Crookston wrote:
On Wed, Apr 6, 2011 at 4:42 PM, Steven Watanabe<watanabesj@gmail.com> wrote:
I get errors too with 1.46.0. It looks like it's because transform_iterator doesn't use result_of. IIRC, this was fixed /very/ recently.
Phoenix v2 is tricky to use with transform due to result_of -- for one, there was the bug Steven mentioned with transform_iterator. For two, Phoenix v2's return type deduction mechanism is different than that used by result_of. Phoenix v3 uses result_of and should then be interoperable with boost::adaptors::transformed. For the time being it may be better to use boost::bind in this case.
Not quite true. That's a common misconception. Phoenix v2 *does* support result_of. It's just phoenix::function that does not support it due to legacy code and backward compat. As a matter of fact, I took Steven's code and changed the headers to that of V2 and it compiles: #include <boost/range/adaptor/transformed.hpp> #include <boost/spirit/include/phoenix_core.hpp> #include <boost/spirit/include/phoenix_bind.hpp> #include <vector> class A {}; class B { public: A a; }; class C { public: static B BFromA(const A& a) { return B(); } }; template<class T, class Range> T construct(const Range& r) { return T(boost::begin(r), boost::end(r)); } std::vector<B> CsFromBs(std::vector<B> bs) { return construct<std::vector<B> >(bs | boost::adaptors::transformed(boost::phoenix::bind(&C::BFromA, boost::phoenix::bind(&B::a, boost::phoenix::arg_names::arg1)))); } Regards, -- Joel de Guzman http://www.boostpro.com http://boost-spirit.com

On Wed, Apr 6, 2011 at 6:13 PM, Joel de Guzman <joel@boost-consulting.com> wrote:
On 4/7/2011 6:57 AM, Nathan Crookston wrote:
Phoenix v2 is tricky to use with transform due to result_of -- for one, there was the bug Steven mentioned with transform_iterator. For two, Phoenix v2's return type deduction mechanism is different than that used by result_of. Phoenix v3 uses result_of and should then be interoperable with boost::adaptors::transformed. For the time being it may be better to use boost::bind in this case.
Not quite true. That's a common misconception. Phoenix v2 *does* support result_of. It's just phoenix::function that does not support it due to legacy code and backward compat.
My mistake -- thanks for the clarification. Nate
participants (4)
-
Jake Brownson
-
Joel de Guzman
-
Nathan Crookston
-
Steven Watanabe