call_mem_fun

Discussion in 'C++' started by rile, Nov 15, 2006.

  1. rile

    rile Guest

    I have this problem that I meet quite often.

    I have a STL container with bunch of whatever objects. The container is
    a member of a class that does something. Now, I want to apply a member
    of this class to each of the contained objects.

    mem_fun will CALL the given member function OF THE CONTAINED object,
    but what I want is to call the given method of the CONTAINING object
    with the argument being a contained object.

    For example:


    class Foo
    {
    public:
    ....
    void doSomething(int i)
    {
    cout << i << endl;
    }

    void doSomethingWithEach()
    {
    for_each<myv.begin(), myv.end(), call_mem_fun(&Foo::doSomething,
    this));
    }


    std::vector<int> myv;
    };

    NOTE:
    call_mem_fun would call "doSomething" and pass to it each int from the
    container.



    ================
    So I created the "call_mem_fun" functor, but I'm not sure if I was
    reinventing the wheel (just can not believe there is not such thing
    already out there somewhere).


    Any suggestions?
     
    rile, Nov 15, 2006
    #1
    1. Advertising

  2. rile

    mlimber Guest

    rile wrote:
    > I have this problem that I meet quite often.
    >
    > I have a STL container with bunch of whatever objects. The container is
    > a member of a class that does something. Now, I want to apply a member
    > of this class to each of the contained objects.
    >
    > mem_fun will CALL the given member function OF THE CONTAINED object,
    > but what I want is to call the given method of the CONTAINING object
    > with the argument being a contained object.
    >
    > For example:
    >
    >
    > class Foo
    > {
    > public:
    > ...
    > void doSomething(int i)
    > {
    > cout << i << endl;
    > }
    >
    > void doSomethingWithEach()
    > {
    > for_each<myv.begin(), myv.end(), call_mem_fun(&Foo::doSomething,
    > this));
    > }
    >
    >
    > std::vector<int> myv;
    > };
    >
    > NOTE:
    > call_mem_fun would call "doSomething" and pass to it each int from the
    > container.
    >
    >
    >
    > ================
    > So I created the "call_mem_fun" functor, but I'm not sure if I was
    > reinventing the wheel (just can not believe there is not such thing
    > already out there somewhere).
    >
    >
    > Any suggestions?


    std::tr1::bind does the same thing (cf. Boost.Bind).

    Cheers! --M
     
    mlimber, Nov 15, 2006
    #2
    1. Advertising

  3. rile

    rile Guest

    I read a bout bind, but I couldn't find the version that does what I
    want...

    Here is compilable example of the use-case I am looking for; could you
    add using "bind" so the code is functionally the same?

    Thanks!


    #include <vector>
    #include <algorithm>
    #include <iostream>
    using namespace std;
    class Bar
    {
    public:
    Bar(int n) : _n(n) {}
    int getN() const { return _n; }
    private:
    int _n;
    };
    class Foo
    {
    public:
    Foo()
    {
    for (int i = 0; i != 10; ++i)
    bars.push_back(Bar(i));
    }
    void printABar(Bar const &bar) const
    {
    cout << bar.getN() << endl;
    }
    void printAllBars() const
    {
    for_each(bars.begin(), bars.end(), call_mem_fun(&Foo::printABar,
    this));
    }
    private:
    vector<Bar> bars;
    };

    .... in main:

    Foo foo;
    foo.printAllBars();

    (RESULT: it prints out to the console numbers 0 to 9 each in a new
    line)


    mlimber wrote:
    > rile wrote:
    > > I have this problem that I meet quite often.
    > >
    > > I have a STL container with bunch of whatever objects. The container is
    > > a member of a class that does something. Now, I want to apply a member
    > > of this class to each of the contained objects.
    > >
    > > mem_fun will CALL the given member function OF THE CONTAINED object,
    > > but what I want is to call the given method of the CONTAINING object
    > > with the argument being a contained object.
    > >
    > > For example:
    > >
    > >
    > > class Foo
    > > {
    > > public:
    > > ...
    > > void doSomething(int i)
    > > {
    > > cout << i << endl;
    > > }
    > >
    > > void doSomethingWithEach()
    > > {
    > > for_each<myv.begin(), myv.end(), call_mem_fun(&Foo::doSomething,
    > > this));
    > > }
    > >
    > >
    > > std::vector<int> myv;
    > > };
    > >
    > > NOTE:
    > > call_mem_fun would call "doSomething" and pass to it each int from the
    > > container.
    > >
    > >
    > >
    > > ================
    > > So I created the "call_mem_fun" functor, but I'm not sure if I was
    > > reinventing the wheel (just can not believe there is not such thing
    > > already out there somewhere).
    > >
    > >
    > > Any suggestions?

    >
    > std::tr1::bind does the same thing (cf. Boost.Bind).
    >
    > Cheers! --M
     
    rile, Nov 15, 2006
    #3
  4. rile

    Daniel T. Guest

    "rile" <> wrote:

    > I have this problem that I meet quite often.
    >
    > I have a STL container with bunch of whatever objects. The container is
    > a member of a class that does something. Now, I want to apply a member
    > of this class to each of the contained objects.
    >
    > mem_fun will CALL the given member function OF THE CONTAINED object,
    > but what I want is to call the given method of the CONTAINING object
    > with the argument being a contained object.
    >
    > For example:
    >
    >
    > class Foo
    > {
    > public:
    > ...
    > void doSomething(int i)
    > {
    > cout << i << endl;
    > }
    >
    > void doSomethingWithEach()
    > {
    > for_each<myv.begin(), myv.end(), call_mem_fun(&Foo::doSomething,
    > this));
    > }
    >
    >
    > std::vector<int> myv;
    > };
    >
    > NOTE:
    > call_mem_fun would call "doSomething" and pass to it each int from the
    > container.
    >
    >
    >
    > ================
    > So I created the "call_mem_fun" functor, but I'm not sure if I was
    > reinventing the wheel (just can not believe there is not such thing
    > already out there somewhere).
    >
    >
    > Any suggestions?


    for_each( vec.begin(), vec.end(), bind1st( mem_fun(&Foo::bar), this ) );

    --
    To send me email, put "sheltie" in the subject.
     
    Daniel T., Nov 15, 2006
    #4
  5. rile

    Pete Becker Guest

    rile wrote:
    >
    > void doSomethingWithEach()
    > {
    > for_each<myv.begin(), myv.end(), call_mem_fun(&Foo::doSomething,
    > this));
    > }
    >


    bind1st(mem_fun(&Foo::doSomething), this)

    If you have TR1 you can make it a bit simpler:


    bind(&Foo::doSomething, this, _1)

    --

    -- Pete
    Roundhouse Consulting, Ltd. (www.versatilecoding.com)
    Author of "The Standard C++ Library Extensions: a Tutorial and
    Reference." (www.petebecker.com/tr1book)
     
    Pete Becker, Nov 15, 2006
    #5
  6. rile

    rile Guest

    Thank you for your replies.

    bind1st(mem_fun(&Foo::bar), this))

    was what I considered first, but it seems that it won't work if 'bar'
    takes reference to argument type (like in my example above). At least
    not on MS VS 2005.

    well, here is my implementation for those who want to see the diff
    (NOTE: I renamed my function "pass_to_mem_fun" because I thought it was
    clearer than "call_mem_fun")

    template <typename _Result, typename T, typename ArgT>
    class pass_to_mem_fun_t : public std::unary_function<ArgT, _Result>
    {
    public:
    explicit pass_to_mem_fun_t(_Result (T::*_Pm)(ArgT), T *pThis)
    : _Pmemfun(_Pm), _this(pThis)
    {
    }

    _Result operator()(ArgT _Pleft) const
    { // call function
    return (_this->*_Pmemfun)(_Pleft);
    }

    private:
    T *_this;
    _Result (T::*_Pmemfun)(ArgT); // the member function pointer
    };

    template <typename _Result, typename T, typename ArgT>
    class pass_to_const_mem_fun_t : public std::unary_function<ArgT,
    _Result>
    {
    public:
    explicit pass_to_const_mem_fun_t(_Result (T::*_Pm)(ArgT) const, T
    const *pThis)
    : _Pmemfun(_Pm), _this(pThis)
    {
    }

    _Result operator()(ArgT _Pleft) const
    { // call function
    return (_this->*_Pmemfun)(_Pleft);
    }

    private:
    T const *_this;
    _Result (T::*_Pmemfun)(ArgT) const; // the member function pointer
    };
    template <typename _Result, typename T, typename ArgT>
    pass_to_mem_fun_t<_Result, T, ArgT>
    pass_to_mem_fun(_Result (T::*pFn)(ArgT), T *pThis)
    {
    return pass_to_mem_fun_t<_Result, T, ArgT>(pFn, pThis);
    }

    template <typename _Result, typename T, typename ArgT>
    pass_to_const_mem_fun_t<_Result, const T, ArgT>
    pass_to_mem_fun(_Result (T::*pFn)(ArgT) const, T const*pThis)
    {
    return pass_to_const_mem_fun_t<_Result, const T, ArgT>(pFn, pThis);
    }

    ------------

    in the foo-bar example I gave, the call would look like this:

    for_each(bars.begin(), bars.end(), pass_to_mem_fun(&Foo::printABar,
    this));

    ====

    Anyhow, if you see that the "Foo bar" example I posted can be compiled
    with any of the standard alternatives, I am eager to know it.

    Thank you,

    Aleksandar

    On Nov 15, 4:13 pm, Pete Becker <> wrote:
    > rile wrote:
    >
    > > void doSomethingWithEach()
    > > {
    > > for_each<myv.begin(), myv.end(), call_mem_fun(&Foo::doSomething,
    > > this));
    > > } bind1st(mem_fun(&Foo::doSomething), this)

    >
    > If you have TR1 you can make it a bit simpler:
    >
    > bind(&Foo::doSomething, this, _1)
    >
    > --
    >
    > -- Pete
    > Roundhouse Consulting, Ltd. (www.versatilecoding.com)
    > Author of "The Standard C++ Library Extensions: a Tutorial and
    > Reference." (www.petebecker.com/tr1book)
     
    rile, Nov 15, 2006
    #6
  7. rile

    Salt_Peter Guest

    rile wrote:
    > I have this problem that I meet quite often.
    >
    > I have a STL container with bunch of whatever objects. The container is
    > a member of a class that does something. Now, I want to apply a member
    > of this class to each of the contained objects.
    >
    > mem_fun will CALL the given member function OF THE CONTAINED object,
    > but what I want is to call the given method of the CONTAINING object
    > with the argument being a contained object.
    >
    > For example:
    >
    >
    > class Foo
    > {
    > public:
    > ...
    > void doSomething(int i)
    > {
    > cout << i << endl;
    > }
    >
    > void doSomethingWithEach()
    > {
    > for_each<myv.begin(), myv.end(), call_mem_fun(&Foo::doSomething,
    > this));
    > }
    >
    >
    > std::vector<int> myv;
    > };
    >
    > NOTE:
    > call_mem_fun would call "doSomething" and pass to it each int from the
    > container.
    >
    >
    >
    > ================
    > So I created the "call_mem_fun" functor, but I'm not sure if I was
    > reinventing the wheel (just can not believe there is not such thing
    > already out there somewhere).
    >
    >
    > Any suggestions?


    As already mentioned: boost's lambda and bind
    http://www.boost.org/libs/bind/bind.html

    #include <iostream>
    #include <vector>
    #include <algorithm>
    #include <boost/lambda/lambda.hpp>
    #include <boost/lambda/bind.hpp>

    template< typename T >
    class Foo
    {
    std::vector< T > myv;
    public:

    void push_back(const T& r_t)
    {
    myv.push_back( r_t );
    }

    static void doSomething( const T& t ) {
    std::cout << t << std::endl;
    }

    void doSomethingWithEach() const {
    using boost::lambda::_1;
    using boost::lambda::bind;
    std::for_each( myv.begin(),
    myv.end(),
    bind(&doSomething, _1) );
    }
    };

    int main()
    {
    Foo< int > foo;
    foo.push_back(0);
    foo.push_back(1);
    foo.push_back(2);

    foo.doSomethingWithEach();
    }

    /*
    0
    1
    2
    */
     
    Salt_Peter, Nov 15, 2006
    #7
  8. rile

    Pete Becker Guest

    rile wrote:
    >
    > bind1st(mem_fun(&Foo::bar), this))
    >
    > was what I considered first, but it seems that it won't work if 'bar'
    > takes reference to argument type (like in my example above).
    >


    In your original example, the member function takes its argument by
    value, not by reference.

    STL in its original form passes just about everything by value, and
    that's a limitation of mem_fun. The bind version works for references.

    --

    -- Pete
    Roundhouse Consulting, Ltd. (www.versatilecoding.com)
    Author of "The Standard C++ Library Extensions: a Tutorial and
    Reference." (www.petebecker.com/tr1book)
     
    Pete Becker, Nov 15, 2006
    #8
  9. rile

    rile Guest

    OK, boost::bind works!

    for_each(bars.begin(), bars.end(), boost::bind(&Foo::doSomething, &foo,
    _1));

    boost::bind does it!

    Thank you all for your replies.

    Pete Becker wrote:
    > rile wrote:
    > >
    > > bind1st(mem_fun(&Foo::bar), this))
    > >
    > > was what I considered first, but it seems that it won't work if 'bar'
    > > takes reference to argument type (like in my example above).
    > >

    >
    > In your original example, the member function takes its argument by
    > value, not by reference.
    >
    > STL in its original form passes just about everything by value, and
    > that's a limitation of mem_fun. The bind version works for references.
    >
    > --
    >
    > -- Pete
    > Roundhouse Consulting, Ltd. (www.versatilecoding.com)
    > Author of "The Standard C++ Library Extensions: a Tutorial and
    > Reference." (www.petebecker.com/tr1book)
     
    rile, Nov 16, 2006
    #9
    1. Advertising

Want to reply to this thread or ask your own question?

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.

Share This Page