Two *template-id*s refer to the same
class, function, or variable if

their

*template-name*s,*operator-function-id*s, or*literal-operator-id*s refer to the same template andtheir corresponding type

*template-argument*s are the same type andtheir corresponding non-type template arguments of integral or enumeration type have identical values and

their corresponding non-type

*template-argument*s of pointer type refer to the same object or function or are both the null pointer value andtheir corresponding non-type

*template-argument*s of pointer-to-member type refer to the same class member or are both the null member pointer value andtheir corresponding non-type

*template-argument*s of reference type refer to the same object or function andtheir corresponding template

*template-argument*s 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 is type-dependent,
decltype(e)
denotes a unique dependent type. Two such *decltype-specifier*s
refer to the same type only if their *expression*s are
equivalent ([temp.over.link]).
[ Note: However, such a type may be aliased,
e.g., by a *typedef-name*. — end note ]