CodeGuru Home VC++ / MFC / C++ .NET / C# Visual Basic VB Forums Developer.com
Results 1 to 5 of 5
  1. #1
    Join Date
    May 2001
    Location
    Germany
    Posts
    1,158

    [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

  2. #2
    Join Date
    May 2007
    Location
    Scotland
    Posts
    1,164

    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.

  3. #3
    Join Date
    Jan 2009
    Posts
    596

    Re: for_each and member function

    Quote Originally Posted by Richard.J View Post
    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

  4. #4
    Join Date
    Oct 2008
    Posts
    1,456

    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 ); } );

  5. #5
    Join Date
    May 2001
    Location
    Germany
    Posts
    1,158

    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
  •  





Click Here to Expand Forum to Full Width

Featured