[Range & c++0x Lambdas] Can this be done?

Can the last line, labelled NOT Ok, be made to work? I think the lambda does not publish its result as a bind does, so I suspect it's hopeless. Any thoughts? Thx, Rob. #include <boost/range/adaptor/transformed.hpp> #include <boost/range/algorithm_ext/push_back.hpp> #include <boost/bind.hpp> #include <vector> #include <algorithm> struct S { int i; }; void f( std::vector<int> & out, std::vector<S> & in ) { using boost::adaptors::transformed; // Ok std::transform( in.begin( ), in.end( ), std::back_inserter( out ), bind( & S::i, _1 ) ); // Ok boost::range::push_back( out, in | transformed( bind( & S::i, _1 ) ) ); // Ok std::transform( in.begin( ), in.end( ), std::back_inserter( out ), []( S & s ) { return s.i; } ); // NOT Ok boost::range::push_back( out, in | transformed( []( S & s ) { return s.i; } ) ); }

Rob, On Wed, Nov 21, 2012 at 6:39 AM, Robert Jones <robertgbjones@gmail.com>wrote:
Can the last line, labelled NOT Ok, be made to work? I think the lambda does not publish its result as a bind does, so I suspect it's hopeless. Any thoughts? // NOT Ok boost::range::push_back( out, in | transformed( []( S & s ) { return s.i; } ) ); }
It seems trivial to have a nested result_type in all cases with a lambda. However, in C++11 there's no need for it due to decltype.
Sadly, some compilers fall into a gap where result_of (boost or std) doesn't use decltype and lambdas don't publish tr1-style result_type -- leaving code like the above in the lurch. Michel Morin wrote some code for adapting such a case which may be of interest to you: http://lists.boost.org/boost-users/2012/01/72879.php HTH, Nate

On Wed, Nov 21, 2012 at 5:15 PM, Nathan Crookston < nathan.crookston@gmail.com> wrote:
Rob,
On Wed, Nov 21, 2012 at 6:39 AM, Robert Jones <robertgbjones@gmail.com>wrote:
Can the last line, labelled NOT Ok, be made to work? I think the lambda does not publish its result as a bind does, so I suspect it's hopeless. Any thoughts? // NOT Ok boost::range::push_back( out, in | transformed( []( S & s ) { return s.i; } ) ); }
It seems trivial to have a nested result_type in all cases with a lambda. However, in C++11 there's no need for it due to decltype.
Sadly, some compilers fall into a gap where result_of (boost or std) doesn't use decltype and lambdas don't publish tr1-style result_type -- leaving code like the above in the lurch.
Michel Morin wrote some code for adapting such a case which may be of interest to you: http://lists.boost.org/boost-users/2012/01/72879.php
Right, thank you for that informative explanation. So, several solutions, non perfect. Choose your poison! - Rob.

On Wed, Nov 21, 2012 at 5:15 PM, Nathan Crookston <nathan.crookston@gmail.com<mailto:nathan.crookston@gmail.com>> wrote: Rob,
On Wed, Nov 21, 2012 at 6:39 AM, Robert Jones <robertgbjones@gmail.com<mailto:robertgbjones@gmail.com>> wrote: Can the last line, labelled NOT Ok, be made to work? I think the lambda does not publish its result as a bind does, so I suspect it's hopeless. Any thoughts? // NOT Ok boost::range::push_back( out, in | transformed( []( S & s ) { return s.i; } ) ); }
It seems trivial to have a nested result_type in all cases with a lambda. However, in C++11 there's no need for it due to decltype.
Sadly, some compilers fall into a gap where result_of (boost or std) doesn't use decltype and lambdas don't publish tr1-style result_type -- leaving code like the above in the lurch.
Michel Morin wrote some code for adapting such a case which may be of interest to you: http://lists.boost.org/boost-users/2012/01/72879.php
Right, thank you for that informative explanation. So, several solutions, non perfect. Choose your poison!
- Rob.
I've been turning on BOOST_RESULT_OF_USE_DECLTYPE for such occasions and haven't had any problems with it. Regards, Nate

On 11/21/2012 11:27 AM, Nathan Ridge wrote:
On Wed, Nov 21, 2012 at 5:15 PM, Nathan Crookston <nathan.crookston@gmail.com<mailto:nathan.crookston@gmail.com>> wrote: Rob,
On Wed, Nov 21, 2012 at 6:39 AM, Robert Jones <robertgbjones@gmail.com<mailto:robertgbjones@gmail.com>> wrote: Can the last line, labelled NOT Ok, be made to work? I think the lambda does not publish its result as a bind does, so I suspect it's hopeless. Any thoughts? // NOT Ok boost::range::push_back( out, in | transformed( []( S & s ) { return s.i; } ) ); }
It seems trivial to have a nested result_type in all cases with a lambda. However, in C++11 there's no need for it due to decltype.
Sadly, some compilers fall into a gap where result_of (boost or std) doesn't use decltype and lambdas don't publish tr1-style result_type -- leaving code like the above in the lurch.
Michel Morin wrote some code for adapting such a case which may be of interest to you: http://lists.boost.org/boost-users/2012/01/72879.php
Right, thank you for that informative explanation. So, several solutions, non perfect. Choose your poison!
- Rob.
I've been turning on BOOST_RESULT_OF_USE_DECLTYPE for such occasions and haven't had any problems with it.
It's *mostly* safe on *most* modern compilers to do that. Boost has been very cautious about rolling out its decltype-based result_of implementation because "mostly" doesn't cut it. But starting with 1.52, it's enabled by default on clang 3.1 and higher. More compilers will be added as their decltype support improves. -- Eric Niebler BoostPro Computing http://www.boostpro.com

On Wed, Nov 21, 2012 at 9:26 PM, Eric Niebler <eric@boostpro.com> wrote:
On 11/21/2012 11:27 AM, Nathan Ridge wrote:
On Wed, Nov 21, 2012 at 5:15 PM, Nathan Crookston <nathan.crookston@gmail.com<mailto:nathan.crookston@gmail.com>> wrote: Rob,
On Wed, Nov 21, 2012 at 6:39 AM, Robert Jones <robertgbjones@gmail.com<mailto:robertgbjones@gmail.com>> wrote: Can the last line, labelled NOT Ok, be made to work? I think the lambda
does
not publish its result as a bind does, so I suspect it's hopeless. Any thoughts? // NOT Ok boost::range::push_back( out, in | transformed( []( S & s ) { return s.i; } ) ); }
It seems trivial to have a nested result_type in all cases with a lambda. However, in C++11 there's no need for it due to decltype.
- Rob.
I've been turning on BOOST_RESULT_OF_USE_DECLTYPE for such occasions and haven't had any problems with it.
It's *mostly* safe on *most* modern compilers to do that. Boost has been very cautious about rolling out its decltype-based result_of implementation because "mostly" doesn't cut it. But starting with 1.52, it's enabled by default on clang 3.1 and higher. More compilers will be added as their decltype support improves.
I've definitely considered this issue in the context of Boost.Range and have as yet failed to come up with anything that works well enough without problems. I need to spend some time looking at the Michel Morin contribution. I do not intend releasing a change to Boost.Range that allows code to compile that has edge cases that are easy to fall into that cause major problems. In practice it might be necessary to conditionally enable this feature for a subset of the supported compilers. I am totally convinced of the additional values that Boost.Range interoperation with lambdas provides and this is therefore worth lots of effort. In the interim solution proposals are very welcome. It could well be that I haven't thought of something simple that is generally safe.
-- Eric Niebler BoostPro Computing http://www.boostpro.com _______________________________________________ Boost-users mailing list Boost-users@lists.boost.org http://lists.boost.org/mailman/listinfo.cgi/boost-users
Thanks, Neil Groves

Hi Niel, Neil Groves wrote:
I've definitely considered this issue in the context of Boost.Range and have as yet failed to come up with anything that works well enough without problems. I need to spend some time looking at the Michel Morin contribution.
I do not intend releasing a change to Boost.Range that allows code to compile that has edge cases that are easy to fall into that cause major problems. In practice it might be necessary to conditionally enable this feature for a subset of the supported compilers. I am totally convinced of the additional values that Boost.Range interoperation with lambdas provides and this is therefore worth lots of effort.
In the interim solution proposals are very welcome. It could well be that I haven't thought of something simple that is generally safe.
I think mimicking bind's double form[1] would be best when needed. This
would require the transformed adaptor to be changed to a function, but would allow the following usage: Uses result_of (with boost::phoenix): float val = boost::accumulate(seq | transformed(px::at_c<0>(arg1)), 0.f); Can't use result_of: float val = boost::accumulate(seq | transformed<float>([](const boost::tuple<float, int, MyType>& tup) { return boost::get<0>(tup); }), 0.f); I have done this in the past with my zip & unpack adaptors and it has worked well -- I only use the secondary syntax with lambdas, and once I'm on compilers that use decltype for result_of, I just won't need to use it. Would you consider a patch which changed transform (and transformed) to allow this? I would ensure that current tests still pass. Thanks, Nate

Nathan Crookston wrote:
I think mimicking bind's double form[1] would be best when needed. This would require the transformed adaptor to be changed to a function, but would allow the following usage:
Forgot the link: [1] http://www.boost.org/doc/libs/1_52_0/libs/bind/bind.html#Q_forms Nate
participants (5)
-
Eric Niebler
-
Nathan Crookston
-
Nathan Ridge
-
Neil Groves
-
Robert Jones