233 lines
12 KiB
Markdown
233 lines
12 KiB
Markdown
[temp.over.link]
|
||
|
||
# 13 Templates [[temp]](./#temp)
|
||
|
||
## 13.7 Template declarations [[temp.decls]](temp.decls#temp.over.link)
|
||
|
||
### 13.7.7 Function templates [[temp.fct]](temp.fct#temp.over.link)
|
||
|
||
#### 13.7.7.2 Function template overloading [temp.over.link]
|
||
|
||
[1](#1)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/templates.tex#L4084)
|
||
|
||
It is possible to overload function templates so that two different
|
||
function template specializations have the same type[.](#1.sentence-1)
|
||
|
||
[*Example [1](#example-1)*:
|
||
|
||
// translation unit 1:template<class T>void f(T*);void g(int* p) { f(p); // calls f<int>(int*)}
|
||
|
||
// translation unit 2:template<class T>void f(T);void h(int* p) { f(p); // calls f<int*>(int*)}
|
||
|
||
â *end example*]
|
||
|
||
[2](#2)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/templates.tex#L4112)
|
||
|
||
Such specializations are distinct functions and do not violate the[one-definition rule](basic.def.odr "6.3 One-definition rule [basic.def.odr]")[.](#2.sentence-1)
|
||
|
||
[3](#3)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/templates.tex#L4116)
|
||
|
||
The signature of a function template
|
||
is defined in [[intro.defs]](intro.defs "3 Terms and definitions")[.](#3.sentence-1)
|
||
|
||
The names of the template parameters are significant only for establishing
|
||
the relationship between the template parameters and the rest of the
|
||
signature[.](#3.sentence-2)
|
||
|
||
[*Note [1](#note-1)*:
|
||
|
||
Two distinct function templates can have identical function return types and
|
||
function parameter lists, even if overload resolution alone cannot distinguish
|
||
them[.](#3.sentence-3)
|
||
|
||
template<class T> void f();template<int I> void f(); // OK, overloads the first template// distinguishable with an explicit template argument list â *end note*]
|
||
|
||
[4](#4)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/templates.tex#L4134)
|
||
|
||
When an expression that references a template parameter is used in the
|
||
function parameter list or the return type in the declaration of a
|
||
function template, the expression that references the template
|
||
parameter is part of the signature of the function template[.](#4.sentence-1)
|
||
|
||
This is
|
||
necessary to permit a declaration of a function template in one
|
||
translation unit to be linked with another declaration of the function
|
||
template in another translation unit and, conversely, to ensure that
|
||
function templates that are intended to be distinct are not linked
|
||
with one another[.](#4.sentence-2)
|
||
|
||
[*Example [2](#example-2)*: template <int I, int J> A<I+J> f(A<I>, A<J>); // #1template <int K, int L> A<K+L> f(A<K>, A<L>); // same as #1template <int I, int J> A<I-J> f(A<I>, A<J>); // different from #1 â *end example*]
|
||
|
||
[*Note [2](#note-2)*:
|
||
|
||
Most expressions that use template parameters use constant template
|
||
parameters, but it is possible for an expression to reference a type
|
||
parameter[.](#4.sentence-3)
|
||
|
||
For example, a template type parameter can be used in thesizeof operator[.](#4.sentence-4)
|
||
|
||
â *end note*]
|
||
|
||
[5](#5)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/templates.tex#L4160)
|
||
|
||
Two expressions involving template parameters are considered[*equivalent*](#def:equivalent,expressions "13.7.7.2 Function template overloading [temp.over.link]") if two function definitions containing the expressions would satisfy
|
||
the [one-definition rule](basic.def.odr "6.3 One-definition rule [basic.def.odr]"), except that the tokens used
|
||
to name the template parameters may differ as long as a token used to
|
||
name a template parameter in one expression is replaced by another token
|
||
that names the same template parameter in the other expression[.](#5.sentence-1)
|
||
|
||
Two unevaluated operands that do not involve template parameters
|
||
are considered equivalent
|
||
if two function definitions containing the expressions
|
||
would satisfy the one-definition rule,
|
||
except that the tokens used to name types and declarations may differ
|
||
as long as they name the same entities, and
|
||
the tokens used to form concept-ids ([[temp.names]](temp.names "13.3 Names of template specializations")) may differ
|
||
as long as the two [*template-id*](temp.names#nt:template-id "13.3 Names of template specializations [temp.names]")*s* are the same ([[temp.type]](temp.type "13.6 Type equivalence"))[.](#5.sentence-2)
|
||
|
||
[*Note [3](#note-3)*:
|
||
|
||
For instance, A<42> and A<40+2> name the same type[.](#5.sentence-3)
|
||
|
||
â *end note*]
|
||
|
||
Two [*lambda-expression*](expr.prim.lambda.general#nt:lambda-expression "7.5.6.1 General [expr.prim.lambda.general]")*s* are never considered equivalent[.](#5.sentence-4)
|
||
|
||
[*Note [4](#note-4)*:
|
||
|
||
The intent is to avoid [*lambda-expression*](expr.prim.lambda.general#nt:lambda-expression "7.5.6.1 General [expr.prim.lambda.general]")*s* appearing in the
|
||
signature of a function template with external linkage[.](#5.sentence-5)
|
||
|
||
â *end note*]
|
||
|
||
For determining whether two dependent names ([[temp.dep]](temp.dep "13.8.3 Dependent names")) are equivalent,
|
||
only the name itself is considered, not the result of name lookup[.](#5.sentence-6)
|
||
|
||
[*Note [5](#note-5)*:
|
||
|
||
If such a dependent name is unqualified,
|
||
it is looked up from
|
||
a first declaration of the function template ([[temp.res.general]](temp.res.general "13.8.1 General"))[.](#5.sentence-7)
|
||
|
||
â *end note*]
|
||
|
||
[*Example [3](#example-3)*: template <int I, int J> void f(A<I+J>); // #1template <int K, int L> void f(A<K+L>); // same as #1template <class T> decltype(g(T())) h();int g(int);template <class T> decltype(g(T())) h() // redeclaration of h() uses the earlier lookup…{ return g(T()); } // … although the lookup here does find g(int)int i = h<int>(); // template argument substitution fails; g(int)// not considered at the first declaration of h()// ill-formed, no diagnostic required: the two expressions are functionally equivalent but not equivalenttemplate <int N> void foo(const char (*s)[([]{}, N)]);template <int N> void foo(const char (*s)[([]{}, N)]);
|
||
|
||
// two different declarations because the non-dependent portions are not considered equivalenttemplate <class T> void spam(decltype([]{}) (*s)[sizeof(T)]);template <class T> void spam(decltype([]{}) (*s)[sizeof(T)]); â *end example*]
|
||
|
||
Two potentially-evaluated expressions involving template parameters that are not equivalent are[*functionally equivalent*](#def:functionally_equivalent,expressions "13.7.7.2 Function template overloading [temp.over.link]") if, for any given set of template arguments, the evaluation of the
|
||
expression results in the same value[.](#5.sentence-8)
|
||
|
||
Two unevaluated operands that are not equivalent
|
||
are functionally equivalent if, for any given set of template arguments,
|
||
the expressions perform
|
||
the same operations in the same order with the same entities[.](#5.sentence-9)
|
||
|
||
[*Note [6](#note-6)*:
|
||
|
||
For instance, one could have redundant parentheses[.](#5.sentence-10)
|
||
|
||
â *end note*]
|
||
|
||
[*Example [4](#example-4)*: template<int I> concept C = true;template<typename T> struct A {void f() requires C<42>; // #1void f() requires true; // OK, different functions}; â *end example*]
|
||
|
||
[6](#6)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/templates.tex#L4235)
|
||
|
||
Two [*template-head*](temp.pre#nt:template-head "13.1 Preamble [temp.pre]")*s* are[*equivalent*](#def:equivalent,template-heads "13.7.7.2 Function template overloading [temp.over.link]") if
|
||
their [*template-parameter-list*](temp.pre#nt:template-parameter-list "13.1 Preamble [temp.pre]")*s* have the same length,
|
||
corresponding [*template-parameter*](temp.param#nt:template-parameter "13.2 Template parameters [temp.param]")*s* are equivalent
|
||
and are both declared with [*type-constraint*](temp.param#nt:type-constraint "13.2 Template parameters [temp.param]")*s* that are equivalent
|
||
if either [*template-parameter*](temp.param#nt:template-parameter "13.2 Template parameters [temp.param]") is declared with a [*type-constraint*](temp.param#nt:type-constraint "13.2 Template parameters [temp.param]"),
|
||
and if either [*template-head*](temp.pre#nt:template-head "13.1 Preamble [temp.pre]") has a [*requires-clause*](temp.pre#nt:requires-clause "13.1 Preamble [temp.pre]"),
|
||
they both have[*requires-clause*](temp.pre#nt:requires-clause "13.1 Preamble [temp.pre]")*s* and the corresponding[*constraint-expression*](temp.constr.decl#nt:constraint-expression "13.5.3 Constrained declarations [temp.constr.decl]")*s* are equivalent[.](#6.sentence-1)
|
||
|
||
Two [*template-parameter*](temp.param#nt:template-parameter "13.2 Template parameters [temp.param]")*s* are[*equivalent*](#def:equivalent,template-parameters "13.7.7.2 Function template overloading [temp.over.link]") under the following conditions:
|
||
|
||
- [(6.1)](#6.1)
|
||
|
||
they declare template parameters of the same kind,
|
||
|
||
- [(6.2)](#6.2)
|
||
|
||
if either declares a template parameter pack, they both do,
|
||
|
||
- [(6.3)](#6.3)
|
||
|
||
if they declare constant template parameters,
|
||
they have equivalent types
|
||
ignoring the use of [*type-constraint*](temp.param#nt:type-constraint "13.2 Template parameters [temp.param]")*s* for placeholder types, and
|
||
|
||
- [(6.4)](#6.4)
|
||
|
||
if they declare template template parameters,
|
||
their [*template-head*](temp.pre#nt:template-head "13.1 Preamble [temp.pre]")*s* are equivalent[.](#6.sentence-2)
|
||
|
||
When determining whether types or [*type-constraint*](temp.param#nt:type-constraint "13.2 Template parameters [temp.param]")*s* are equivalent, the rules above are used to compare expressions
|
||
involving template parameters[.](#6.sentence-3)
|
||
|
||
Two [*template-head*](temp.pre#nt:template-head "13.1 Preamble [temp.pre]")*s* are[*functionally equivalent*](#def:functionally_equivalent,template-heads "13.7.7.2 Function template overloading [temp.over.link]") if they accept and are satisfied by ([[temp.constr.constr]](temp.constr.constr "13.5.2 Constraints"))
|
||
the same set of template argument lists[.](#6.sentence-4)
|
||
|
||
[7](#7)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/templates.tex#L4267)
|
||
|
||
If the validity or meaning of the program depends on
|
||
whether two constructs are equivalent, and they are
|
||
functionally equivalent but not equivalent, the program is ill-formed,
|
||
no diagnostic required[.](#7.sentence-1)
|
||
|
||
Furthermore, if two declarations A and B of function templates
|
||
|
||
- [(7.1)](#7.1)
|
||
|
||
introduce the same name,
|
||
|
||
- [(7.2)](#7.2)
|
||
|
||
have corresponding signatures ([[basic.scope.scope]](basic.scope.scope "6.4.1 General")),
|
||
|
||
- [(7.3)](#7.3)
|
||
|
||
would declare the same entity,
|
||
when considering A and B to correspond in that determination ([[basic.link]](basic.link "6.7 Program and linkage")), and
|
||
|
||
- [(7.4)](#7.4)
|
||
|
||
accept and are satisfied by the same set of template argument lists,
|
||
|
||
but do not correspond,
|
||
the program is ill-formed, no diagnostic required[.](#7.sentence-2)
|
||
|
||
[8](#8)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/templates.tex#L4287)
|
||
|
||
[*Note [7](#note-7)*:
|
||
|
||
This rule guarantees that equivalent declarations will be linked with
|
||
one another, while not requiring implementations to use heroic efforts
|
||
to guarantee that functionally equivalent declarations will be treated
|
||
as distinct[.](#8.sentence-1)
|
||
|
||
For example, the last two declarations are functionally
|
||
equivalent and would cause a program to be ill-formed:// guaranteed to be the sametemplate <int I> void f(A<I>, A<I+10>);template <int I> void f(A<I>, A<I+10>);
|
||
|
||
// guaranteed to be differenttemplate <int I> void f(A<I>, A<I+10>);template <int I> void f(A<I>, A<I+11>);
|
||
|
||
// ill-formed, no diagnostic requiredtemplate <int I> void f(A<I>, A<I+10>);template <int I> void f(A<I>, A<I+1+2+3+4>);
|
||
|
||
â *end note*]
|