The code is very simple and concise (YATC
means yet another template class
:)
)
template<typename T1, typename T2> class YATC; /*declaration*/ template<typename T1> class YATC<T1,T1> {}; template<typename T1, typename T2, typename T3> class YATC<T1, YATC<T2, T3>> {}; int main() { YATC<int, YATC<int, double>> yatc; return 0; }
This black magic looks very disturbing for me.
I declared the class as a template class with two template arguments
T1
,T2
;I’ve expected that I can make specializations for
YATC
class based on idea that I can specificate definition of the class on two template arguments only;I’ve found out that actually I can make specialization using infinite template arguments like
typename T1, typename T2, typename T3
but with some interesting restrictions:I cannot use
std::common_type_t<T1, T2>
as second parameter forYATC
specialization. The compiler throws an error thatT2
isn’t used forYATC
‘s specialization;However, I can use them for using specialization with instance of some template class that receives these arguments (as
YATC<T2, T3>
);But! I still cannot instantiate the class with
YATC<int, int, double>
, onlyYATC<int, YATC<int, double>>
;
Why the such declaration is still valid but why I cannot instantiate the class with YATC<int, int, double>
?
Answer
I’ve expected that I can make specializations for
YATC
class based on idea that I can specificate definition of the class on two template arguments only;
And this is correct.
I’ve found out that actually I can make specialization using infinite template arguments like
typename T1, typename T2, typename T3
but with some interesting restrictions:
Yes… but still remain that YACT
has only two template arguments
Take your second specialization
template<typename T1, typename T2, typename T3> class YATC<T1, YATC<T2, T3>> {};
You use three template parameter but YACT
receive only two template arguments:
T1
YACT<T2, T3>
The second one is something complex, and is expressed through YACT
itself and a couple of template parameters of the specializations, but YACT<T2, T2>
remain a single template argument, from the YACT
point of view.
Substantially, declaring
template<typename T1, typename T2> class YATC;
you declare that YACT
receive exactly two types; nothing forbid you to construct your types in a very very complex way
// 1 2 //...vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv..vvvvvvvvvvvvvvvvvvvvvvvvv YACT<std::tuple<YACT<int, long>>, char>, std::vector<std::string>>> foo;
and declare YACT
specializations that use a lot of template parameter (not only types but also values and template-template), to express the couple the YACT
types parameter. But YACT
has to receive exaclty two types parameters. Complex as you will but exactly two.
I still cannot insatiate the class with
YATC<int, int, double>
, onlyYATC<int, YATC<int, double>>
;
Exactly.
Because with
// 1 2 3 // ..VVV..VVV..VVVVVV YATC<int, int, double>
you pass three types to YACT
, but with
// 1 2 // ..VVV..VVVVVVVVVVVVVVVVV YATC<int, YATC<int, double>>
you pass two types to YACT
(YACT<int, double>
is a single type).