Non-const "member functor" problem

Discussion in 'C++' started by Lionel B, Dec 1, 2006.

  1. Lionel B

    Lionel B Guest

    I have a function which takes a functor argument. I which to call it for a
    functor which is actually a class member; this works fine, using
    the mem_fun_ref and bind1st functions (see listing 1 below). Or, rather,
    it works fine as long as my member functor is const. The problem comes
    when I wish to use it for a *non*-const functor (see listing 2 below):

    *** Start listing 1 ***************************************************

    // test1.cpp

    #include <iostream>

    // function taking (ref. to) functor
    template<typename F> double bar(const F& f, double x, double y)
    {
    return f(x)+y;
    }

    // class with member functor
    class Object
    {
    private:
    double a, b;

    public:
    Object(double a_, double b_) : a(a_), b(b_) {}

    // the (const) member functor
    double foo(double x) const {return a*x+b;}
    };

    int main(int argc, char* argv[])
    {
    using namespace std;

    // create object
    Object object(2.0,3.0);

    // create functor ref from member functor "foo", bind to object
    // and pass to function "bar"
    double z = bar(bind1st(mem_fun_ref(&Object::foo),object),1.0,2.0);

    cout << "z = " << z << '\n';

    return 0;
    }

    *** End listing 1 *****************************************************

    $ g++ test1.cpp -o test1
    $ ./test1
    z = 7

    So far so good. Now I try to make the member functor "foo" non-const:

    *** Start listing 2 ***************************************************

    // test2.cpp

    #include <iostream>

    // function taking (ref. to) functor
    template<typename F> double bar(F& f, double x, double y)
    {
    return f(x)+y;
    }

    // class with member functor
    class Object
    {
    private:
    double a, b;

    public:
    Object(double a_, double b_) : a(a_), b(b_) {}

    // the (non-const) member functor
    double foo(double x) {return a*x+b;}
    };

    int main(int argc, char* argv[])
    {
    using namespace std;

    // create object
    Object object(2.0,3.0);

    // create functor ref from member functor "foo", bind to object
    // and pass to function "bar"
    double z = bar(bind1st(mem_fun_ref(&Object::foo),object),1.0,2.0);

    cout << "z = " << z << '\n';

    return 0;
    }

    *** End listing 2 *****************************************************

    Note that I have made the first argument of bar now a *non* const ref:

    $ g++ test2.cpp -o test2
    test2.cpp: In function ‘int main(int, char**)’:
    test2.cpp:33: error: no matching function for call to ‘bar(std::binder1st<std::mem_fun1_ref_t<double, Object, double> >, double, double)’
    test2.cpp:6: note: candidates are: double bar(F&, double, double) [with F = std::binder1st<std::mem_fun1_ref_t<double, Object, double> >]

    I don't understand this, as I would have thought that there'd be sensible
    non-const overloads for the binder and mem_fun routines...

    Any help much appreciated.

    Using gcc 4.1.1 on RHEL linux on x86_64

    --
    Lionel B
    Lionel B, Dec 1, 2006
    #1
    1. Advertising

  2. Lionel B

    Salt_Peter Guest

    Lionel B wrote:
    > I have a function which takes a functor argument. I which to call it for a
    > functor which is actually a class member; this works fine, using
    > the mem_fun_ref and bind1st functions (see listing 1 below). Or, rather,
    > it works fine as long as my member functor is const. The problem comes
    > when I wish to use it for a *non*-const functor (see listing 2 below):
    >
    > *** Start listing 1 ***************************************************
    >
    > // test1.cpp
    >
    > #include <iostream>
    >
    > // function taking (ref. to) functor
    > template<typename F> double bar(const F& f, double x, double y)
    > {
    > return f(x)+y;
    > }
    >
    > // class with member functor
    > class Object
    > {
    > private:
    > double a, b;
    >
    > public:
    > Object(double a_, double b_) : a(a_), b(b_) {}
    >
    > // the (const) member functor
    > double foo(double x) const {return a*x+b;}
    > };
    >
    > int main(int argc, char* argv[])
    > {
    > using namespace std;
    >
    > // create object
    > Object object(2.0,3.0);
    >
    > // create functor ref from member functor "foo", bind to object
    > // and pass to function "bar"
    > double z = bar(bind1st(mem_fun_ref(&Object::foo),object),1.0,2.0);
    >
    > cout << "z = " << z << '\n';
    >
    > return 0;
    > }
    >
    > *** End listing 1 *****************************************************
    >
    > $ g++ test1.cpp -o test1
    > $ ./test1
    > z = 7
    >
    > So far so good. Now I try to make the member functor "foo" non-const:
    >
    > *** Start listing 2 ***************************************************
    >
    > // test2.cpp
    >
    > #include <iostream>
    >
    > // function taking (ref. to) functor
    > template<typename F> double bar(F& f, double x, double y)
    > {
    > return f(x)+y;
    > }
    >
    > // class with member functor
    > class Object
    > {
    > private:
    > double a, b;
    >
    > public:
    > Object(double a_, double b_) : a(a_), b(b_) {}
    >
    > // the (non-const) member functor
    > double foo(double x) {return a*x+b;}
    > };
    >
    > int main(int argc, char* argv[])
    > {
    > using namespace std;
    >
    > // create object
    > Object object(2.0,3.0);
    >
    > // create functor ref from member functor "foo", bind to object
    > // and pass to function "bar"
    > double z = bar(bind1st(mem_fun_ref(&Object::foo),object),1.0,2.0);
    >
    > cout << "z = " << z << '\n';
    >
    > return 0;
    > }
    >
    > *** End listing 2 *****************************************************
    >
    > Note that I have made the first argument of bar now a *non* const ref:


    Switch both bind1st and mem_fun_ref over to boost and it works with
    non-const member function.
    However, it remains to be seen if you get what you seek. bar's first
    arguement must be const.
    #include <boost/functional.hpp>

    replace
    using namepsace std;
    with
    using boost::binder1st;
    using boost::mem_fun_ref;


    >
    > $ g++ test2.cpp -o test2
    > test2.cpp: In function 'int main(int, char**)':
    > test2.cpp:33: error: no matching function for call to 'bar(std::binder1st<std::mem_fun1_ref_t<double, Object, double> >, double, double)'
    > test2.cpp:6: note: candidates are: double bar(F&, double, double) [with F = std::binder1st<std::mem_fun1_ref_t<double, Object, double> >]
    >
    > I don't understand this, as I would have thought that there'd be sensible
    > non-const overloads for the binder and mem_fun routines...
    >
    > Any help much appreciated.
    >
    > Using gcc 4.1.1 on RHEL linux on x86_64
    >
    > --
    > Lionel B
    Salt_Peter, Dec 1, 2006
    #2
    1. Advertising

  3. Lionel B

    Lionel B Guest

    On Fri, 01 Dec 2006 08:11:56 -0800, Salt_Peter wrote:

    > Lionel B wrote:
    >> I have a function which takes a functor argument. I which to call it for a
    >> functor which is actually a class member; this works fine, using
    >> the mem_fun_ref and bind1st functions (see listing 1 below). Or, rather,
    >> it works fine as long as my member functor is const. The problem comes
    >> when I wish to use it for a *non*-const functor (see listing 2 below):
    >>

    [snip]
    >
    > Switch both bind1st and mem_fun_ref over to boost and it works with
    > non-const member function.
    > However, it remains to be seen if you get what you seek. bar's first
    > arguement must be const.
    >
    > #include <boost/functional.hpp>
    >
    > replace
    > using namepsace std;
    > with
    > using boost::binder1st;
    > using boost::mem_fun_ref;


    Yes, it works alright - thanks.

    Is this just down to a dodgy implementation of binder1st and mem_fun_ref? I
    tested my original code using Intel's compiler (icc 9.0 - which
    generally seems to be pretty good on standards support) and it failed in
    a similar way to gcc 4.1.

    --
    Lionel B
    Lionel B, Dec 1, 2006
    #3
    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. Replies:
    11
    Views:
    1,086
  2. Javier
    Replies:
    2
    Views:
    542
    James Kanze
    Sep 4, 2007
  3. 0m
    Replies:
    26
    Views:
    1,089
    Tim Rentsch
    Nov 10, 2008
  4. fungus
    Replies:
    13
    Views:
    870
    fungus
    Oct 31, 2008
  5. Replies:
    2
    Views:
    526
    Andrew Koenig
    Feb 9, 2009
Loading...

Share This Page