Why not use Boost.Bind? It will bind to data members, returning a functor that accesses that member. E.g. boost::bind(&A::a, _1); will create a functor that takes an instance of A and returns a reference to the a member. You can then pass that to whatever other functor is being used. Something like (not tested!) std::accumulate(m.begin(), m.end(), bind(std::add, _1, bind(&std::map<std::string, int>::value_type::first, _1)); Boost.Lambda can do this as well, but I am not familiar enough with it to provide an example. At 07:22 AM 1/20/2009, you wrote:
Hi again,
I have a problem. Not really big one but annoying. Often we need to write code like this:
struct A{ int a; std::string b; };
int a_sum(int i, const A &v){ return v.a + i; };
std::vector<A> v; //fill this vector somewhere
std::accumulate( v.begin(), v.end(), 0, a_sum );
or something like
int m_sum(int i, const std::pair<int, std::string> p) { return p.first + i; };
std::map <std::string, int> m;
std::accumlate( m.begin(), m.end(), 0, m_sum);
Or in common words we need to write some kind functor which just get member from element and apply it to another functor.
Of course I can write something like:
template<typename T_, typename V_, V_ T_::*Ptr_> struct get_mem{ const V_ &operator()(const T_ &elem){ return elem->*Ptr_; }; };
but may be there is library way to do this? _______________________________________________ Boost-users mailing list Boost-users@lists.boost.org http://lists.boost.org/mailman/listinfo.cgi/boost-users
On Tue, Jan 20, 2009 at 2:21 PM, Alan M. Carroll < amc@network-geographics.com> wrote:
Why not use Boost.Bind? It will bind to data members, returning a functor that accesses that member. E.g.
boost::bind(&A::a, _1);
will create a functor that takes an instance of A and returns a reference to the a member. You can then pass that to whatever other functor is being used. Something like (not tested!)
std::accumulate(m.begin(), m.end(), bind(std::add, _1, bind(&std::map<std::string, int>::value_type::first, _1));
Boost.Lambda can do this as well, but I am not familiar enough with it to provide an example.
The Lambda version would be similar, just replacing the outer bind with infix notation #include "boost/lambda/lambda.hpp" #include "boost/lambda/bind.hpp" using namespace boost::lambda; std::accumulate( begin, end, _1 + bind(&A::a, _2 )); Again untested.
At 07:22 AM 1/20/2009, you wrote:
Hi again,
I have a problem. Not really big one but annoying. Often we need to write code like this:
struct A{ int a; std::string b; };
int a_sum(int i, const A &v){ return v.a + i; };
std::vector<A> v; //fill this vector somewhere
std::accumulate( v.begin(), v.end(), 0, a_sum );
or something like
int m_sum(int i, const std::pair<int, std::string> p) { return p.first + i; };
std::map <std::string, int> m;
std::accumlate( m.begin(), m.end(), 0, m_sum);
Or in common words we need to write some kind functor which just get member from element and apply it to another functor.
Of course I can write something like:
template<typename T_, typename V_, V_ T_::*Ptr_> struct get_mem{ const V_ &operator()(const T_ &elem){ return elem->*Ptr_; }; };
but may be there is library way to do this?
The Lambda version would be similar, just replacing the outer bind with infix notation
#include "boost/lambda/lambda.hpp" #include "boost/lambda/bind.hpp"
using namespace boost::lambda;
std::accumulate( begin, end, _1 + bind(&A::a, _2 ));
Again untested.
this std::accumulate return complicated lambda function, but not int value :-) May be we need to use boost::ref?
On Tue, Jan 20, 2009 at 2:53 PM, Maxim Koshelev <chuchelo@gmail.com> wrote:
The Lambda version would be similar, just replacing the outer bind with infix notation
#include "boost/lambda/lambda.hpp" #include "boost/lambda/bind.hpp"
using namespace boost::lambda;
std::accumulate( begin, end, _1 + bind(&A::a, _2 ));
Again untested.
this std::accumulate return complicated lambda function, but not int value :-)
Yeah, sorry, missed the initial value! std::accumulate( begin, end, 0, _1 + bind(&A::a, _2 ));
oh, thanks, but according this: http://www.boost.org/doc/libs/1_37_0/doc/html/lambda/le_in_details.html#lamb... I can write... (_2 ->* &A::a) instead of ... bind(&A::a, _2) but it does'nt work
Yeah, sorry, missed the initial value!
std::accumulate( begin, end, 0, _1 + bind(&A::a, _2 ));
On Tue, Jan 20, 2009 at 3:18 PM, Maxim Koshelev <chuchelo@gmail.com> wrote:
oh, thanks, but according this:
http://www.boost.org/doc/libs/1_37_0/doc/html/lambda/le_in_details.html#lamb...
I can write...
(_2 ->* &A::a)
instead of ...
bind(&A::a, _2)
but it does'nt work
_2 is a reference to A, not a pointer or iterator, so you'd need .* but there is no such thing for lambda palceholders 'cos you can't overload it. Rob.
On Tue, Jan 20, 2009 at 9:11 AM, Robert Jones <robertgbjones@gmail.com>wrote:
On Tue, Jan 20, 2009 at 2:53 PM, Maxim Koshelev <chuchelo@gmail.com>wrote:
The Lambda version would be similar, just replacing the outer bind with infix notation
#include "boost/lambda/lambda.hpp" #include "boost/lambda/bind.hpp"
using namespace boost::lambda;
std::accumulate( begin, end, _1 + bind(&A::a, _2 ));
Again untested.
this std::accumulate return complicated lambda function, but not int value :-)
Yeah, sorry, missed the initial value!
std::accumulate( begin, end, 0, _1 + bind(&A::a, _2 ));
I still get problems. Mostly ambiguity issues with _1 and _2, so I qualify them with boost::lambda and then I get boost::lambda::function_adaptor<Func>::apply none of the 8 overloads could convert all the argument types with [ Func = int Test::* ] could be ... and from there it lists every possible overload of RET boost::lambda::function_adaptor<Func>::apply<RET>(T Test::*, _____) where ____ is every possible combination of const, volatile, pointer, and reference, and the type "Object".
On Tue, Jan 20, 2009 at 3:22 PM, Zachary Turner <divisortheory@gmail.com>wrote:
On Tue, Jan 20, 2009 at 9:11 AM, Robert Jones <robertgbjones@gmail.com>wrote:
On Tue, Jan 20, 2009 at 2:53 PM, Maxim Koshelev <chuchelo@gmail.com>wrote:
The Lambda version would be similar, just replacing the outer bind with infix notation
#include "boost/lambda/lambda.hpp" #include "boost/lambda/bind.hpp"
using namespace boost::lambda;
std::accumulate( begin, end, _1 + bind(&A::a, _2 ));
Again untested.
this std::accumulate return complicated lambda function, but not int value :-)
Yeah, sorry, missed the initial value!
std::accumulate( begin, end, 0, _1 + bind(&A::a, _2 ));
I still get problems. Mostly ambiguity issues with _1 and _2, so I qualify them with boost::lambda and then I get
boost::lambda::function_adaptor<Func>::apply none of the 8 overloads could convert all the argument types with [ Func = int Test::* ] could be ...
and from there it lists every possible overload of RET boost::lambda::function_adaptor<Func>::apply<RET>(T Test::*, _____)
where ____ is every possible combination of const, volatile, pointer, and reference, and the type "Object".
This one IS tested! #include "boost/lambda/lambda.hpp" #include "boost/lambda/bind.hpp" #include <vector> #include <numeric> #include <iostream> struct A{ int a; std::string b; }; int a_sum(int i, const A &v){ return i + v.a; } int main( ) { using namespace boost::lambda; std::vector<A> v; for ( unsigned i=1; i != 6; ++i) { A a = { i, "" }; v.push_back( a ); } int result = std::accumulate(v.begin(),v.end(),0, _1 + bind(&A::a,_2)); std::cout << result << "\n"; }
This one IS tested! ... yes, this worked, but next, more simple example not work:
std::map <int, std::string> m; std::vector <int> v; std::transform( m.begin(), m.end(), std::backinserter(v), bind(&std::pair<const int, std::string>::second, _1) ); even replacing 'bind' by _1 ->* &std::pair<const int,std::string>::second doesn't work. GCC 4.1.2 reports: error: reference to '_1' is ambiguous /usr/include/boost/lambda/core.hpp:69: error: candidates are: const boost::lambda::placeholder1_type& boost::lambda::<unnamed>::_1 /usr/include/boost/bind/placeholders.hpp:30: error: boost::arg<1><unnamed>::_1() services.cc:56: error: reference to '_1' is ambiguous
heh, gcc 4.3 compile without errors On Tue, Jan 20, 2009 at 6:52 PM, Maxim Koshelev <chuchelo@gmail.com> wrote:
This one IS tested! ... yes, this worked, but next, more simple example not work:
std::map <int, std::string> m; std::vector <int> v;
std::transform( m.begin(), m.end(), std::backinserter(v), bind(&std::pair<const int, std::string>::second, _1) );
even replacing 'bind' by _1 ->* &std::pair<const int,std::string>::second doesn't work. GCC 4.1.2 reports: error: reference to '_1' is ambiguous /usr/include/boost/lambda/core.hpp:69: error: candidates are: const boost::lambda::placeholder1_type& boost::lambda::<unnamed>::_1 /usr/include/boost/bind/placeholders.hpp:30: error: boost::arg<1><unnamed>::_1() services.cc:56: error: reference to '_1' is ambiguous
On Tue, Jan 20, 2009 at 3:52 PM, Maxim Koshelev <chuchelo@gmail.com> wrote:
This one IS tested! ... yes, this worked, but next, more simple example not work:
std::map <int, std::string> m; std::vector <int> v;
std::transform( m.begin(), m.end(), std::backinserter(v), bind(&std::pair<const int, std::string>::second, _1) );
even replacing 'bind' by _1 ->* &std::pair<const int,std::string>::second doesn't work. GCC 4.1.2 reports: error: reference to '_1' is ambiguous /usr/include/boost/lambda/core.hpp:69: error: candidates are: const boost::lambda::placeholder1_type& boost::lambda::<unnamed>::_1 /usr/include/boost/bind/placeholders.hpp:30: error: boost::arg<1><unnamed>::_1() services.cc:56: error: reference to '_1' is ambiguous _______________________________________________
This works for me... #include "boost/lambda/lambda.hpp" #include "boost/lambda/bind.hpp" #include <vector> #include <map> #include <algorithm> #include <iterator> #include <iostream> int main( ) { using namespace boost::lambda; std::map<int,std::string> v; std::vector<int> i; for ( unsigned i=1; i != 6; ++i) v.insert( std::pair<const int,std::string>(i,"") ); std::transform( v.begin(), v.end(), std::back_inserter(i), bind(&std::pair<const int,std::string>::first, _1) ); } Rob.
On Tue, Jan 20, 2009 at 9:33 AM, Robert Jones <robertgbjones@gmail.com>wrote:
This one IS tested!
#include "boost/lambda/lambda.hpp" #include "boost/lambda/bind.hpp" #include <vector> #include <numeric> #include <iostream>
struct A{ int a; std::string b; };
int a_sum(int i, const A &v){ return i + v.a; }
int main( ) { using namespace boost::lambda; std::vector<A> v; for ( unsigned i=1; i != 6; ++i) { A a = { i, "" }; v.push_back( a ); }
int result = std::accumulate(v.begin(),v.end(),0, _1 + bind(&A::a,_2)); std::cout << result << "\n"; }
What compiler are you using? Doesn't work on VC 2005 or 2008. Overload resolution ambiguity failure on boost::lambda::function_adaptor<Func>::apply
On Tue, Jan 20, 2009 at 3:52 PM, Zachary Turner <divisortheory@gmail.com>wrote:
What compiler are you using? Doesn't work on VC 2005 or 2008. Overload resolution ambiguity failure on boost::lambda::function_adaptor<Func>::apply
Visual Studio 2005 Pro, with Boost 1.36.0 Cheers
On Tue, Jan 20, 2009 at 10:15 AM, Robert Jones <robertgbjones@gmail.com>wrote:
On Tue, Jan 20, 2009 at 3:52 PM, Zachary Turner <divisortheory@gmail.com>wrote:
What compiler are you using? Doesn't work on VC 2005 or 2008. Overload resolution ambiguity failure on boost::lambda::function_adaptor<Func>::apply
Visual Studio 2005 Pro, with Boost 1.36.0
Cheers
Ahh I'm using 1.35 :(
But I think that boost::bind wait function as first parameter, not constant. Or I'm wrong? On Tue, Jan 20, 2009 at 5:21 PM, Alan M. Carroll <amc@network-geographics.com> wrote:
Why not use Boost.Bind? It will bind to data members, returning a functor that accesses that member. E.g.
boost::bind(&A::a, _1);
will create a functor that takes an instance of A and returns a reference to the a member. You can then pass that to whatever other functor is being used. Something like (not tested!)
std::accumulate(m.begin(), m.end(), bind(std::add, _1, bind(&std::map<std::string, int>::value_type::first, _1));
Boost.Lambda can do this as well, but I am not familiar enough with it to provide an example.
participants (4)
-
Alan M. Carroll
-
Maxim Koshelev
-
Robert Jones
-
Zachary Turner