the template parameter values determined by
their corresponding non-type template arguments ([temp.arg.nontype])
are template-argument-equivalent (see below), and
they are of union type and either
they both have no active member or
they have the same active member and their active members are template-argument-equivalent, or
template<class E, int size>class buffer {/* ... */};
buffer<char,2*512> x;
buffer<char,1024> y;
declares
x
and
y
to be of the same type, and
template<class T, void(*err_fct)()>class list {/* ... */};
list<int,&error_handler1> x1;
list<int,&error_handler2> x2;
list<int,&error_handler2> x3;
list<char,&error_handler2> x4;
declares
x2
and
x3
to be of the same type.
template<class T>struct X {};
template<class>struct Y {};
template<class T>using Z = Y<T>;
X<Y<int>> y;
X<Z<int>> z;
declares y and z to be of the same type.