Reputation: 2099
I'd like to specialize a class template on the type template parameter of the template template parameter. Is it possible? If yes, what is the syntax?
#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
Motivation: Let's assume that the template template parameter denotes Collections (e.g. std::vector
, std::deque
). And I want to specialize Z
on std::vector
but I am not interested about the type template parameter of std::vector
, that's OK. Also I want to specialize on all Collection types, which holds an int
.
This question is similar to the following questions, but they are either trying to specialize a function template
or they are trying to specialize not on the template template parameter
or there's no template template parameter in the primary template
Upvotes: 2
Views: 2580
Reputation: 23590
The following code compiles fine:
#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
}
In your code you give Z
a template template parameter, even though that should be done for the specialization only. That's why your code does not compile.
Upvotes: 2
Reputation: 511
This cannot work because in your code:
template<template<class> class C>
struct Z : std::false_type {};
template<>
struct Z<X> : std::true_type {};
Z
expects class template as a parameter.
template <template<class> class C>
struct Z<C<int>> {};
Here you are are not specializing any of it's template arguments and trying to pass C<int>
which is not a class template (C
is a class template and is different than C<int>
which is concrete type).
If your class has template parameter which is a class template and you want your class to behave differently for different types passed for the container you probably should do something like:
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();
//...
};
Upvotes: 1