boost::lambda::select2nd
Hi!
I would like to write code like
int main()
{
namespace l = boost::lambda;
std::map
Hi! I would like to write code like int main() { namespace l = boost::lambda; std::map
M; M[1] = 5.0; M[3] = 7.0; std::for_each(M.begin(), M.end(), l::select2nd(l::_1) *= 6.0); } Is it hard to implement this for boost::lambda? Markus
Accessing data members can be done, but it's unfortunately a bit more
complicated than:
_1.second
I just wish . could be overloaded.
Example code below.
Cheers, Jaakko
--------------------
#include "boost/lambda/lambda.hpp"
#include "boost/lambda/bind.hpp"
#include <algorithm>
#include <map>
#include <iostream>
// A function object class that takes returns a second argument of a pair.
// This can be used with bind.
struct select2nd {
// Tell LL how to get the return type. Args will be tuple
Jaakko Jarvi wrote:
std::for_each(M.begin(), M.end(), std::cout << l::bind(select2nd(), l::_1) << " ");
Well, that's too complicated ;-)
_binding_ to a function or functor is the approach
I wanted to avoid.
I think that select1st and select2nd (or - to be generic - select<n>)
could be directly supported by boost::lambda.
It's so common to have a list/vector of tuples or a std::map
(yes, its a request for a feature ;-))
I tried to write something taking ll_static_cast as an example,
but failed to quickly understand the requirements
and semantics of lambda_functor*
Could You correct/complete the code below?
I could not figure out how select2nd_action::apply
gets its RET defined :-(
Is there some documentation on the functor conventions
or on how to extend LL?
class select2nd_action
{
public:
template
ll_select2nd(const Arg1& a1) {
return
lambda_functor_base<
action<1, select2nd_action >,
tuple
Markus Werle wrote:
Jaakko Jarvi wrote:
std::for_each(M.begin(), M.end(), std::cout << l::bind(select2nd(), l::_1) << " ");
Well, that's too complicated ;-) _binding_ to a function or functor is the approach I wanted to avoid.
I have to repeat my usual advice here, use the correct algorithm (even if
it's not standard).
template
Peter Dimov wrote:
I have to repeat my usual advice here, use the correct algorithm (even if it's not standard).
template
void for_each_pair(It first, It last, F f) { for(; first != last; ++first) f(first->first, first->second); } for_each_pair(m.begin(), m.end(), std::cout << _2 << " ");
OK, that's a solution. Many thanks, Markus -- Build your own Expression Template Library with Daixtrose! Visit http://daixtrose.sourceforge.net/
OK, that's a solution.
No it is not :-(
still having problems with template functions:
#include <iostream>
#include <string>
#include <vector>
#include <map>
#include <algorithm>
#include "boost/lambda/lambda.hpp"
#include "boost/lambda/if.hpp"
#include "boost/lambda/exceptions.hpp"
#include "boost/lambda/casts.hpp"
#include "boost/lambda/algorithm.hpp"
#include "boost/lambda/bind.hpp"
#include "boost/mpl/select2nd.hpp"
template <class T>
inline
std::string Foo(const T& t) {}
template
Markus Werle wrote:
Markus Werle wrote:
OK, that's a solution.
No it is not :-( still having problems with template functions:
[...]
template <class T> inline std::string Foo(const T& t) {}
[...]
// THIS HERE FAILS TO COMPILE! for_each_pair(M.begin(), M.end(), l::bind(&Foostd::string, l::_2));
This is a language problem. A function template is treated as if it names an overload set, even when the supplied template arguments limit that set to a single instance. Many compilers accept the code above as an extension. There is an open issue about this problem: http://std.dkuug.dk/jtc1/sc22/wg21/docs/cwg_active.html#115 Workaround: std::string (*pf)(std::string const &) = &Foo; for_each_pair(M.begin(), M.end(), l::bind(pf, l::_2));
Peter Dimov wrote:
Workaround:
std::string (*pf)(std::string const &) = &Foo;
for_each_pair(M.begin(), M.end(), l::bind(pf, l::_2));
... which is a perfect reason for requesting the feature I asked for :-) Well, I use this workaround in some places, but then the code using iterators is as readable like this one, so there is no advantage left for using lamda :-( Anyway thanks for the explanation. Markus -- Build your own Expression Template Library with Daixtrose! Visit http://daixtrose.sourceforge.net/
std::for_each(M.begin(), M.end(), std::cout << l::bind(select2nd(), l::_1) << " "); Well, that's too complicated ;-) _binding_ to a function or functor is the approach I wanted to avoid. I think that select1st and select2nd (or - to be generic - select<n>) could be directly supported by boost::lambda. It's so common to have a list/vector of tuples or a std::map (yes, its a request for a feature ;-))
Peter suggested a nice solution.
For completeness, below is the ll_select_2nd solution.
There are many ways to do it, but maybe the cleanest is to add a
wrapper function that does the same as bind(select2nd, ...).
That is, you need to write the function object, which was in the
previous posting (I'll repeat it here too), and then a wrapper
function that makes the results of
bind(select2nd, ...) and ll_select_2nd(...) equal.
Cheers, Jaakko
PS. There is very little documentation on the functor conventions.
This will all change in the future, as bind proposal is now part of
the standard TR, and the conventions are spelled out there. They are
different from the current lambda though.
Here's the code:
#include "boost/lambda/lambda.hpp"
#include "boost/lambda/bind.hpp"
#include <algorithm>
#include <map>
#include <iostream>
// A function object class that takes returns a second argument of a pair.
// This can be used with bind.
namespace boost {
namespace lambda {
struct select2nd {
// Tell LL how to get the return type. Args will be tuple
participants (3)
-
Jaakko Jarvi
-
Markus Werle
-
Peter Dimov