Я изучаю шаблон 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;
}
но г ++ жалуется
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). — конец примечания]
Поэтому я думаю, что любой частичный специализированный шаблон, который не специализируется на базовом / основном шаблоне, считается ошибкой, хотя иногда мы можем генерировать некоторые неспециализированные формы выражения из обычных.
Когда вы определяете шаблон класса как:
template <int a, int b, int... cs> struct max { ... };
Следующее является действительной специализацией.
template <int a, int b> struct max<a, b> { ... };
Однако следующего нет.
template <int a> struct max<a> { ... };
поскольку шаблон базового класса требует как минимум двух параметров шаблона.
Не ответ, но почему бы не просто …
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> {};
…?
Причина, по которой вы получаете эту ошибку, состоит в том, что каждый вызов шаблона должен сначала соответствовать базовому шаблону, а специализация только начинается после этого.
Ваш базовый шаблон должен соответствовать любому количеству аргументов и не иметь реализации (поскольку 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;
}