Причина в том, что у компилятора есть две перегрузки на выбор, каждая из которых принимает три параметра. Обратите внимание, что в процессе вывода аргументов компилятор выводит участвующие параметры шаблона из аргументов вызова функции, независимо просматривая пару параметр / аргумент.
Вывод аргумента успешен только тогда, когда параметры шаблона определены однозначно с учетом каждой пары параметр / аргумент. Это означает, что, глядя на вашу вторую пару параметр / аргумент, он полагается (и не может) полагаться на тот факт, что atype1, atype2 и atype3 имеют тип int, даже если вы изменили параметры шаблона как
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);
}
Вот цитата из стандарта, которая поддерживает это:
Не выведенные контексты:
- The
nested-name-спецификатор типа, который
был указан с помощью квалифицированного идентификатора.
-
Нетипичный аргумент шаблона или
связанный массив, в котором подвыражение
ссылается на параметр шаблона.
- А
параметр шаблона, используемый в
тип параметра параметра функции
который имеет аргумент по умолчанию, который
используется в вызове, для которого
вывод аргумента делается.
- A
параметр функции, для которого аргумент
удержание не может быть сделано, потому что
аргумент связанной функции является
функция или набор перегруженных
функции (13.4) и один или несколько
применяется следующее:
- более одного
функция соответствует функции
тип параметра (в результате чего
двусмысленный вывод) или
- нет функции
соответствует типу параметра функции,
или
- набор функций поставляется в виде
аргумент содержит один или несколько
шаблоны функций.
Теперь для решения,
Я думаю, что единственным решением является то, что вам придется явно указывать параметры шаблона, а не полагаться на вывод аргумента шаблона. Небольшая перестановка параметров шаблона поможет
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);
}