#c #templates #generics
Вопрос:
Рассмотрим следующий шаблон
template <typename T, int v> void func(const Tamp;x);
и я хочу специализироваться на нем для какого-нибудь класса A
. Вот моя попытка (со ссылкой на это):
template <int v> void func<A, v>(const Aamp;x);
Однако это незаконно. Мой вопрос в том, почему это незаконно (какое правило это нарушает), и если это противоречит грамматике, есть ли для нас другие способы его специализации A
?
Комментарии:
1. вы можете сделать
template <int v> void func(const Aamp;x);
2. @appleapple Но разве это не создание другого шаблона?
3. в чем разница? можете ли вы показать, как вы хотели бы его использовать?
4. Вы не можете частично специализировать функции . См. раздел Шаблоны : «частичная специализация допускается только для шаблонов классов [и шаблонов переменных (начиная с C 14)]».
5. Кстати, лучше изменить порядок параметров шаблона
T
в соответствии с выводимым:template <int v, typename T> void func(const Tamp;x);
разрешить такие вызовы, какfunc<42>(my_obj);
Ответ №1:
Вы не можете частично специализировать шаблон функции, но вы можете перегрузить его, как показано ниже.
#include <iostream>
class A
{
};
template <typename T, int v> void func(const Tamp;x) //primary template
{
std::cout<<"primary template"<<std::endl;
}
//this is an overload and not a specialization. Also partial specialization cannot be done for function templates
template <int v> void func(const Aamp;x)
{
std::cout<<"overload not specialization"<<std::endl;
}
int main()
{
func<int, 5>(84); //uses primary template
func<5>(A()); //uses the overloaded version
return 0;
}
Ответ №2:
Шаблоны функций не могут быть частично специализированными, поэтому возникает ошибка:
<source>:8:23: error: non-class, non-variable partial specialization 'func<A, v>' is not allowed
8 | template <int v> void func<A, v>(const Aamp;x);
| ^~~~~~~~~~
Вы можете, например, частично специализировать тип с помощью operator()
:
template <typename T, int v>
struct func{
void operator()(const Tamp;x);
};
struct A {};
template <int v>
struct func<A, v>{
void operator()(const Aamp;x);
};
Комментарии:
1. Спасибо вам за этот ответ! Я также подумал о возможности использования функционального объекта, и я попробую это сделать!
Ответ №3:
Для этого можно использовать ограничение (или SFINAE).
#include <iostream>
class A {};
class B {};
template <typename T, int v> void func(const Tamp;)
{
std::cout<<"generic";
}
template <typename T, int v> void func(const Tamp;)
requires std::is_same_v<T,A>
{
std::cout<<"A";
}
int main(){
func<A,1>(A{}); // output A
}
Ответ №4:
Поймите v
, здесь не выводится, что может вызвать нежелательный эффект, оставьте это здесь, так как это может быть полезно для кого-то, кто ответит на этот вопрос.
вы можете сделать это с помощью
template <typename T, int v> void func(const Tamp;x);
template <int v> void func(const Aamp;x);
что касается причины, я думаю, что это главным образом потому, что это не дает никакой дополнительной ценности
template <typename T> void func(const Tamp;x);
template <typename T> void func(const T*x);
void func(const Aamp;);
уже является допустимой функцией «специализация». не совсем специализация в смысле стандартной формулировки
Комментарии:
1. Вы ошибаетесь. Последние 2 версии, которые вы называете специализацией, являются перегрузками.
2. @AanchalSharma Я не называю их специализацией, поэтому я цитирую их и использую курсив
3.
is already a valid function "specialization".
Мне кажется, вы называете их специализацией. Может быть, вы сможете более четко сформулировать, что вы имеете в виду, чтобы не было путаницы.4. @AanchalSharma добавил.