Распаковка пакетов параметров в псевдонимах шаблонов

#c #c 11 #variadic-templates #gcc4.9 #template-aliases

#c #c 11 #переменные-шаблоны #gcc4.9 #шаблон-псевдонимы

Вопрос:

Я столкнулся с проблемой при распаковке шаблонов переменных в псевдоним шаблона.

Следующий код работает с Clang 3.4 и GCC 4.8, но не работает с GCC 4.9:

 template <typename T, typename...>
using front_type = T;

template <typename... Ts>
struct foo
{
  using front = front_type<Ts...>;
};
 

GCC 4.9 жалуется:

 test.cc:7:37: error: pack expansion argument for non-pack parameter 'T' of alias template 'template<class T, class ...> using front_type = T'
       using front = front_type<Ts...>;
                                     ^
test.cc:1:15: note: declared here
     template <typename T, typename...>
               ^
 

Существует ошибка GCC (# 59498), но предполагается ли, что это приведет к сбою? Вот некоторый контекст из выпуска C core language # 1430, «расширение пакета в список параметров шаблона с фиксированным псевдонимом»:

Первоначально расширение пакета не могло расширяться до списка параметров шаблона фиксированной длины, но это было изменено в N2555. Это отлично работает для большинства шаблонов, но вызывает проблемы с шаблонами псевдонимов.

В большинстве случаев шаблон псевдонима прозрачен; когда он используется в шаблоне, мы можем просто подставить в зависимые аргументы шаблона. Но это не сработает, если template-id использует расширение пакета для переменных параметров. Например:

   template<class T, class U, class V>
  struct S {};

  template<class T, class V>
  using A = S<T, int, V>;

  template<class... Ts>
  void foo(A<Ts...>);
 

Нет способа выразить A<Ts...> в терминах S , поэтому нам нужно придерживаться A , пока у нас не будет T s для замены, и поэтому его нужно обрабатывать с помощью манипулирования.

В настоящее время EDG и Clang отклоняют этот тестовый пример, жалуясь на слишком мало аргументов шаблона для A. G сделал то же самое, но я подумал, что это ошибка. Однако в списке ABI Джон Спайсер утверждал, что его следует отклонить.

Комментарии:

1. Можете ли вы выйти front_type за пределы foo — они, похоже, не связаны?

2. Да, хорошая мысль @PiotrNycz. (Однако это не исправляет проблему.)

3. Я проверил этот измененный код с помощью gcc4.8 — похоже, он работает.

4. «работает с Clang 3.4» Однако это отклоняется clang 3.5.0: error: pack expansion used as argument for non-pack parameter of alias template

Ответ №1:

Об этом сообщалось в gcc4.9 bugzilla:

https://gcc.gnu.org/bugzilla/show_bug.cgi?id=59498

Минимальный код для воспроизведения

 template <typename T, typename ...>
using alias = T;

template <typename ...T>
using variadic_alias = alias<T...>;

using Fail = variadic_alias<int>;

int main() { }
 

Из объяснения людей из gcc — не так очевидно, что это настоящая ошибка.
Это все еще обсуждается в gcc bugzilla и в DR 1430 (http://open-std.org/jtc1/sc22/wg21/docs/cwg_active.html#1430 ) — краткое изложение в настоящем вопросе выше.

Комментарии:

1. Сообщается, что это ошибка, но, судя по комментариям, это сделано специально.

2. Да, похоже, что это должно завершиться неудачей? Я отредактировал вопрос с помощью контекста из # 1430

3. @MatthiasVallentin я пропустил ваш комментарий — я удалю дублированный контент из своего ответа.