Reputation: 8287
What's wrong with the following snippet ?
#include <tr1/functional>
#include <functional>
#include <iostream>
using namespace std::tr1::placeholders;
struct abc
{
typedef void result_type;
void hello(int)
{ std::cout << __PRETTY_FUNCTION__ << std::endl; }
void hello(int) const
{ std::cout << __PRETTY_FUNCTION__ << std::endl; }
abc()
{}
};
int
main(int argc, char *argv[])
{
const abc x;
int a = 1;
std::tr1::bind(&abc::hello, x , _1)(a);
return 0;
}
Trying to compile it with g++-4.3, it seems that cv-qualifier overloaded functions confuse both tr1::mem_fn<>
and tr1::bind<>
and it comes out the following error:
no matching function for call to ‘bind(<unresolved overloaded function type>,...
Instead the following snippet compiles but seems to break the const-correctness:
struct abc
{
typedef void result_type;
void operator()(int)
{ std::cout << __PRETTY_FUNCTION__ << std::endl; }
void operator()(int) const
{ std::cout << __PRETTY_FUNCTION__ << std::endl; }
abc()
{}
};
...
const abc x;
int a = 1;
std::tr1::bind( x , _1)(a);
Any clue?
Upvotes: 6
Views: 3238
Reputation: 14526
This question has been answered, but I find the best way to specify an overload with bind is to specify it on the template:
std::tr1::bind<void(foo::*)(int)>(&foo::bar);
This method is just as explicit, but shorter than casting (with static_cast
anyway. But it's cleaner than the C-cast, which is the same length.
Upvotes: 1
Reputation: 8287
As John suggested, the problems arisen in those snippets are the following:
bind()
are passed arguments by value.The first problem is solved by casting the member function pointer provided to bind:
std::tr1::bind(static_cast< void(abc::*)(int) const >(&abc::hello), x, _1)(a);
The second can be solved by passing the callable object by address (as John suggested), or by means of TR1 reference_wrapper<>
-- otherwise it will be passed by value, making the const-correctness breaking hallucination.
Given x a callable object:
std::tr1::bind( std::tr1::ref(x) , _1)(a);
bind()
will forward a
to the proper operator()
in accordance to the x constness.
Upvotes: 1
Reputation: 249592
The lookup is done at a time when the constness of this
is not known. You just have to give it a hint via casting. Try this:
typedef void (abc::*fptr)(int) const; // or remove const
std::tr1::bind((fptr)&abc::hello, x , _1)(a);
You may also notice here that removing the const
still works. This is because you should be passing x by pointer (because the first argument to a C++ member function, the implicit this
parameter, is always a pointer). Try this instead:
typedef void (abc::*fptr)(int) const; // won't compile without const (good!)
std::tr1::bind((fptr)&abc::hello, &x , _1)(a);
As discovered during within my comments below, if you omit the &
as you originally did, you'll be passing x by value, which is usually not what you want (though it makes little practical difference in your particular example). This actually seems like an unfortunate pitfall for bind
.
Upvotes: 5