How to use a class's member function in STL's algorithm?

Discussion in 'C++' started by want.to.be.professer, Jul 12, 2008.

  1. We know that alomost every algorithm function, such as for_each,
    find_if, use funcional as well as function pointer. But when I want
    to use another class's member function, how could I do?

    See example:


    class TestPrint
    {
    public:
    TestPrint( int i ) { start_num = i; }
    void print( int i )
    {
    cout << endl<< "| " << i + start_num <<
    " |" << endl;
    }
    private:
    int start_num;
    };

    int main()
    {
    TestPrint* pTest = new TestPrint( 8 );
    int a[10] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9};
    for_each( a, a + 9, /*** Use the pTest's "print" ***/ );
    delete pTest;
    return 0;
    }

    /*** Use the pTest's "print" ***/ is where I want to write code .
     
    want.to.be.professer, Jul 12, 2008
    #1
    1. Advertising

  2. On Jul 12, 4:54 pm, "want.to.be.professer" <>
    wrote:
    > We know that alomost every algorithm function, such as for_each,
    > find_if,  use funcional as well as function pointer. But when I want
    > to use another class's member function, how could I do?
    >
    > See example:
    >
    > class TestPrint
    > {
    > public:
    >         TestPrint( int i ) { start_num = i; }
    >         void print( int i )
    >         {
    >                 cout << endl<< "|        " << i + start_num <<
    > "                |" << endl;
    >         }
    > private:
    >         int start_num;
    >
    > };
    >
    > int main()
    > {
    >         TestPrint* pTest = new TestPrint( 8 );
    >         int  a[10] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9};
    >         for_each( a, a + 9, /*** Use the pTest's "print" ***/ );
    >         delete pTest;
    >         return 0;
    >
    > }
    >
    > /*** Use the pTest's "print" ***/ is where I want to write code .


    sorry

    > for_each( a, a + 9, /*** Use the pTest's "print" ***/ );

    should be
    > for_each( a, a + 10, /*** Use the pTest's "print" ***/ );
     
    want.to.be.professer, Jul 12, 2008
    #2
    1. Advertising

  3. On Jul 12, 1:59 pm, "want.to.be.professer" <>
    wrote:
    > On Jul 12, 4:54 pm, "want.to.be.professer" <>
    > wrote:
    > > We know that alomost every algorithm function, such as for_each,
    > > find_if,  use funcional as well as function pointer. But when I want
    > > to use another class's member function, how could I do?

    >
    > > See example:

    >
    > > class TestPrint
    > > {
    > > public:
    > >         TestPrint( int i ) { start_num = i; }
    > >         void print( int i )
    > >         {
    > >                 cout << endl<< "|        " << i + start_num <<
    > > "                |" << endl;
    > >         }
    > > private:
    > >         int start_num;

    >
    > > };

    >
    > > int main()
    > > {
    > >         TestPrint* pTest = new TestPrint( 8 );
    > >         int  a[10] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9};
    > >         for_each( a, a + 9, /*** Use the pTest's "print" ***/ );
    > >         delete pTest;
    > >         return 0;

    >
    > > }

    >
    > > /*** Use the pTest's "print" ***/ is where I want to write code .

    >
    > sorry
    >
    > >         for_each( a, a + 9, /*** Use the pTest's "print" ***/ );

    > should be
    > >         for_each( a, a + 10, /*** Use the pTest's "print" ***/ );


    You can use binders like boost::bind, or standard binders like bind1st
    (here) / bind2nd along with std::mem_fun_ref.

    for_each( a, a + 9, bind(&TestPrint::print, pTest, _1));

    Make the print member a const member function, else std:: binders
    won't probably work.
     
    Abhishek Padmanabh, Jul 12, 2008
    #3
  4. On Jul 12, 5:26 pm, Abhishek Padmanabh <>
    wrote:
    > On Jul 12, 1:59 pm, "want.to.be.professer" <>
    > wrote:
    >
    >
    >
    > > On Jul 12, 4:54 pm, "want.to.be.professer" <>
    > > wrote:
    > > > We know that alomost every algorithm function, such as for_each,
    > > > find_if,  use funcional as well as function pointer. But when I want
    > > > to use another class's member function, how could I do?

    >
    > > > See example:

    >
    > > > class TestPrint
    > > > {
    > > > public:
    > > >         TestPrint( int i ) { start_num = i; }
    > > >         void print( int i )
    > > >         {
    > > >                 cout << endl<< "|        " << i + start_num <<
    > > > "                |" << endl;
    > > >         }
    > > > private:
    > > >         int start_num;

    >
    > > > };

    >
    > > > int main()
    > > > {
    > > >         TestPrint* pTest = new TestPrint( 8 );
    > > >         int  a[10] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9};
    > > >         for_each( a, a + 9, /*** Use the pTest's "print" ***/ );
    > > >         delete pTest;
    > > >         return 0;

    >
    > > > }

    >
    > > > /*** Use the pTest's "print" ***/ is where I want to write code .

    >
    > > sorry

    >
    > > >         for_each( a, a + 9, /*** Use the pTest's "print" ***/ );

    > > should be
    > > >         for_each( a, a + 10, /*** Use the pTest's "print" ***/ );

    >
    > You can use binders like boost::bind, or standard binders like bind1st
    > (here) / bind2nd along with std::mem_fun_ref.
    >
    >                 for_each( a, a + 9, bind(&TestPrint::print, pTest, _1));
    >
    > Make the  print member a const member function, else std:: binders
    > won't probably work.

    please tell me how to use standard binders like bind1st
    (here) / bind2nd along with std::mem_fun_ref.

    Thank you!
     
    want.to.be.professer, Jul 12, 2008
    #4
  5. want.to.be.professer

    Daniel T. Guest

    On Jul 12, 4:54 am, "want.to.be.professer" <>
    wrote:
    > We know that alomost every algorithm function, such as for_each,
    > find_if,  use funcional as well as function pointer. But when I want
    > to use another class's member function, how could I do?
    >
    > See example:
    >
    > class TestPrint
    > {
    > public:
    >         TestPrint( int i ) { start_num = i; }
    >         void print( int i )
    >         {
    >                 cout << endl<< "|        " << i + start_num <<
    > "                |" << endl;
    >         }
    > private:
    >         int start_num;
    >
    > };
    >
    > int main()
    > {
    >         TestPrint* pTest = new TestPrint( 8 );
    >         int  a[10] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9};
    >         for_each( a, a + 9, /*** Use the pTest's "print" ***/ );
    >         delete pTest;
    >         return 0;
    >
    > }
    >
    > /*** Use the pTest's "print" ***/ is where I want to write code .


    First the obvious:

    struct foo
    {
    TestPrint* testPrint;
    foo( TestPrint* tp ): testPrint( tp ) { }
    void operator()( int i ) {
    testPrint->print( i );
    }
    };

    for_each( a, a + 9, foo( pTest ) );

    the above structure can be built with the standard functional objects
    as well:


    for_each( a, a + 9, bind1st( mem_fun( &TestPrint::print ), pTest ) );

    mem_fun wraps TestPrint::print into a function object that takes two
    parameters (TestPrint* and int), and bind1st wraps the mem_fun into a
    function object that always passes pTest as the first parameter.
     
    Daniel T., Jul 12, 2008
    #5
  6. On Jul 12, 10:24 pm, "Daniel T." <> wrote:
    > On Jul 12, 4:54 am, "want.to.be.professer" <>
    > wrote:
    >
    >
    >
    > > We know that alomost every algorithm function, such as for_each,
    > > find_if,  use funcional as well as function pointer. But when I want
    > > to use another class's member function, how could I do?

    >
    > > See example:

    >
    > > class TestPrint
    > > {
    > > public:
    > >         TestPrint( int i ) { start_num = i; }
    > >         void print( int i )
    > >         {
    > >                 cout << endl<< "|        " << i + start_num <<
    > > "                |" << endl;
    > >         }
    > > private:
    > >         int start_num;

    >
    > > };

    >
    > > int main()
    > > {
    > >         TestPrint* pTest = new TestPrint( 8 );
    > >         int  a[10] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9};
    > >         for_each( a, a + 9, /*** Use the pTest's "print" ***/ );
    > >         delete pTest;
    > >         return 0;

    >
    > > }

    >
    > > /*** Use the pTest's "print" ***/ is where I want to write code .

    >
    > First the obvious:
    >
    > struct foo
    > {
    >         TestPrint* testPrint;
    >         foo( TestPrint* tp ): testPrint( tp ) { }
    >         void operator()( int i ) {
    >                 testPrint->print( i );
    >         }
    >
    > };
    >
    > for_each( a, a + 9, foo( pTest ) );
    >
    > the above structure can be built with the standard functional objects
    > as well:
    >
    > for_each( a, a + 9, bind1st( mem_fun( &TestPrint::print ), pTest ) );
    >
    > mem_fun wraps TestPrint::print into a function object that takes two
    > parameters (TestPrint* and int), and bind1st wraps the mem_fun into a
    > function object that always passes pTest as the first parameter.


    en, Thank you
    for_each( a, a + 9, bind1st( mem_fun( &TestPrint::print ), pTest ) );
    this is what I want,
    I'd better review the STL.
     
    want.to.be.professer, Jul 12, 2008
    #6
  7. want.to.be.professer

    Jerry Coffin Guest

    In article <e66af743-5009-4e68-bfe6-5734bd324ab4
    @k13g2000hse.googlegroups.com>, says...

    [ ... ]

    > class TestPrint
    > {
    > public:
    > TestPrint( int i ) { start_num = i; }
    > void print( int i )
    > {
    > cout << endl<< "| " << i + start_num <<
    > " |" << endl;
    > }
    > private:
    > int start_num;
    > };
    >
    > int main()
    > {
    > TestPrint* pTest = new TestPrint( 8 );


    Why are you allocating this dynamically? You're doing dynamic
    allocation, but using it to imitate automatic allocation (i.e.
    allocating it as you enter a scope and deleting it as you leave that
    scope). With that given, automatic allocation would be far more suitable
    under the circumstances.

    > int a[10] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9};
    > for_each( a, a + 9, /*** Use the pTest's "print" ***/ );


    The direct, obvious answers to your question would involve things like
    mem_fun or mem_fun_ref. Personally, however, I've become convinced that
    while these were well intended, using them is a mistake far more often
    than not. Code using them is rarely readable, and (more importantly)
    over time I've become convinced that they're _usually_ a sign of poor
    design anyway.

    It's less obvious, but when you get down to it, TestPrint is really a
    functor. All you ever do with it is create it, and then invoke one
    member function -- and that member function is basically a repetition of
    the verb in the name of the class. The 'print' doesn't add any useful
    information -- TestPrint() would mean as much as TestPrint::print().

    General observation: when a class name is primarily a verb instead of a
    noun, there's a pretty good chance that class should be a functor.

    What I think you really should do is change your code to more accurately
    reflect the nature of TestPrint, making it a real functor.

    class TestPrint {
    int start_num;
    public:
    TestPrint(int i) : start_num(i) {}
    void operator()(int i) {
    cout << endl<< "| "
    << i + start_num
    << " |" << endl;
    }
    };

    Having done that, invocation becomes trivial:

    int main() {
    int a[] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9};
    for_each(a, a+9, TestPrint(8));
    return 0;
    }

    Contrary to what you said elsthread, in this case it should be a+9, NOT
    a+10. IMO, it's worthwhile to write code to handle this for you though:

    template <class T, size_t N>
    T *end(T (&a)[N]) {
    return a+N;
    }

    Then you can use:

    for_each(a, end(a), TestPrint(8));

    Though it's not really related to your original question, there's also
    the minor detail of the formatting you used for the output. At a guess,
    this is probably closer to what you really wanted:

    cout << "|" << setw(10) << i+start_num << setw(17) << "|" << endl;

    --
    Later,
    Jerry.

    The universe is a figment of its own imagination.
     
    Jerry Coffin, Jul 12, 2008
    #7
  8. want.to.be.professer

    joseph cook Guest

    On Jul 12, 11:58 am, Jerry Coffin <> wrote:
    <snip>
    > Contrary to what you said elsthread, in this case it should be a+9, NOT
    > a+10. IMO, it's worthwhile to write code to handle this for you though:
    >
    > template <class T, size_t N>
    > T *end(T (&a)[N]) {
    >         return a+N;


    All great points here; I very much agree. Except "a+10" _is_ correct.

    Although we won't hold you responsible, since your helper function
    would return the correct amount in this case.

    Joe Cook
     
    joseph cook, Jul 12, 2008
    #8
  9. On Jul 12, 11:58 pm, Jerry Coffin <> wrote:
    > In article <e66af743-5009-4e68-bfe6-5734bd324ab4
    > @k13g2000hse.googlegroups.com>, says...
    >


    Thanks for your explaination.But I cann't get the follow advise :

    > Contrary to what you said elsthread, in this case it should be a+9, NOT
    > a+10. IMO,


    Let's look at the source code of " for_each ":

    // for_each. Apply a function to every element of a range.
    template <class _InputIter, class _Function>
    _Function for_each(_InputIter __first, _InputIter __last,
    _Function __f) {
    __STL_REQUIRES(_InputIter, _InputIterator);
    for ( ; __first != __last; ++__first)
    __f(*__first);
    return __f;
    }

    Note the "__first != __last" .When used a+9, at the end, __first ==
    &a[9], but a[9] is never printed.
    So I thind "a+10" is correct.
     
    want.to.be.professer, Jul 13, 2008
    #9
  10. want.to.be.professer

    Jerry Coffin Guest

    In article <d5fd36ec-ce61-49d4-b1f1-
    >, says...
    > On Jul 12, 11:58 pm, Jerry Coffin <> wrote:
    > > In article <e66af743-5009-4e68-bfe6-5734bd324ab4
    > > @k13g2000hse.googlegroups.com>, says...
    > >

    >
    > Thanks for your explaination.But I cann't get the follow advise :
    >
    > > Contrary to what you said elsthread, in this case it should be a+9, NOT
    > > a+10. IMO,


    As well you shouldn't -- I just plain screwed up.

    --
    Later,
    Jerry.

    The universe is a figment of its own imagination.
     
    Jerry Coffin, Jul 13, 2008
    #10
    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. E11
    Replies:
    1
    Views:
    4,844
    Thomas Weidenfeller
    Oct 12, 2005
  2. Replies:
    12
    Views:
    729
    fluden
    Feb 11, 2005
  3. many_years_after
    Replies:
    6
    Views:
    768
    Pete Becker
    Jul 19, 2007
  4. many_years_after
    Replies:
    2
    Views:
    377
    James Kanze
    Jul 20, 2007
  5. Praetorian
    Replies:
    11
    Views:
    2,365
    James Kanze
    Apr 3, 2008
Loading...

Share This Page