Two template-ids refer to the same class or function if
their template-names, operator-function-ids, or literal-operator-ids refer to the same template and
their corresponding type template-arguments are the same type and
their corresponding non-type template arguments of integral or enumeration type have identical values and
their corresponding non-type template-arguments of pointer type refer to the same external object or function or are both the null pointer value and
their corresponding non-type template-arguments of pointer-to-member type refer to the same class member or are both the null member pointer value and
their corresponding non-type template-arguments of reference type refer to the same external object or function and
their corresponding template template-arguments refer to the same template.
[ Example:
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. Their type differs from the types of x1 and x4.
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. — end example ]
If an expression e involves a template parameter, decltype(e) denotes a unique dependent type. Two such decltype-specifiers refer to the same type only if their expressions are equivalent ([temp.over.link]). [ Note: however, it may be aliased, e.g., by a typedef-name. — end note ]