[temp.type]

# 13 Templates [[temp]](./#temp)

## 13.6 Type equivalence [temp.type]

[1](#1)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/templates.tex#L2445)

Two [*template-id*](temp.names#nt:template-id "13.3 Names of template specializations [temp.names]")*s* are the same if

- [(1.1)](#1.1)

their [*template-name*](temp.names#nt:template-name "13.3 Names of template specializations [temp.names]")*s*,[*operator-function-id*](over.oper.general#nt:operator-function-id "12.4.1 General [over.oper.general]")*s*, or[*literal-operator-id*](over.literal#nt:literal-operator-id "12.6 User-defined literals [over.literal]")*s* refer to the same template, and

- [(1.2)](#1.2)

their corresponding type [*template-argument*](temp.names#nt:template-argument "13.3 Names of template specializations [temp.names]")*s* are the same type, and

- [(1.3)](#1.3)

the template parameter values determined by
their corresponding constant template arguments ([[temp.arg.nontype]](temp.arg.nontype "13.4.3 Constant template arguments"))
are template-argument-equivalent (see below), and

- [(1.4)](#1.4)

their corresponding template [*template-argument*](temp.names#nt:template-argument "13.3 Names of template specializations [temp.names]")*s* refer to the same template[.](#1.sentence-1)

Two [*template-id*](temp.names#nt:template-id "13.3 Names of template specializations [temp.names]")*s* that are the same
refer to the same class, function, or variable[.](#1.sentence-2)

[2](#2)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/templates.tex#L2471)

Two values are [*template-argument-equivalent*](#def:template-argument-equivalent "13.6 Type equivalence [temp.type]") if
they are of the same type and

- [(2.1)](#2.1)

they are of integral type and their values are the same, or

- [(2.2)](#2.2)

they are of floating-point type and their values are identical, or

- [(2.3)](#2.3)

they are of type std​::​nullptr_t, or

- [(2.4)](#2.4)

they are of type std​::​meta​::​info and
their values compare equal ([[expr.eq]](expr.eq "7.6.10 Equality operators")), or

- [(2.5)](#2.5)

they are of enumeration type and their values are the same,[112](#footnote-112 "The identity of enumerators is not preserved.") or

- [(2.6)](#2.6)

they are of pointer type and they have the same pointer value, or

- [(2.7)](#2.7)

they are of pointer-to-member type and they refer to the same class member
or are both the null member pointer value, or

- [(2.8)](#2.8)

they are of reference type and they refer to the same object or function, or

- [(2.9)](#2.9)

they are of array type and their corresponding elements are template-argument-equivalent,[113](#footnote-113 "An array as a template-parameter decays to a pointer.") or

- [(2.10)](#2.10)

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

- [(2.11)](#2.11)

they are of a closure type ([[expr.prim.lambda.closure]](expr.prim.lambda.closure "7.5.6.2 Closure types")), or

- [(2.12)](#2.12)

they are of class type and
their corresponding direct subobjects and reference members are template-argument-equivalent[.](#2.sentence-1)

[3](#3)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/templates.tex#L2525)

[*Example [1](#example-1)*:

template<class E, int size> class buffer { /* ... */ };
buffer<char,2*512> x;
buffer<char,1024> y; declaresx andy to be of the same type, andtemplate<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; declaresx2 andx3 to be of the same type[.](#3.sentence-1)

Their type differs from the types ofx1 andx4[.](#3.sentence-2)

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[.](#3.sentence-3)

â *end example*]

[4](#4)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/templates.tex#L2564)

If an expression e is [type-dependent](temp.dep.expr "13.8.3.3 Type-dependent expressions [temp.dep.expr]"),decltype(e) denotes a unique dependent type[.](#4.sentence-1)

Two such [*decltype-specifier*](dcl.type.decltype#nt:decltype-specifier "9.2.9.6 Decltype specifiers [dcl.type.decltype]")*s* refer to the same type only if their [*expression*](expr.comma#nt:expression "7.6.20 Comma operator [expr.comma]")*s* are
equivalent ([[temp.over.link]](temp.over.link "13.7.7.2 Function template overloading"))[.](#4.sentence-2)

[*Note [1](#note-1)*:

However, such a type might be aliased,
e.g., by a [*typedef-name*](dcl.typedef#nt:typedef-name "9.2.4 The typedef specifier [dcl.typedef]")[.](#4.sentence-3)

â *end note*]

[5](#5)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/templates.tex#L2575)

For a type template parameter pack T,T...[[*constant-expression*](expr.const#nt:constant-expression "7.7 Constant expressions [expr.const]")] denotes
a unique dependent type[.](#5.sentence-1)

[6](#6)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/templates.tex#L2580)

If the [*constant-expression*](expr.const#nt:constant-expression "7.7 Constant expressions [expr.const]") of a [*pack-index-specifier*](dcl.type.pack.index#nt:pack-index-specifier "9.2.9.4 Pack indexing specifier [dcl.type.pack.index]") is value-dependent,
two such [*pack-index-specifier*](dcl.type.pack.index#nt:pack-index-specifier "9.2.9.4 Pack indexing specifier [dcl.type.pack.index]")*s* refer to the same type
only if their [*constant-expression*](expr.const#nt:constant-expression "7.7 Constant expressions [expr.const]")*s* are equivalent ([[temp.over.link]](temp.over.link "13.7.7.2 Function template overloading"))[.](#6.sentence-1)

Otherwise, two such [*pack-index-specifier*](dcl.type.pack.index#nt:pack-index-specifier "9.2.9.4 Pack indexing specifier [dcl.type.pack.index]")*s* refer to the same type
only if their indexes have the same value[.](#6.sentence-2)

[112)](#footnote-112)[112)](#footnoteref-112)

The identity of enumerators is not preserved[.](#footnote-112.sentence-1)

[113)](#footnote-113)[113)](#footnoteref-113)

An array as a [*template-parameter*](temp.param#nt:template-parameter "13.2 Template parameters [temp.param]") decays to a pointer[.](#footnote-113.sentence-1)
