Специализация частичной шаблоны с несколькими параметрами шаблона
-
11-10-2019 - |
Вопрос
Продолжение Мое путешествие в мир вариационных шаблонов, Я столкнулся с другой проблемой.
Предполагая следующий класс шаблонов:
template < typename T >
struct foo
{
//default implementation
};
Можно частично специализироваться на его экземплярах, подобных вариационным шаблонам, как это:
template < template < typename ... > class T, typename ...Args >
struct foo< T< Args... > >
{
//specialized implementation
};
С этим, foo< int >
будет соответствовать реализации по умолчанию и foo< std::tuple< int, char > >
к специализированной реализации.
Тем не менее, все становится более сложным при использовании нескольких параметров шаблона. Например, если у нас есть следующий класс шаблонов
template < typename T, typename U >
struct bar {};
и мы хотим частично специализироваться, как и для foo
, мы не можем сделать
template < template < typename ... > class T, typename ...TArgs,
template < typename ... > class U, typename ...UArgs >
struct bar< T< TArgs... >, U< UArgs... > > {};
//This would correspond to the specialized version with
//T=std::tuple,
//TArgs=int,char
//U=std::tuple,
//UArgs=float
bar< std::tuple< int, char >, std::tuple< float > > b;
Действительно, если я прав, у нас может быть только один пакет параметров шаблона, и он должен быть расположен в конце списка параметров. Я понимаю, почему это обязательно в декларациях шаблонов, но для определенной специализации по частичным шаблонам (например, пример выше) это не должно быть проблемой.
Можно ли достичь специализации по частичным шаблонам с помощью нескольких пакетов параметров шаблона?
Редактировать: Теперь я чувствую себя глупо ... код, который я дал выше, компилируется идеально (по крайней мере, с GCC 4.5). Ошибка компиляции, которая у меня была, была не из -за нескольких пакетов параметров, а из -за их использования в качестве параметров функций членов. В частичной специализации bar
, Я попытался определить функцию участника, которая берет оба TArgs
а также UArgs
параметры:
template < template < typename ... > class T, typename ...TArgs,
template < typename ... > class U, typename ...UArgs >
struct bar< T< TArgs... >, U< UArgs... > >
{
void method( TArgs... targs, UArgs... uargs ) //compile error here
{
}
};
На объявлении функции участника GCC дает мне ошибку
Пакеты параметров должны быть в конце списка параметров.
Насколько я могу судить, компилятор должен быть в состоянии определить правильную функцию члена для данной экземпляры шаблона, например, bar< std::tuple< int, char >, std::tuple< float > >
должен содержать функцию члена void method( int, char, float )
. Анкет Я делаю что-то неправильно? Или я пытаюсь сделать что -то, что невозможно? Если так, есть ли веская причина, почему это невозможно?
Решение
Вероятно, этот ответ не будет очищать ваш вопрос напрямую, но следующий код, составленный на iDeone (GCC-4.5.1), когда я тестировал.
#include <cstdio>
#include <tuple>
template< class, class > struct S {
S() { puts("primary"); }
};
template<
template< class... > class T, class...TArgs
, template< class... > class U, class...UArgs
>
struct S< T< TArgs... >, U< UArgs... > > {
S() { puts("specialized"); }
};
int main()
{
S< int, int > p; // "primary"
S< std::tuple< int, char >, std::tuple< float > > s; // "specialised"
}
Я не уверен, что этот код строго соответствует, но, насколько я прочитал N3225 14.5.3, я не смог найти утверждение, в котором упоминается, что пакет параметров шаблона должен быть последним параметром шаблона.
Редактировать:
Я перечитал N3225 и нашел следующие утверждения:
8.3.5/4 Если параметром по декларации заканчивается эллипсисом или пакетом параметров функции (14.5.3), количество аргументов должно быть равно или больше, чем количество параметров, которые не имеют аргумента по умолчанию и аргумента не являются функциональными параметрами.
14.8.2.5/10. -end Примечание
Таким образом, как вы упоминали, пакет параметров функций должен быть последним параметром, к сожалению.
Функция неэлемента в шаблоне класса является обычной функцией для этого класса, когда он создан (полностью специализирован). Поэтому я хотел бы, чтобы код в этом вопросе был логически скомпилирован как особый случай.