Частичная специализация шаблона с несколькими пакетами параметров шаблона - PullRequest
15 голосов
/ 16 января 2011

Продолжая моего путешествия в мир вариационных шаблонов , я столкнулся с другой проблемой.

Предполагая следующий класс шаблона:

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 ). Я делаю что-то неправильно? Или я пытаюсь сделать то, что невозможно? Если так, есть ли веская причина, почему это невозможно?

1 Ответ

6 голосов
/ 16 января 2011

Возможно, этот ответ не прояснит ваш вопрос напрямую, но следующий код, скомпилированный на 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 [Примечание: пакет параметров функции может находиться только в конце списка объявлений параметров (8.30,5).-конечная заметка]

Итак, как вы упомянули, пакет параметров функции, к сожалению, должен быть последним параметром.
Функция, не являющаяся членом шаблона, является обычной функцией для этого класса.когда он создан (полностью специализирован).Поэтому я хочу, чтобы код в этом вопросе мог быть скомпилирован логически, как особый случай.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...