Параметры шаблона шаблона и вариативные шаблоны с gcc 4.4

Я использую gcc 4.4 на сжатии Debian. Рассмотрим следующий код.

#include <map>
#include <string>
using std::map;
using std::string;

// Args lets the user specify additional explicit template arguments
template <typename T,
      template <typename T, typename... Args> class C,
      typename... Args>
C<T, Args...> foo()
{
  C<T, Args...> x;
  return x;
}

int main(void)
{
  map<string, int> a = foo<string, map, int>();
}

Итак, идея здесь в том, что T соответствует string, C соответствует map, а пакет параметров шаблона Args соответствует int. Возможно, у меня неправильный синтаксис, поправьте, пожалуйста. В частности, если нужно, чтобы первый аргумент шаблона в class C соответствовал T, а остальные соответствовали пакету параметров шаблона Args, является ли template <typename T, typename... Args> class C правильным синтаксисом?

Это дает ошибку

In function 'int main()':
post.cc:18: error: no matching function for call to 'foo()'

Это похоже на вопрос Шаблоны шаблонов Variadic и идеальная пересылка. Этот вопрос предполагает, что это ошибка gcc, но, возможно, я ошибаюсь, думая, что эти вопросы об одном и том же.

Пожалуйста, будьте нежны. Мое знание шаблонов с переменным числом аргументов составляет менее 12 часов; Я просто пытался переписать старый код C++, чтобы уменьшить дублирование. Также прошло некоторое время с тех пор, как я делал какие-либо C++. Если есть обходной путь, пожалуйста, дайте мне знать. Спасибо.

РЕДАКТИРОВАТЬ: Обходной путь, предложенный в комментариях шаблонов Variadic и идеальной пересылки У меня сработало Ise Wisteria, что говорит о том, что это та же ошибка. Конечно, сейчас я (а) задаюсь вопросом, насколько хрупок этот обходной путь и (б) почему он работает и что побудило Исэ задуматься об этом. Хотя, думаю, только Исэ может ответить на последний вопрос. :-)


person Faheem Mitha    schedule 15.12.2011    source источник
comment
Код компилируется на g++ 4.7. Должен быть баг.   -  person kennytm    schedule 15.12.2011
comment
@KennyTM: Спасибо. Это означает, что мне не нужно сообщать об этом, верно?   -  person Faheem Mitha    schedule 15.12.2011
comment
Итак, что вы хотите сделать с этим вопросом? Закрыть как дубликат? Может, ответишь на свой вопрос? :) Это нельзя оставлять как есть.   -  person Xeo    schedule 15.12.2011
comment
@Xeo: Итак, по вашему мнению, это определенно дубликат связанного вопроса? Если да, то у меня нет сильных чувств. Было бы нормально, если бы я ответил на него, а затем принял свой ответ? Если только вы или кто-то другой не предпочтете. :-) Если он закрыт, он все еще будет виден людям, выполняющим поиск?   -  person Faheem Mitha    schedule 15.12.2011
comment
Не совсем так, но проблема такая же, как и ответ. Мне все равно, хотя, мог бы также пойти дальше и ответить на свой вопрос. :)   -  person Xeo    schedule 15.12.2011


Ответы (2)


Как обсуждалось в правках, мой вопрос, похоже, затрагивает ту же ошибку, что и связанный вопрос, Variadic шаблоны шаблонов и идеальная переадресация. В частности, обходной путь, приведенный там по ссылке, работает и в моем случае. Модифицированный код, который работает, выглядит следующим образом:

#include <map>
#include <string>
using std::map;
using std::string;

template <typename T,
      template <typename T, typename... Args> class C,
      typename... Args>
struct X
{
  typedef C<T, Args...> type;
};

template <typename T,
      template <typename T, typename... Args> class C,
      typename... Args>
typename X<T, C, Args...>::type foo()
{
  C<T, Args...> x;
  return x;
}

int main(void)
{
  map<string, int> a = foo<string, map, int>();
}
person Faheem Mitha    schedule 15.12.2011

Я не думаю, что вариативные параметры шаблона могут соответствовать невариативным аргументам в g++ 4.4, поэтому вам нужно перегрузить свою функцию foo невариативной версией.

Также имейте в виду, что карта на самом деле имеет более двух параметров шаблона и поэтому также не будет соответствовать новой функции foo.

Это дополнение к вашему примеру должно прояснить это:

#include <map>
#include <string>
using std::map;
using std::string;

// Args lets the user specify additional explicit template arguments
template <typename T,
          template <typename T, typename... Args> class C,
          typename... Args>
C<T, Args...> foo() {
  C<T, Args...> x;
  return x;
}

template<typename T, template<typename, typename> class C, typename Arg>
C<T, Arg> foo() {
  return C<T, Arg>();
}

template<typename T, typename... Args> class A {};

template<typename T, typename Arg> class B {};

int main(void) {
  map<string, int> a = foo<string, map, int>(); // fails.
  A<string, int> x = foo<string, A, int>();
  B<string, int> y = foo<string, B, int>();
}
person masaers    schedule 15.12.2011
comment
Нет, вариативные шаблоны явно могут соответствовать невариативным шаблонам. - person Xeo; 15.12.2011
comment
Ну, это ошибка. Я говорю о том, что говорит стандарт. Я не думаю, что вариативные параметры шаблона могут соответствовать невариативным аргументам, казалось, предполагало, что вы думаете, что это так в целом. - person Xeo; 15.12.2011
comment
@Xeo: достаточно честно. Я отредактирую ответ, чтобы отразить вашу точку зрения. - person masaers; 15.12.2011