Да, явно специализация функции без полной специализации всего внешнего шаблона невозможна (явная специализированная функция - это реальная функция - не может быть никаких «переменных частей» вокруг нее, которые все еще параметризуются шаблоном)
простой способ заключается в использовании шаблона type2type вместе с перегрузкой:
template<typename T> struct t2t { typedef T type; };
void Func(Parm1 arg1, Parm2, arg2) { Call<Parm3>(arg1, arg2, t2t<Parm3>()); }
template< class Type, class V > void Call(Parm1 arg1, Parm2 arg2, t2t<V>) { }
template< class Type > void Call(Parm1 arg1, Parm2 arg2, t2t<void>) { }
Теперь он будет вызывать второй Call
перегрузку, если вы звоните его t2t<void>
, и первый в противном случае, поскольку первый из них меньше особый.
Использование enable_if
можно также:
void Func(Parm1 arg1, Parm2, arg2) { Call<Parm3>(arg1, arg2); }
template< class Type > typename disable_if< is_same<Type, void> >::type
Call(Parm1 arg1, Parm2 arg2) { }
template< class Type > typename enable_if< is_same<Type, void> >::type
Call(Parm1 arg1, Parm2 arg2) { }
Теперь, второй один берется, если Type
является недействительным, и первый один берется, если Type
что-то еще раз. Но с использованием другой техники. Это называется SFINAE
. Альтернативный способ, но снова добавляет один параметр это - продемонстрировать, как SFINAE работает:
void Func(Parm1 arg1, Parm2, arg2) { Call<Parm3>(arg1, arg2); }
template< class Type >
void Call(Parm1 arg1, Parm2 arg2, char(*)[!is_same<Type, void>::value] = 0) { }
template< class Type >
void Call(Parm1 arg1, Parm2 arg2, char(*)[ is_same<Type, void>::value] = 0) { }
SFINAE
происходит, если замещение выходов параметров шаблона недопустимого типа или построить. Ниже мы пытаемся создать указатель на массив размером 0 или 1 соответственно. Массив размера 0 недействителен и вызовет сбой SFINAE. Соответствующая спецификация шаблона не будет считаться кандидатом на вызов, если это функция.
В случае с enable_if
этот товар отличается. Если enable_if
получает что-то, полученное от false_type
, то оно делает его ::type
typedef не существует. is_same
происходит от false_type
в случае, если типы не совпадают. Затем мы попытаемся получить доступ к несуществующему имени, которое является недопустимой конструкцией, и для этого также должен быть сбой SFINAE.
Очень интересная информация на листе, но у меня возникают проблемы с кодом - существуют ли функции Func() и Call() внутри класса? –
да. я удалил заметку сейчас :) Я имел в виду этот комментарий только для t2t, потому что он полезен и для других случаев и может быть определен в каком-то пространстве имен приложений :) –
Я вижу, очень умно! (Пришло время выяснить, что именно происходит там ...) Правильно ли я полагаю, что вы используете t2t на всякий случай, если V либо большой, либо не имеет значения по умолчанию ctor? Кстати, это прояснит ситуацию, если вы можете поместить последние 3 строки фрагмента №1 в определение класса. –