Как специализировать шаблон класса с параметром шаблона?
Я хотел бы специализировать шаблон класса на параметре шаблона типа параметра шаблона шаблона. Является ли это возможным? Если да, какой синтаксис?
#include <type_traits>
template <typename T>
struct X {};
// primary template
template<template<class> class C>
struct Z : std::false_type {};
// specialization on the template template parameter
template<>
struct Z<X> : std::true_type {}; // OK
// specialization on the type template parameter of the
// template template parameter
template <template<class> class C>
struct Z<C<int>> {}; // ERROR
Мотивация: Давайте предположим, что параметр шаблона шаблона обозначает Коллекции (например, std::vector
, std::deque
). И я хочу специализироваться Z
на std::vector
но меня не интересует параметр шаблона типа std::vector
, это нормально. Также я хочу специализироваться на всех типах Коллекции, которая содержит int
,
Этот вопрос похож на следующие вопросы, но они либо пытаются специализировать шаблон функции
или они пытаются специализироваться не на параметре шаблона шаблона
или нет параметра шаблона шаблона в основном шаблоне
2 ответа
Следующий код компилируется нормально:
#include <type_traits>
template <typename T>
struct X {};
// primary template, no template template parameter
template<typename T>
struct Z : std::false_type {};
// specialization on the template template parameter with arbitrary T
template<typename T>
struct Z<X<T>> : std::true_type {};
// here's where you need the template template parameter
template <template<class> class C>
struct Z<C<int>> : std::true_type {};
int main()
{
static_assert(!Z<Z<double>>::value, "" );
static_assert( Z<Z<int >>::value, "" );
static_assert( Z<X<double>>::value, "" );
// static_assert( Z<X<int >>::value, "" ); // error: ambiguous
// partial specialization
}
В своем коде вы даете Z
параметр шаблона шаблона, хотя это должно быть сделано только для специализации. Вот почему ваш код не компилируется.
Это не может работать, потому что в вашем коде:
template<template<class> class C>
struct Z : std::false_type {};
template<>
struct Z<X> : std::true_type {};
Z
ожидает шаблон класса в качестве параметра.
template <template<class> class C>
struct Z<C<int>> {};
Здесь вы не специализируете ни один из аргументов шаблона и не пытаетесь передать C<int>
который не является шаблоном класса (C
является шаблоном класса и отличается от C<int>
который является конкретным типом).
Если в вашем классе есть параметр шаблона, который является шаблоном класса, и вы хотите, чтобы ваш класс вел себя по-разному для разных типов, передаваемых для контейнера, вы, вероятно, должны сделать что-то вроде:
template<template <typename> class Container,typename Element>
struct MyStruct
{
Container<Element> generic_elements;
// ...
};
template<template <typename> class Container>
struct MyStruct<Container,int>
{
Container<int> special_int_container;
void special_int_things();
//...
};