Reputation: 2848
If you have this generic function:
template<class type, class ret, class atype1, class atype2, class atype3>
ret call3(type *pClass, ret(type::* funcptr)(atype1, atype2, atype3), atype1 arg, atype2 arg2, atype3 arg3)
{
//do some stuff here
return (pClass->*funcptr)(arg, arg2, arg3);
}
and you do this:
class MyClass
{
public:
void test(int, int, int){};
void test(int, int){};
void test(int, int, const char *){}; //comment this line, and it works fine.
};
...
MyClass *a = new MyClass();
call3(a, &MyClass::test, 1, 2, 3);
g++ will say:
no matching function for call to `call3(MyClass*&, <unknown type>, int, int, int)'
Is there any way to fix this? (My code is probably very bad also since I'm not very good at C++.)
Upvotes: 2
Views: 301
Reputation: 12814
You have to specify which of the three test you need. This can be accomplished with a cast:
call3(a, static_cast<void (MyClass::*)(int, int, int)>(&MyClass::test), 1, 2, 3);
It's not really all that clean. It would probably be better to just give the functions different names.
Upvotes: 3
Reputation: 25497
The reason is that the compiler has two overloads to choose from each of which takes three parameters. Note that during argument deduction process, the compiler deduces participating template parameters from function call arguments indepdently looking at the parameter/argument pair.
Argument deduction succeeds only when the template parameters are determined unambiguously looking at each parameter/argument pair. This means, that while looking at your second parameter/argument pair, it does (and cannot) rely on the fact that atype1, atype2 and atype3 each are of type 'int', even if you rearrange the template parameters as
template<class type, class ret, class atype1, class atype2, class atype3>
ret call3(type *pClass, atype1 arg, atype2 arg2, atype3 arg3, ret(type::* funcptr)(atype1, atype2, atype3))
{
//do some stuff here
return (pClass->*funcptr)(arg, arg2, arg3);
}
Here's the quote from the Standard that supports this:
The non-deduced contexts are:
— The nested-name-specifier of a type that was specified using a qualified-id.
— A non-type template argument or an array bound in which a subexpression references a template parameter.
— A template parameter used in the parameter type of a function parameter that has a default argument that is being used in the call for which argument deduction is being done.
— A function parameter for which argument deduction cannot be done because the associated function argument is a function, or a set of overloaded functions (13.4), and one or more of the following apply:
— more than one function matches the function parameter type (resulting in an ambiguous deduction),or
— no function matches the function parameter type, or
— the set of functions supplied as an argument contains one or more function templates.
Now for the solution,
I think the only solution is that you will have to explicitly specify the template parameters rather than relying on template argument deduction. A little rearrangement of the template parameters will help
template<class atype1, class atype2, class atype3, class type, class ret>
ret call3(type *pClass, ret(type::* funcptr)(atype1, atype2, atype3), atype1 arg, atype2 arg2, atype3 arg3)
{
//do some stuff here
return (pClass->*funcptr)(arg, arg2, arg3);
}
int main(){
MyClass *a = new MyClass();
call3<int, int, int>(a, &MyClass::test, 1, 2, 3);
}
Upvotes: 2
Reputation: 73490
You can explicitly specify which template to use.
call3<MyClass, void, int, int, int>( a, &MyClass::test, 1, 2, 3 );
If you rearange the order of your template parameters, you can get the MyClass and void deduced from the argument, so the call when needing an overload will look like this:
call3<int,int,int>( a, &MyClass::test, 1, 2, 3 )
Note that when you dont actually need the explicit overload resolution it can still be
call3( a, &MyClass::otherfunction, 1,2,3 );
Upvotes: 3
Reputation: 2256
I think the problem here is that compiler is not able to resolve which test
function you are referring to.
If suppose you have following tho methods
void test(int, int, int);
void test(int, int, const char *);
now if you call test
like this
test(1, 2, 3);
3
can be implicitly converted to const char *
. So compiler wont be able to resolve between the two overloads of function test
, and hence the compilation error.
The solution given by JoshD should solve your problem
Upvotes: 0
Reputation: 1274
The compiler cannot deduce the return parameter type. You'll have to specify template parameters of call3
explicitly.
Upvotes: 0