You have to take in count that there are three types of template parameters:
1) types
2) non-types (or values)
3) template-templates
The first type is preceded by typename
(or class
)
template <typename T>
void foo (T const & t);
In the preceding example, T
is a type and t
(a classical function argument) is a value of type T
.
The second type of template parameter are values and are preceded by the type of the value (or auto
, starting from C++17, for a not specified type)
template <int I>
void bar ()
{ std::cout << I << std::endl; }
In the preceding example the I
template parameter is a value of type int
.
The third type is the most complex to explain.
Do you know (I suppose) that std::vector<int>
and std::vector<double>
are different types, but they have in common std::vector
, a template class.
A template-template parameter is a parameter that accept std::vector
, the template class without arguments.
A template-template parameter is preceded by a template
keyword, as in the following example
template <template <int> class C>
void baz ();
The template-template parameter C
in the preceding example is class (or struct) that require a single int
(value) template parameter.
So if you have a class
template <int I>
class getInt
{ };
you can pass getInt
, as template parameter, to baz()
baz<getInt>();
Now you should be able to understand your code:
template <class T, template <class...> class Template>
struct is_specialization : std::false_type {};
the is_specialization
struct is a template struct that receive, as template parameters, a type (T
) and a template-template Template
that accept classes/structs receiving a variadic number of type template parameters.
Now you have a specialization of is_specialization
:
template <template <class...> class Template, class... Args>
struct is_specialization<Template<Args...>, Template> : std::true_type {};
This specialization is selected when the first template parameter (Template<Args...>
) is a class based on the second (Template
).
An example: if you instantiate
is_specialization<std::vector<int>, std::map>
the main version (that inherit from std::false_type
) is selected because std::vector<int>
isn't based on std::map
.
But if you instantiate
is_specialization<std::vector<int>, std::vector>
the specialization (that inherit from std::true_type
) is selected because std::vector<int>
is based on std::vector
.