Шаблон C ++: не может соответствовать последнему шаблону в шаблоне класса variadic - PullRequest
0 голосов
/ 06 июня 2018

Я изучаю шаблон C ++ 11 variadic и создал структуру шаблона для вычисления максимального числа заданного списка и попробовал:

#include <iostream>
#include <type_traits>

template <int a, int b, int... cs>
struct max: std::integral_constant<int, (a>b? max<a, cs...>::value: max<b, cs...>::value)> {};
template <int a, int b>
struct max<a, b>: std::integral_constant<int, (a>b? max<a>::value: max<b>::value)> {};
template <int a>
struct max<a>: std::integral_constant<int, a> {};

int main() {
  std::cout << max<2,1,5,7>::value << std::endl;
  return 0;
}

, но g ++ жалуется:

test.cc:7:58: error: wrong number of template arguments (1, should be at least 2)
 struct max<a, b>: std::integral_constant<int, (a>b? max<a>::value : max<b>::value)> {};

test.cc:9:13: error: wrong number of template arguments (1, should be at least 2)
 struct max<a>: std::integral_constant<int, a> {};

Я могу запустить его, добавив простое объявление впереди:

template <int...>
struct max;

и изменив первый шаблон выше на:

template <int a, int b, int... cs>
struct max<a, b, cs...>: ...

Я ссылался на cppreference: https://en.cppreference.com/w/cpp/language/partial_specialization#Partial_ordering но я не могу найти никакого полезного объяснения для моего случая.

Проблема может быть связана с последним шаблоном (max<a>) только с одним параметром шаблона, который не является специализированной версией основного.

Итак, мой вопрос:

Почему max<a> не может быть сопоставлено?Есть ли какие-либо правила или стандарты, касающиеся этого?

================================================================

хорошо, я нашел стандарты C ++ (Документ № N4659)это говорит:

[Примечание: Частичные специализации шаблонов классов находятся путем поиска шаблона основного класса и , а затем учитывает все частичные специализации этого шаблона.Если объявление-использование называет шаблон класса, частичные специализации, введенные после объявления-использования, эффективно видны, потому что основной шаблон видим (17.5.5).- конец примечания]

Так что я думаю, что любой частичный специализированный шаблон, который не специализируется от базового / основного, считается ошибкой, хотя иногда мы можем генерировать некоторые неспециализированные формы выраженияиз нормальных.

Ответы [ 3 ]

0 голосов
/ 06 июня 2018

Не ответ, но почему бы просто ...

template <int a, int... bs>
struct max : std::integral_constant<int,
   (a > max<bs...>::value ? a : max<bs...>::value)> {};

template <int a>
struct max<a> : std::integral_constant<int, a> {};

...?

0 голосов
/ 06 июня 2018

Когда вы определяете шаблон класса как:

template <int a, int b, int... cs> struct max { ... };

Следующее является допустимой специализацией.

template <int a, int b> struct max<a, b> { ... };

Однако следующее не является.

template <int a> struct max<a> { ... };

, поскольку шаблон базового класса требует как минимум двух параметров шаблона.

0 голосов
/ 06 июня 2018

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

Ваш базовый шаблон должен соответствовать любому числу аргументов и иметьнет реализации (так как max<>::value не имеет смысла), и имеет один аргумент с переменным числом аргументов, причем все остальные ваши классы будут специализацией этого.

#include <iostream>
#include <type_traits>

template<int... cs>
struct max;

template <int a, int b, int... cs>
struct max<a, b, cs...>: std::integral_constant<int, (a>b? max<a, cs...>::value: max<b, cs...>::value)> {};
template <int a, int b>
struct max<a, b>: std::integral_constant<int, (a>b? max<a>::value: max<b>::value)> {};
template <int a>
struct max<a>: std::integral_constant<int, a> {};

int main() {
  std::cout << max<2,1,5,7>::value << std::endl;
  return 0;
}
...