|
-
April 2nd, 2012, 01:31 AM
#1
[RESOLVED] for_each and member function
I have searched the forum and googled, but I can't get this code to compile (using VS2010 and gcc4.6.1):
Code:
#include <string>
#include <vector>
#include <algorithm>
#include <boost/bind.hpp>
class X
{
public:
void foo( const std::vector<std::string>& v )
{
std::for_each( v.begin(), v.end(), std::bind1st( std::mem_fun(&X::bar), this ) );
}
private:
void bar( const std::string& s ) const
{
}
};
VS2010 presents an error message like
"member function already defined or declared"
and gcc something like "... function can not be overloaded" (very cryptic error message).
If I change the vector to foo to std::vector<int> and let bar() take an int, it works perfectly fine.
And if I use boost
Code:
std::for_each( v.begin(), v.end(), boost::bind( std::mem_fun(&X::bar), this, _1 ) );
the above code compiles as well.
While it is perfectly fine for me to use boost I would nevertheless like to understand what's happening here. I have spent more than an hour with this.
Could someone explain what is the problem here?
Thanks,
Richard
-
April 2nd, 2012, 06:59 AM
#2
Re: for_each and member function
I think this issue you are having is that the type held by the vector v needs to match the type specified in the result of bind1st. Therefore if you change
Code:
void bar( const std::string& s ) const
to
Code:
void bar( std::string s ) const
I expect it will work fine.
-
April 2nd, 2012, 07:13 AM
#3
Re: for_each and member function
 Originally Posted by Richard.J
If I change the vector to foo to std::vector<int> and let bar() take an int, it works perfectly fine.
The problem here is nothing to do with std::string. Rather, it is the fact that bar() takes a reference to a string. (I presume that when you say you changed to int, you subconsciously changed bar() to take a plain int rather than int& - after all, there is nothing to be gained passing an int by reference if it is const ).
It is not a problem with std::mem_fun either. You can see this from the following code:
Code:
#include <string>
typedef std::string varType;
class X
{
public:
void foo()
{
const varType v;
(std::mem_fun(&X::bar))(this,v);
(std::mem_fun(&X::barRef))(this,v);
(std::bind1st( std::mem_fun(&X::bar), this ))(v);
(std::bind1st( std::mem_fun(&X::barRef), this ))(v); // This line doesn't compile
}
private:
void bar(const varType s) const {}
void barRef(const varType& s) const {}
};
This all compiles except the indicated line, and this doesn't change if the varType typedef is change to int.
So, what is the problem Basically, std::bind1st doesn't accept a functor which takes reference arguments. This is because internally it forms references to these arguments, and you can't have references to references. I think this behaviour is actually prescribed by the C++ standard (C++03 at least).
boost::bind() must do this differently internally, hence it works.
Last edited by Peter_B; April 2nd, 2012 at 07:40 AM.
Reason: Typo
-
April 2nd, 2012, 07:15 AM
#4
Re: for_each and member function
given that you're using vc2010, why not using a lambda directly ?
Code:
std::for_each( v.begin(), v.end(), [this]( const std::string& s ){ bar( s ); } );
-
April 2nd, 2012, 07:55 AM
#5
Re: for_each and member function
Peter_B, thanks for this explanation. It didn't come to my mind that the reference might be the problem. I have played around with the bar() signature, making it const or not, making the parameter to bar const or not, but never thought about the reference. Then I changed bar() to take an int, and that worked, leaving me even more confused.
superbonzo, I was so concentrated on the member function that the lambda you propose didn't come to my mind.
Thanks for your contributions,
Richard
Tags for this Thread
Posting Permissions
- You may not post new threads
- You may not post replies
- You may not post attachments
- You may not edit your posts
-
Forum Rules
|
Click Here to Expand Forum to Full Width
|