Следует учитывать, что существует три типа параметров шаблона:
1) типы
2) нетипы (или значения)
3) template-templates
Первому типу предшествует typename
(или class
)
template <typename T>
void foo (T const & t);
В предыдущем примере T
- это тип, а t
(a аргумент классической функции) - это значение типа T
.
Второй тип параметра шаблона - это значения, которым предшествует тип значения (или auto
, начиная с C ++ 17, для тип не указан)
template <int I>
void bar ()
{ std::cout << I << std::endl; }
В предыдущем примере параметр шаблона I
представляет собой значение типа int
.
Третий тип является наиболее сложным для объяснения.
Знаете ли вы (я полагаю), что std::vector<int>
и std::vector<double>
- это разные типы, но у них есть общий std::vector
, класс шаблона.
Параметр шаблона-шаблона является параметр, который принимает std::vector
, класс шаблона без аргументов.
Параметру шаблона-шаблона предшествует template
ключевое слово, как в следующем примере
template <template <int> class C>
void baz ();
Параметр шаблона-шаблона C
в предыдущем примере - это класс (или структура), для которого требуется единственный параметр шаблона int
(значение).
Итак, если у вас есть класс
template <int I>
class getInt
{ };
, вы можете передать getInt
в качестве параметра шаблона в baz()
baz<getInt>();
Теперь вы должны понимать code:
template <class T, template <class...> class Template>
struct is_specialization : std::false_type {};
структура is_specialization
- это структура шаблона, которая получает в качестве параметров шаблона тип (T
) и шаблон-шаблон Template
, которые принимают классы / структуры, получающие переменную c количество параметров шаблона типа.
Теперь у вас есть специализация is_specialization
:
template <template <class...> class Template, class... Args>
struct is_specialization<Template<Args...>, Template> : std::true_type {};
Эта специализация выбирается, когда первый параметр шаблона (Template<Args...>
) является класс на основе второго (Template
).
Пример: если вы создаете экземпляр
is_specialization<std::vector<int>, std::map>
, то выбирается основная версия (которая наследуется от std::false_type
), поскольку std::vector<int>
isn На основе std::map
.
Но если вы создадите экземпляр
is_specialization<std::vector<int>, std::vector>
специализация (которая наследуется от std::true_type
) выбрана потому, что std::vector<int>
основана на std::vector
.