remove_if and member function pointers

Discussion in 'C++' started by Jon Rea, Nov 16, 2006.

  1. Jon Rea

    Jon Rea Guest

    Hello all,

    Sorry if this is long, but I wanted to be specific...

    Can anyone shed any light on the following errors in the context of the
    following example code:

    cullMethod1(); // compiles, but not what we want - we cant access
    m_Exclustions

    cullMethod2(); // fine but long-winded and causes many array re-allocations

    cullMethod3(); // doen't compile!

    i.e. How do you pass a member function to std functions.

    Many thanks,
    Jon Rea


    ////////////////////////////////////////////////////
    // Begin example code ..

    #include <vector>
    #include <algorithm>
    #include <functional>

    using namespace std;

    class Bond
    {
    public:
    Bond( int _i, int _j )
    {
    i = _i;
    j = _j;
    }
    Bond()
    {
    i = rand();
    j = rand();
    }
    int i;
    int j;
    };

    class MyBase
    {
    public:
    virtual void Setup()
    {
    int bigNumber = 10000;
    for( int i = 0; i < bigNumber; i++ )
    {
    m_Bonds.push_back( Bond() ); // add lots of random "bonds"
    }
    }
    protected:
    std::vector<Bond> m_Bonds;
    };

    bool mySpecialSelectionFunction( Bond& _b )
    {
    return _b.i == 47;
    }

    class MyDerived : public MyBase
    {
    public:
    virtual void Setup()
    {
    MyBase::Setup();

    m_Exclustions.push_back(Bond(43,21));
    m_Exclustions.push_back(Bond(12,14));
    m_Exclustions.push_back(Bond(1,41));

    // Remove all instances of the definitions in m_Exclustions from the
    base class list.

    // Call ONE of these in real code:
    cullMethod1(); // compiles, but not what we want - we cant access
    m_Exclustions
    cullMethod2(); // fine but long-whinded and causes many array
    re-allocations
    cullMethod3(); // doen't compile!
    }

    bool Matches( Bond& bond )
    {
    for( size_t k = 0; k < m_Exclustions.size(); k++ )
    {
    if( ( bond.i == m_Exclustions[k].i && bond.j == m_Exclustions[k].j ) ||
    ( bond.j == m_Exclustions[k].i && bond.i == m_Exclustions[k].j ) )
    {
    return true;
    }
    }
    return false;
    }

    void cullMethod1()
    {
    m_Bonds.erase( remove_if( m_Bonds.begin(), m_Bonds.end(),
    mySpecialSelectionFunction ), m_Bonds.end() );
    }

    void cullMethod2()
    {
    for( size_t i = 0; i < m_Bonds.size(); /*blank*/ )
    {
    if( Matches( m_Bonds ) )
    {
    m_Bonds.erase(m_Bonds.begin()+i);
    }
    else
    {
    i++;
    }
    }
    }

    void cullMethod3()
    {
    // Illegal operand on bound member function expression ...
    //m_Bonds.erase( remove_if( m_Bonds.begin(), m_Bonds.end(), &Matches
    ), m_Bonds.end() );

    // Term does not evaluare to a function taking 1 arguments ...
    //m_Bonds.erase( remove_if( m_Bonds.begin(), m_Bonds.end(),
    &MyDerived::Matches ), m_Bonds.end() );

    // Term does not evaluare to a function taking 1 arguments ...
    //m_Bonds.erase( remove_if( m_Bonds.begin(), m_Bonds.end(),
    std::mem_fun_ref(&MyDerived::Matches) ), m_Bonds.end() );
    }

    protected:
    std::vector<Bond> m_Exclustions;
    };

    int _tmain(int argc, _TCHAR* argv[])
    {
    MyDerived bob;
    bob.Setup();
    return 0;
    }
     
    Jon Rea, Nov 16, 2006
    #1
    1. Advertising

  2. Jon Rea

    Daniel T. Guest

    In article <>, Jon Rea <>
    wrote:

    > Hello all,
    >
    > Sorry if this is long, but I wanted to be specific...
    >
    > Can anyone shed any light on the following errors in the context of the
    > following example code:
    >
    > cullMethod1(); // compiles, but not what we want - we cant access
    > m_Exclustions
    >
    > cullMethod2(); // fine but long-winded and causes many array re-allocations
    >
    > cullMethod3(); // doen't compile!
    >
    > i.e. How do you pass a member function to std functions.


    First change the signature for Matches:

    bool Matches(Bond bond) const
    {
    ...
    }

    Then you can:

    void cullMethod1()
    {
    m_Bonds.erase(remove_if(m_Bonds.begin(), m_Bonds.end(),
    bind1st(mem_fun(&MyDerived::Matches), this)), m_Bonds.end());
    }

    --
    To send me email, put "sheltie" in the subject.
     
    Daniel T., Nov 17, 2006
    #2
    1. Advertising

  3. Jon Rea

    Jon Rea Guest

    Daniel T. wrote:
    > In article <>, Jon Rea <>
    > wrote:
    >
    >> Hello all,
    >>
    >> Sorry if this is long, but I wanted to be specific...
    >>
    >> Can anyone shed any light on the following errors in the context of the
    >> following example code:
    >>
    >> cullMethod1(); // compiles, but not what we want - we cant access
    >> m_Exclustions
    >>
    >> cullMethod2(); // fine but long-winded and causes many array re-allocations
    >>
    >> cullMethod3(); // doen't compile!
    >>
    >> i.e. How do you pass a member function to std functions.

    >
    > First change the signature for Matches:
    >
    > bool Matches(Bond bond) const
    > {
    > ...
    > }
    >
    > Then you can:
    >
    > void cullMethod1()
    > {
    > m_Bonds.erase(remove_if(m_Bonds.begin(), m_Bonds.end(),
    > bind1st(mem_fun(&MyDerived::Matches), this)), m_Bonds.end());
    > }
    >


    Thanks for the reply. Thats better!

    What though if I had to use:
    bool Matches(BIG_Bond& bond) const;
    because copying a 'BIG_Bond' is an expensive operation.

    Cheers,
    Jon
     
    Jon Rea, Nov 17, 2006
    #3
  4. Jon Rea

    Daniel T. Guest

    In article <>, Jon Rea <> wrote:

    > Daniel T. wrote:
    > > In article <>, Jon Rea <>
    > > wrote:
    > >
    > >> Hello all,
    > >>
    > >> Sorry if this is long, but I wanted to be specific...
    > >>
    > >> Can anyone shed any light on the following errors in the context of the
    > >> following example code:
    > >>
    > >> cullMethod1(); // compiles, but not what we want - we cant access
    > >> m_Exclustions
    > >>
    > >> cullMethod2(); // fine but long-winded and causes many array re-allocations
    > >>
    > >> cullMethod3(); // doen't compile!
    > >>
    > >> i.e. How do you pass a member function to std functions.

    > >
    > > First change the signature for Matches:
    > >
    > > bool Matches(Bond bond) const
    > > {
    > > ...
    > > }
    > >
    > > Then you can:
    > >
    > > void cullMethod1()
    > > {
    > > m_Bonds.erase(remove_if(m_Bonds.begin(), m_Bonds.end(),
    > > bind1st(mem_fun(&MyDerived::Matches), this)), m_Bonds.end());
    > > }
    > >

    >
    > Thanks for the reply. Thats better!
    >
    > What though if I had to use:
    > bool Matches(BIG_Bond& bond) const;
    > because copying a 'BIG_Bond' is an expensive operation.


    Test first. I would not be surprised to find that the compiler optimized
    the copy away if the Matches function doesn't modify the parameter in
    any way.

    However, if you absolutely *had* to use a const& the you can always
    create your own selector and then use:

    m_Bonds.erase(remove_if(m_Bonds.begin(), m_Bonds.end(),
    selector(&MyDerived::Matches, this)), m_Bonds.end());

    Before I show you what "selector" looks like, you may be interested in
    how I developed it. I put the above code in as the interface I wished,
    and then fixed the compile errors until I had something that ran. After
    than, I substituted templated tyeps. QED

    template < typename Ret, typename Tp, typename Arg >
    struct selector_t : unary_function< Arg, Ret >
    {
    Ret (Tp::*mfn)(Arg) const;
    const Tp* obj;

    selector_t(Ret(Tp::*x)(Arg) const, const Tp* y): mfn(x), obj(y) { }

    Ret operator()(Arg x) const {
    return (obj->*mfn)(x);
    }
    };

    template < typename Ret, typename Tp, typename Arg >
    selector_t< Ret, Tp, Arg > selector(Ret(Tp::*x)(Arg) const, Tp* y) {
    return selector_t< Ret, Tp, Arg >(x, y);
    }

    And yes, I double checked. Arg in the above template is a "const Bond&"
    and not a "Bond".

    --
    To send me email, put "sheltie" in the subject.
     
    Daniel T., Nov 18, 2006
    #4
    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.
Similar Threads
  1. Paavo K

    STL remove_if function

    Paavo K, Feb 17, 2004, in forum: C++
    Replies:
    1
    Views:
    4,323
    David Harmon
    Feb 17, 2004
  2. marco_segurini

    remove_if and functions overloading

    marco_segurini, Apr 7, 2004, in forum: C++
    Replies:
    1
    Views:
    1,105
    tom_usenet
    Apr 7, 2004
  3. n2xssvv g02gfr12930

    Smart pointers and member function pointers

    n2xssvv g02gfr12930, Nov 26, 2005, in forum: C++
    Replies:
    3
    Views:
    484
    n2xssvv g02gfr12930
    Nov 27, 2005
  4. Hamish
    Replies:
    3
    Views:
    598
    Alf P. Steinbach
    Jan 25, 2008
  5. paul
    Replies:
    8
    Views:
    741
    Alf P. Steinbach
    Apr 30, 2009
Loading...

Share This Page