Non-const "member functor" problem

L

Lionel B

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
 
S

Salt_Peter

Lionel said:
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
 
L

Lionel B

Lionel said:
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.
 

Ask a Question

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

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,755
Messages
2,569,536
Members
45,020
Latest member
GenesisGai

Latest Threads

Top