问题
I have class with a member function that takes a default argument.
struct Class
{
void member(int n = 0)
{}
};
By means of std::tr1::mem_fn I can invoke it:
Class object;
std::tr1::mem_fn(&Class::member)(object,10);
That said, if I want to invoke the callable member on the object with the default argument, what's the correct syntax?
std::tr1::mem_fn(&Class::member)(object); // This does not work
g++ complains with the following error:
test.cc:17: error: no match for call to ‘(std::tr1::_Mem_fn<void (Class::*)(int)>) (Class&)’
/usr/include/c++/4.3/tr1_impl/functional:551: note: candidates are: _Res std::tr1::_Mem_fn<_Res (_Class::*)(_ArgTypes ...)>::operator()(_Class&, _ArgTypes ...) const [with _Res = void, _Class = Class, _ArgTypes = int]
/usr/include/c++/4.3/tr1_impl/functional:556: note: _Res std::tr1::_Mem_fn<_Res (_Class::*)(_ArgTypes ...)>::operator()(_Class*, _ArgTypes ...) const [with _Res = void, _Class = Class, _ArgTypes = int]
Still, the I have the same problem when Class::member is overloaded by members that takes different arguments...
回答1:
Default functions are bound at call time, but can't be bound into any sort of wrapper implicitly, because of the way they are implemented. When you pass &Class::member
, mem_fn
only sees a void (Class::*)(int)
, and can't see the default argument. Using tr1::bind
, you can bind the default argument explictly: std::tr1::bind(&Class::member, 0)
or you can use it as you would mem_fn
, but you can't do both in one object. You would have to write your own wrapper class for that.
As for overloads, you will have to explicitly specify the template arguments for mem_fn
so the right function pointer is picked as in mem_fn<void(int)>(&Class::member)
.
回答2:
The reason is that any default arguments do not change the function type of a function.
mem_fn
has no way to know the function only requires 1 argument, or that the functions' second argument is optional, since all the knowledge it gets is given to it by the type of &Class::member
(which stays void(Class::*)(int)
) . It therefor requires an integer as the second argument.
If you want to pass the address of a member function overloaded, you have to cast to the right member function pointer type:
static_cast<void(Class::*)()>(&Class::member)
instead of just &Class::member
, so the compiler has a context to figure out which address is to be taken.
Edit: coppro has a nicer solution how to provide context: std::tr1::mem_fn<void()>(&Class::member)
来源:https://stackoverflow.com/questions/294261/tr1mem-fn-and-members-with-default-arguments