564 lines
31 KiB
Markdown
564 lines
31 KiB
Markdown
[dcl.fct]
|
||
|
||
# 9 Declarations [[dcl]](./#dcl)
|
||
|
||
## 9.3 Declarators [[dcl.decl]](dcl.decl#dcl.fct)
|
||
|
||
### 9.3.4 Meaning of declarators [[dcl.meaning]](dcl.meaning#dcl.fct)
|
||
|
||
#### 9.3.4.6 Functions [dcl.fct]
|
||
|
||
[1](#1)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/declarations.tex#L3671)
|
||
|
||
In a declarationTD whereT may be empty andD has the form
|
||
|
||
D1 ( [*parameter-declaration-clause*](#nt:parameter-declaration-clause "9.3.4.6 Functions [dcl.fct]") ) [*cv-qualifier-seq*](dcl.decl.general#nt:cv-qualifier-seq "9.3.1 General [dcl.decl.general]")opt
|
||
[*ref-qualifier*](dcl.decl.general#nt:ref-qualifier "9.3.1 General [dcl.decl.general]")opt [*noexcept-specifier*](except.spec#nt:noexcept-specifier "14.5 Exception specifications [except.spec]")opt [*attribute-specifier-seq*](dcl.attr.grammar#nt:attribute-specifier-seq "9.13.1 Attribute syntax and semantics [dcl.attr.grammar]")opt [*trailing-return-type*](dcl.decl.general#nt:trailing-return-type "9.3.1 General [dcl.decl.general]")opt
|
||
|
||
a *derived-declarator-type-list* is determined as follows:
|
||
|
||
- [(1.1)](#1.1)
|
||
|
||
If the [*unqualified-id*](expr.prim.id.unqual#nt:unqualified-id "7.5.5.2 Unqualified names [expr.prim.id.unqual]") of the [*declarator-id*](dcl.decl.general#nt:declarator-id "9.3.1 General [dcl.decl.general]") is a [*conversion-function-id*](class.conv.fct#nt:conversion-function-id "11.4.8.3 Conversion functions [class.conv.fct]"),
|
||
the *derived-declarator-type-list* is empty[.](#1.1.sentence-1)
|
||
|
||
- [(1.2)](#1.2)
|
||
|
||
Otherwise, the *derived-declarator-type-list* is as appears in
|
||
the type â*derived-declarator-type-list* Tâ
|
||
of the contained[*declarator-id*](dcl.decl.general#nt:declarator-id "9.3.1 General [dcl.decl.general]") in the declarationTD1[.](#1.2.sentence-1)
|
||
|
||
The declared return type U of the function type
|
||
is determined as follows:
|
||
|
||
- [(1.3)](#1.3)
|
||
|
||
If the [*trailing-return-type*](dcl.decl.general#nt:trailing-return-type "9.3.1 General [dcl.decl.general]") is present,T shall be the single [*type-specifier*](dcl.type.general#nt:type-specifier "9.2.9.1 General [dcl.type.general]") auto, andU is the type specified by the [*trailing-return-type*](dcl.decl.general#nt:trailing-return-type "9.3.1 General [dcl.decl.general]")[.](#1.3.sentence-1)
|
||
|
||
- [(1.4)](#1.4)
|
||
|
||
Otherwise, if the declaration declares a conversion function,
|
||
see [[class.conv.fct]](class.conv.fct "11.4.8.3 Conversion functions")[.](#1.4.sentence-1)
|
||
|
||
- [(1.5)](#1.5)
|
||
|
||
Otherwise, U is T[.](#1.5.sentence-1)
|
||
|
||
The type of the[*declarator-id*](dcl.decl.general#nt:declarator-id "9.3.1 General [dcl.decl.general]") inD is
|
||
â*derived-declarator-type-list*noexceptopt function of parameter-type-list[*cv-qualifier-seq*](dcl.decl.general#nt:cv-qualifier-seq "9.3.1 General [dcl.decl.general]")opt [*ref-qualifier*](dcl.decl.general#nt:ref-qualifier "9.3.1 General [dcl.decl.general]")opt returning Uâ, where
|
||
|
||
- [(1.6)](#1.6)
|
||
|
||
the parameter-type-list is derived from
|
||
the [*parameter-declaration-clause*](#nt:parameter-declaration-clause "9.3.4.6 Functions [dcl.fct]") as described below and
|
||
|
||
- [(1.7)](#1.7)
|
||
|
||
the optional noexcept is present if and only if
|
||
the exception specification ([[except.spec]](except.spec "14.5 Exception specifications")) is non-throwing[.](#1.sentence-3)
|
||
|
||
Such a type is a [*function type*](#def:type,function "9.3.4.6 Functions [dcl.fct]")[.](#1.sentence-4)[75](#footnote-75 "As indicated by syntax, cv-qualifiers are a significant component in function return types.")
|
||
|
||
The optional [*attribute-specifier-seq*](dcl.attr.grammar#nt:attribute-specifier-seq "9.13.1 Attribute syntax and semantics [dcl.attr.grammar]") appertains to the function type[.](#1.sentence-5)
|
||
|
||
[2](#2)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/declarations.tex#L3740)
|
||
|
||
[parameter-declaration-clause:](#nt:parameter-declaration-clause "9.3.4.6 Functions [dcl.fct]")
|
||
...
|
||
[*parameter-declaration-list*](#nt:parameter-declaration-list "9.3.4.6 Functions [dcl.fct]")opt
|
||
[*parameter-declaration-list*](#nt:parameter-declaration-list "9.3.4.6 Functions [dcl.fct]") , ...
|
||
[*parameter-declaration-list*](#nt:parameter-declaration-list "9.3.4.6 Functions [dcl.fct]") ...
|
||
|
||
[parameter-declaration-list:](#nt:parameter-declaration-list "9.3.4.6 Functions [dcl.fct]")
|
||
[*parameter-declaration*](#nt:parameter-declaration "9.3.4.6 Functions [dcl.fct]")
|
||
[*parameter-declaration-list*](#nt:parameter-declaration-list "9.3.4.6 Functions [dcl.fct]") , [*parameter-declaration*](#nt:parameter-declaration "9.3.4.6 Functions [dcl.fct]")
|
||
|
||
[parameter-declaration:](#nt:parameter-declaration "9.3.4.6 Functions [dcl.fct]")
|
||
[*attribute-specifier-seq*](dcl.attr.grammar#nt:attribute-specifier-seq "9.13.1 Attribute syntax and semantics [dcl.attr.grammar]")opt thisopt [*decl-specifier-seq*](dcl.spec.general#nt:decl-specifier-seq "9.2.1 General [dcl.spec.general]") [*declarator*](dcl.decl.general#nt:declarator "9.3.1 General [dcl.decl.general]")
|
||
[*attribute-specifier-seq*](dcl.attr.grammar#nt:attribute-specifier-seq "9.13.1 Attribute syntax and semantics [dcl.attr.grammar]")opt [*decl-specifier-seq*](dcl.spec.general#nt:decl-specifier-seq "9.2.1 General [dcl.spec.general]") [*declarator*](dcl.decl.general#nt:declarator "9.3.1 General [dcl.decl.general]") = [*initializer-clause*](dcl.init.general#nt:initializer-clause "9.5.1 General [dcl.init.general]")
|
||
[*attribute-specifier-seq*](dcl.attr.grammar#nt:attribute-specifier-seq "9.13.1 Attribute syntax and semantics [dcl.attr.grammar]")opt thisopt [*decl-specifier-seq*](dcl.spec.general#nt:decl-specifier-seq "9.2.1 General [dcl.spec.general]") [*abstract-declarator*](dcl.name#nt:abstract-declarator "9.3.2 Type names [dcl.name]")opt
|
||
[*attribute-specifier-seq*](dcl.attr.grammar#nt:attribute-specifier-seq "9.13.1 Attribute syntax and semantics [dcl.attr.grammar]")opt [*decl-specifier-seq*](dcl.spec.general#nt:decl-specifier-seq "9.2.1 General [dcl.spec.general]") [*abstract-declarator*](dcl.name#nt:abstract-declarator "9.3.2 Type names [dcl.name]")opt = [*initializer-clause*](dcl.init.general#nt:initializer-clause "9.5.1 General [dcl.init.general]")
|
||
|
||
The optional [*attribute-specifier-seq*](dcl.attr.grammar#nt:attribute-specifier-seq "9.13.1 Attribute syntax and semantics [dcl.attr.grammar]") in a [*parameter-declaration*](#nt:parameter-declaration "9.3.4.6 Functions [dcl.fct]") appertains to the parameter[.](#2.sentence-1)
|
||
|
||
[3](#3)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/declarations.tex#L3767)
|
||
|
||
The[*parameter-declaration-clause*](#nt:parameter-declaration-clause "9.3.4.6 Functions [dcl.fct]") determines the arguments that can be specified, and their processing, when the function is called[.](#3.sentence-1)
|
||
|
||
[*Note [1](#note-1)*:
|
||
|
||
The[*parameter-declaration-clause*](#nt:parameter-declaration-clause "9.3.4.6 Functions [dcl.fct]") is used to convert the arguments specified on the function call;
|
||
see [[expr.call]](expr.call "7.6.1.3 Function call")[.](#3.sentence-2)
|
||
|
||
â *end note*]
|
||
|
||
If the[*parameter-declaration-clause*](#nt:parameter-declaration-clause "9.3.4.6 Functions [dcl.fct]") is empty, the function takes no arguments[.](#3.sentence-3)
|
||
|
||
A parameter list consisting of a single unnamed non-object parameter of
|
||
non-dependent type void is equivalent to an empty parameter
|
||
list[.](#3.sentence-4)
|
||
|
||
Except for this special case, a parameter shall not have type cv void[.](#3.sentence-5)
|
||
|
||
A parameter with volatile-qualified type is deprecated;
|
||
see [[depr.volatile.type]](depr.volatile.type "D.4 Deprecated volatile types")[.](#3.sentence-6)
|
||
|
||
If the[*parameter-declaration-clause*](#nt:parameter-declaration-clause "9.3.4.6 Functions [dcl.fct]")terminates with an ellipsis or a function parameter
|
||
pack ([[temp.variadic]](temp.variadic "13.7.4 Variadic templates")), the number of arguments shall be equal
|
||
to or greater than the number of parameters that do not have a default
|
||
argument and are not function parameter packs[.](#3.sentence-7)
|
||
|
||
Where syntactically correct and where â...â is not
|
||
part of an [*abstract-declarator*](dcl.name#nt:abstract-declarator "9.3.2 Type names [dcl.name]"),
|
||
â...â
|
||
is synonymous with
|
||
â, ...â[.](#3.sentence-8)
|
||
|
||
A [*parameter-declaration-clause*](#nt:parameter-declaration-clause "9.3.4.6 Functions [dcl.fct]") of the form[*parameter-declaration-list*](#nt:parameter-declaration-list "9.3.4.6 Functions [dcl.fct]") ... is deprecated ([[depr.ellipsis.comma]](depr.ellipsis.comma "D.5 Non-comma-separated ellipsis parameters"))[.](#3.sentence-9)
|
||
|
||
[*Example [1](#example-1)*:
|
||
|
||
The declarationint printf(const char*, ...); declares a function that can be called with varying numbers and types of arguments[.](#3.sentence-10)
|
||
|
||
printf("hello world");
|
||
printf("a=%d b=%d", a, b);
|
||
|
||
However, the first argument must be of a type
|
||
that can be converted to aconstchar*[.](#3.sentence-11)
|
||
|
||
â *end example*]
|
||
|
||
[*Note [2](#note-2)*:
|
||
|
||
The standard header [<cstdarg>](cstdarg.syn#header:%3ccstdarg%3e "17.14.2 Header <cstdarg> synopsis [cstdarg.syn]") contains a mechanism for accessing arguments passed using the ellipsis
|
||
(see [[expr.call]](expr.call "7.6.1.3 Function call") and [[support.runtime]](support.runtime "17.14 Other runtime support"))[.](#3.sentence-12)
|
||
|
||
â *end note*]
|
||
|
||
[4](#4)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/declarations.tex#L3833)
|
||
|
||
The type of a function is determined using the following rules[.](#4.sentence-1)
|
||
|
||
The type of each parameter (including function parameter packs) is
|
||
determined from its own [*parameter-declaration*](#nt:parameter-declaration "9.3.4.6 Functions [dcl.fct]") ([[dcl.decl]](dcl.decl "9.3 Declarators"))[.](#4.sentence-2)
|
||
|
||
After determining the type of each parameter, any parameterof type âarray of Tâ orof function type T is adjusted to be âpointer to Tâ[.](#4.sentence-3)
|
||
|
||
After producing the list of parameter types,
|
||
any top-level[*cv-qualifier*](dcl.decl.general#nt:cv-qualifier "9.3.1 General [dcl.decl.general]")*s* modifying a parameter type are deleted
|
||
when forming the function type[.](#4.sentence-4)
|
||
|
||
The resulting list of transformed parameter types
|
||
and the presence or absence of the ellipsis or a function parameter pack
|
||
is the function's[*parameter-type-list*](#def:parameter-type-list "9.3.4.6 Functions [dcl.fct]")[.](#4.sentence-5)
|
||
|
||
[*Note [3](#note-3)*:
|
||
|
||
This transformation does not affect the types of the parameters[.](#4.sentence-6)
|
||
|
||
For example, int(*)(const int p, decltype(p)*) andint(*)(int, const int*) are identical types[.](#4.sentence-7)
|
||
|
||
â *end note*]
|
||
|
||
[*Example [2](#example-2)*: void f(char*); // #1void f(char[]) {} // defines #1void f(const char*) {} // OK, another overloadvoid f(char *const) {} // error: redefines #1void g(char(*)[2]); // #2void g(char[3][2]) {} // defines #2void g(char[3][3]) {} // OK, another overloadvoid h(int x(const int)); // #3void h(int (*)(int)) {} // defines #3 â *end example*]
|
||
|
||
[5](#5)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/declarations.tex#L3874)
|
||
|
||
An [*explicit-object-parameter-declaration*](#def:explicit-object-parameter-declaration "9.3.4.6 Functions [dcl.fct]") is
|
||
a [*parameter-declaration*](#nt:parameter-declaration "9.3.4.6 Functions [dcl.fct]") with a this specifier[.](#5.sentence-1)
|
||
|
||
An explicit-object-parameter-declaration shall appear only as
|
||
the first [*parameter-declaration*](#nt:parameter-declaration "9.3.4.6 Functions [dcl.fct]") of
|
||
a [*parameter-declaration-list*](#nt:parameter-declaration-list "9.3.4.6 Functions [dcl.fct]") of one of:
|
||
|
||
- [(5.1)](#5.1)
|
||
|
||
a declaration of
|
||
a member function or member function template ([[class.mem]](class.mem "11.4 Class members")), or
|
||
|
||
- [(5.2)](#5.2)
|
||
|
||
an explicit instantiation ([[temp.explicit]](temp.explicit "13.9.3 Explicit instantiation")) or
|
||
explicit specialization ([[temp.expl.spec]](temp.expl.spec "13.9.4 Explicit specialization")) of
|
||
a templated member function, or
|
||
|
||
- [(5.3)](#5.3)
|
||
|
||
a [*lambda-declarator*](expr.prim.lambda.general#nt:lambda-declarator "7.5.6.1 General [expr.prim.lambda.general]") ([[expr.prim.lambda]](expr.prim.lambda "7.5.6 Lambda expressions"))[.](#5.sentence-2)
|
||
|
||
A [*member-declarator*](class.mem.general#nt:member-declarator "11.4.1 General [class.mem.general]") with an explicit-object-parameter-declaration
|
||
shall not include
|
||
a [*ref-qualifier*](dcl.decl.general#nt:ref-qualifier "9.3.1 General [dcl.decl.general]") or a [*cv-qualifier-seq*](dcl.decl.general#nt:cv-qualifier-seq "9.3.1 General [dcl.decl.general]") and
|
||
shall not be declared static or virtual[.](#5.sentence-3)
|
||
|
||
[*Example [3](#example-3)*: struct C {void f(this C& self); template <typename Self> void g(this Self&& self, int); void h(this C) const; // error: const not allowed here};
|
||
|
||
void test(C c) { c.f(); // OK, calls C::f c.g(42); // OK, calls C::g<C&> std::move(c).g(42); // OK, calls C::g<C>} â *end example*]
|
||
|
||
[6](#6)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/declarations.tex#L3912)
|
||
|
||
A function parameter declared with an explicit-object-parameter-declaration
|
||
is an [*explicit object parameter*](#def:parameter,explicit_object "9.3.4.6 Functions [dcl.fct]")[.](#6.sentence-1)
|
||
|
||
An explicit object parameter shall not be
|
||
a function parameter pack ([[temp.variadic]](temp.variadic "13.7.4 Variadic templates"))[.](#6.sentence-2)
|
||
|
||
An [*explicit object member function*](#def:member_function,explicit_object "9.3.4.6 Functions [dcl.fct]") is a non-static member function
|
||
with an explicit object parameter[.](#6.sentence-3)
|
||
|
||
An [*implicit object member function*](#def:member_function,implicit_object "9.3.4.6 Functions [dcl.fct]") is a non-static member function
|
||
without an explicit object parameter[.](#6.sentence-4)
|
||
|
||
[7](#7)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/declarations.tex#L3922)
|
||
|
||
The [*object parameter*](#def:parameter,object "9.3.4.6 Functions [dcl.fct]") of a non-static member function is either
|
||
the explicit object parameter or
|
||
the implicit object parameter ([[over.match.funcs]](over.match.funcs "12.2.2 Candidate functions and argument lists"))[.](#7.sentence-1)
|
||
|
||
[8](#8)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/declarations.tex#L3927)
|
||
|
||
A [*non-object parameter*](#def:parameter,non-object "9.3.4.6 Functions [dcl.fct]") is a function parameter
|
||
that is not the explicit object parameter[.](#8.sentence-1)
|
||
|
||
The [*non-object-parameter-type-list*](#def:non-object-parameter-type-list "9.3.4.6 Functions [dcl.fct]") of a member function is
|
||
the parameter-type-list of that function with the explicit object parameter,
|
||
if any, omitted[.](#8.sentence-2)
|
||
|
||
[*Note [4](#note-4)*:
|
||
|
||
The non-object-parameter-type-list consists of
|
||
the adjusted types of all the non-object parameters[.](#8.sentence-3)
|
||
|
||
â *end note*]
|
||
|
||
[9](#9)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/declarations.tex#L3938)
|
||
|
||
A function type with a [*cv-qualifier-seq*](dcl.decl.general#nt:cv-qualifier-seq "9.3.1 General [dcl.decl.general]") or a[*ref-qualifier*](dcl.decl.general#nt:ref-qualifier "9.3.1 General [dcl.decl.general]") (including a type denoted by[*typedef-name*](dcl.typedef#nt:typedef-name "9.2.4 The typedef specifier [dcl.typedef]") ([[dcl.typedef]](dcl.typedef "9.2.4 The typedef specifier"), [[temp.param]](temp.param "13.2 Template parameters")))
|
||
shall appear only as:
|
||
|
||
- [(9.1)](#9.1)
|
||
|
||
the function type for a non-static member function,
|
||
|
||
- [(9.2)](#9.2)
|
||
|
||
the function type to which a pointer to member refers,
|
||
|
||
- [(9.3)](#9.3)
|
||
|
||
the top-level function type of a function typedef declaration
|
||
or [*alias-declaration*](dcl.pre#nt:alias-declaration "9.1 Preamble [dcl.pre]"),
|
||
|
||
- [(9.4)](#9.4)
|
||
|
||
the [*type-id*](dcl.name#nt:type-id "9.3.2 Type names [dcl.name]") in the default argument of a[*type-parameter*](temp.param#nt:type-parameter "13.2 Template parameters [temp.param]") ([[temp.param]](temp.param "13.2 Template parameters")),
|
||
|
||
- [(9.5)](#9.5)
|
||
|
||
the [*type-id*](dcl.name#nt:type-id "9.3.2 Type names [dcl.name]") of a [*template-argument*](temp.names#nt:template-argument "13.3 Names of template specializations [temp.names]") for a[*type-parameter*](temp.param#nt:type-parameter "13.2 Template parameters [temp.param]") ([[temp.arg.type]](temp.arg.type "13.4.2 Type template arguments")), or
|
||
|
||
- [(9.6)](#9.6)
|
||
|
||
the operand of a [*reflect-expression*](expr.reflect#nt:reflect-expression "7.6.2.10 The reflection operator [expr.reflect]") ([[expr.reflect]](expr.reflect "7.6.2.10 The reflection operator"))[.](#9.sentence-1)
|
||
|
||
[*Example [4](#example-4)*: typedef int FIC(int) const;
|
||
FIC f; // error: does not declare a member functionstruct S { FIC f; // OK};
|
||
FIC S::*pm = &S::f; // OKconstexpr std::meta::info yeti = ^^void(int) const &; // OK â *end example*]
|
||
|
||
[10](#10)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/declarations.tex#L3971)
|
||
|
||
The effect of a[*cv-qualifier-seq*](dcl.decl.general#nt:cv-qualifier-seq "9.3.1 General [dcl.decl.general]") in a function declarator is not the same as
|
||
adding cv-qualification on top of the function type[.](#10.sentence-1)
|
||
|
||
In the latter case, the cv-qualifiers are ignored[.](#10.sentence-2)
|
||
|
||
[*Note [5](#note-5)*:
|
||
|
||
A function type that has a [*cv-qualifier-seq*](dcl.decl.general#nt:cv-qualifier-seq "9.3.1 General [dcl.decl.general]") is not a
|
||
cv-qualified type; there are no cv-qualified function types[.](#10.sentence-3)
|
||
|
||
â *end note*]
|
||
|
||
[*Example [5](#example-5)*: typedef void F();struct S {const F f; // OK, equivalent to: void f();}; â *end example*]
|
||
|
||
[11](#11)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/declarations.tex#L3990)
|
||
|
||
The return type, the parameter-type-list, the [*ref-qualifier*](dcl.decl.general#nt:ref-qualifier "9.3.1 General [dcl.decl.general]"),
|
||
the [*cv-qualifier-seq*](dcl.decl.general#nt:cv-qualifier-seq "9.3.1 General [dcl.decl.general]"), and
|
||
the exception specification,
|
||
but not the default arguments ([[dcl.fct.default]](dcl.fct.default "9.3.4.7 Default arguments"))
|
||
or the trailing [*requires-clause*](temp.pre#nt:requires-clause "13.1 Preamble [temp.pre]") ([[dcl.decl]](dcl.decl "9.3 Declarators")),
|
||
are part of the function type[.](#11.sentence-1)
|
||
|
||
[*Note [6](#note-6)*:
|
||
|
||
Function types are checked during the assignments and initializations of
|
||
pointers to functions, references to functions, and pointers to member functions[.](#11.sentence-2)
|
||
|
||
â *end note*]
|
||
|
||
[12](#12)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/declarations.tex#L4002)
|
||
|
||
[*Example [6](#example-6)*:
|
||
|
||
The declarationint fseek(FILE*, long, int); declares a function taking three arguments of the specified types,
|
||
and returningint ([[dcl.type]](dcl.type "9.2.9 Type specifiers"))[.](#12.sentence-1)
|
||
|
||
â *end example*]
|
||
|
||
[13](#13)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/declarations.tex#L4013)
|
||
|
||
[*Note [7](#note-7)*:
|
||
|
||
A single name can be used for several different functions in a single scope;
|
||
this is function overloading ([[over]](over "12 Overloading"))[.](#13.sentence-1)
|
||
|
||
â *end note*]
|
||
|
||
[14](#14)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/declarations.tex#L4020)
|
||
|
||
The return type shall be a non-array object type, a reference type, or cv void[.](#14.sentence-1)
|
||
|
||
[*Note [8](#note-8)*:
|
||
|
||
An array of placeholder type is considered an array type[.](#14.sentence-2)
|
||
|
||
â *end note*]
|
||
|
||
[15](#15)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/declarations.tex#L4028)
|
||
|
||
A volatile-qualified return type is deprecated;
|
||
see [[depr.volatile.type]](depr.volatile.type "D.4 Deprecated volatile types")[.](#15.sentence-1)
|
||
|
||
[16](#16)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/declarations.tex#L4032)
|
||
|
||
Types shall not be defined in return or parameter types[.](#16.sentence-1)
|
||
|
||
[17](#17)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/declarations.tex#L4035)
|
||
|
||
A typedef of function type may be used to declare a function but shall not be
|
||
used to define a function ([[dcl.fct.def]](dcl.fct.def "9.6 Function definitions"))[.](#17.sentence-1)
|
||
|
||
[*Example [7](#example-7)*: typedef void F();
|
||
F fv; // OK, equivalent to void fv(); F fv { } // errorvoid fv() { } // OK, definition of fv â *end example*]
|
||
|
||
[18](#18)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/declarations.tex#L4048)
|
||
|
||
An identifier can optionally be provided as a parameter name;
|
||
if present in a function definition ([[dcl.fct.def]](dcl.fct.def "9.6 Function definitions")), it names a parameter[.](#18.sentence-1)
|
||
|
||
[*Note [9](#note-9)*:
|
||
|
||
In particular, parameter names are also optional in function definitions
|
||
and names used for a parameter in different declarations and the definition
|
||
of a function need not be the same[.](#18.sentence-2)
|
||
|
||
â *end note*]
|
||
|
||
[19](#19)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/declarations.tex#L4057)
|
||
|
||
[*Example [8](#example-8)*:
|
||
|
||
The declarationint i, *pi,
|
||
f(), *fpi(int), (*pif)(const char*, const char*), (*fpif(int))(int); declares an integeri,
|
||
a pointerpi to an integer,
|
||
a functionf taking no arguments and returning an integer,
|
||
a functionfpi taking an integer argument and returning a pointer to an integer,
|
||
a pointerpif to a function which
|
||
takes two pointers to constant characters and returns an integer,
|
||
a functionfpif taking an integer argument and returning a pointer to a function that takes an integer argument and returns an integer[.](#19.sentence-1)
|
||
|
||
It is especially useful to comparefpi andpif[.](#19.sentence-2)
|
||
|
||
The binding of*fpi(int) is*(fpi(int)),
|
||
so the declaration suggests,
|
||
and the same construction in an expression
|
||
requires, the calling of a functionfpi,
|
||
and then using indirection through the (pointer) result
|
||
to yield an integer[.](#19.sentence-3)
|
||
|
||
In the declarator(*pif)(const char*, const char*),
|
||
the extra parentheses are necessary to indicate that indirection through
|
||
a pointer to a function yields a function, which is then called[.](#19.sentence-4)
|
||
|
||
â *end example*]
|
||
|
||
[*Note [10](#note-10)*:
|
||
|
||
Typedefs and [*trailing-return-type*](dcl.decl.general#nt:trailing-return-type "9.3.1 General [dcl.decl.general]")*s* are sometimes convenient when the return type of a function is complex[.](#19.sentence-5)
|
||
|
||
For example,
|
||
the functionfpif above can be declaredtypedef int IFUNC(int);
|
||
IFUNC* fpif(int); orauto fpif(int)->int(*)(int);
|
||
|
||
A [*trailing-return-type*](dcl.decl.general#nt:trailing-return-type "9.3.1 General [dcl.decl.general]") is most useful for a type that would be more complicated to specify before the [*declarator-id*](dcl.decl.general#nt:declarator-id "9.3.1 General [dcl.decl.general]"):template <class T, class U> auto add(T t, U u) -> decltype(t + u); rather thantemplate <class T, class U> decltype((*(T*)0) + (*(U*)0)) add(T t, U u);
|
||
|
||
â *end note*]
|
||
|
||
[20](#20)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/declarations.tex#L4130)
|
||
|
||
A [*non-template function*](#def:function,non-template "9.3.4.6 Functions [dcl.fct]") is a function that is not a function template
|
||
specialization[.](#20.sentence-1)
|
||
|
||
[*Note [11](#note-11)*:
|
||
|
||
A function template is not a function[.](#20.sentence-2)
|
||
|
||
â *end note*]
|
||
|
||
[21](#21)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/declarations.tex#L4137)
|
||
|
||
An [*abbreviated function template*](#def:template,function,abbreviated "9.3.4.6 Functions [dcl.fct]") is a function declaration that has
|
||
one or more generic parameter type placeholders ([[dcl.spec.auto]](dcl.spec.auto "9.2.9.7 Placeholder type specifiers"))[.](#21.sentence-1)
|
||
|
||
An abbreviated function template is equivalent to
|
||
a function template ([[temp.fct]](temp.fct "13.7.7 Function templates"))
|
||
whose [*template-parameter-list*](temp.pre#nt:template-parameter-list "13.1 Preamble [temp.pre]") includes
|
||
one invented [*type-parameter*](temp.param#nt:type-parameter "13.2 Template parameters [temp.param]") for each generic parameter type placeholder
|
||
of the function declaration, in order of appearance[.](#21.sentence-2)
|
||
|
||
For a [*placeholder-type-specifier*](dcl.spec.auto.general#nt:placeholder-type-specifier "9.2.9.7.1 General [dcl.spec.auto.general]") of the form auto,
|
||
the invented parameter is
|
||
an unconstrained [*type-parameter*](temp.param#nt:type-parameter "13.2 Template parameters [temp.param]")[.](#21.sentence-3)
|
||
|
||
For a [*placeholder-type-specifier*](dcl.spec.auto.general#nt:placeholder-type-specifier "9.2.9.7.1 General [dcl.spec.auto.general]") of the form[*type-constraint*](temp.param#nt:type-constraint "13.2 Template parameters [temp.param]") auto,
|
||
the invented parameter is a [*type-parameter*](temp.param#nt:type-parameter "13.2 Template parameters [temp.param]") with
|
||
that [*type-constraint*](temp.param#nt:type-constraint "13.2 Template parameters [temp.param]")[.](#21.sentence-4)
|
||
|
||
The invented [*type-parameter*](temp.param#nt:type-parameter "13.2 Template parameters [temp.param]") declares
|
||
a template parameter pack
|
||
if the corresponding [*parameter-declaration*](#nt:parameter-declaration "9.3.4.6 Functions [dcl.fct]") declares a function parameter pack[.](#21.sentence-5)
|
||
|
||
If the placeholder contains decltype(auto),
|
||
the program is ill-formed[.](#21.sentence-6)
|
||
|
||
The adjusted function parameters of an abbreviated function template
|
||
are derived from the [*parameter-declaration-clause*](#nt:parameter-declaration-clause "9.3.4.6 Functions [dcl.fct]") by
|
||
replacing each occurrence of a placeholder with
|
||
the name of the corresponding invented [*type-parameter*](temp.param#nt:type-parameter "13.2 Template parameters [temp.param]")[.](#21.sentence-7)
|
||
|
||
[*Example [9](#example-9)*: template<typename T> concept C1 = /* ... */;template<typename T> concept C2 = /* ... */;template<typename... Ts> concept C3 = /* ... */;
|
||
|
||
void g1(const C1 auto*, C2 auto&);void g2(C1 auto&...);void g3(C3 auto...);void g4(C3 auto);
|
||
|
||
The declarations above are functionally equivalent (but not equivalent) to
|
||
their respective declarations below:template<C1 T, C2 U> void g1(const T*, U&);template<C1... Ts> void g2(Ts&...);template<C3... Ts> void g3(Ts...);template<C3 T> void g4(T);
|
||
|
||
Abbreviated function templates can be specialized like all function templates[.](#21.sentence-9)
|
||
|
||
template<> void g1<int>(const int*, const double&); // OK, specialization of g1<int, const double> â *end example*]
|
||
|
||
[22](#22)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/declarations.tex#L4190)
|
||
|
||
An abbreviated function template can have a [*template-head*](temp.pre#nt:template-head "13.1 Preamble [temp.pre]")[.](#22.sentence-1)
|
||
|
||
The invented [*type-parameter*](temp.param#nt:type-parameter "13.2 Template parameters [temp.param]")*s* are
|
||
appended to the [*template-parameter-list*](temp.pre#nt:template-parameter-list "13.1 Preamble [temp.pre]") after
|
||
the explicitly declared [*template-parameter*](temp.param#nt:template-parameter "13.2 Template parameters [temp.param]")*s*[.](#22.sentence-2)
|
||
|
||
[*Example [10](#example-10)*: template<typename> concept C = /* ... */;
|
||
|
||
template <typename T, C U>void g(T x, U y, C auto z);
|
||
|
||
This is functionally equivalent to each of the following two declarations[.](#22.sentence-3)
|
||
|
||
template<typename T, C U, C W>void g(T x, U y, W z);
|
||
|
||
template<typename T, typename U, typename W>requires C<U> && C<W>void g(T x, U y, W z); â *end example*]
|
||
|
||
[23](#23)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/declarations.tex#L4214)
|
||
|
||
A function declaration at block scope
|
||
shall not declare an abbreviated function template[.](#23.sentence-1)
|
||
|
||
[24](#24)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/declarations.tex#L4218)
|
||
|
||
A [*declarator-id*](dcl.decl.general#nt:declarator-id "9.3.1 General [dcl.decl.general]") or [*abstract-declarator*](dcl.name#nt:abstract-declarator "9.3.2 Type names [dcl.name]") containing an ellipsis shall only
|
||
be used in a [*parameter-declaration*](#nt:parameter-declaration "9.3.4.6 Functions [dcl.fct]")[.](#24.sentence-1)
|
||
|
||
When it is part of a[*parameter-declaration-clause*](#nt:parameter-declaration-clause "9.3.4.6 Functions [dcl.fct]"),
|
||
the [*parameter-declaration*](#nt:parameter-declaration "9.3.4.6 Functions [dcl.fct]") declares a
|
||
function parameter pack ([[temp.variadic]](temp.variadic "13.7.4 Variadic templates"))[.](#24.sentence-2)
|
||
|
||
Otherwise, the [*parameter-declaration*](#nt:parameter-declaration "9.3.4.6 Functions [dcl.fct]") is part of a[*template-parameter-list*](temp.pre#nt:template-parameter-list "13.1 Preamble [temp.pre]") and declares a
|
||
template parameter pack; see [[temp.param]](temp.param "13.2 Template parameters")[.](#24.sentence-3)
|
||
|
||
A function parameter pack is a pack expansion ([[temp.variadic]](temp.variadic "13.7.4 Variadic templates"))[.](#24.sentence-4)
|
||
|
||
[*Example [11](#example-11)*: template<typename... T> void f(T (* ...t)(int, int));
|
||
|
||
int add(int, int);float subtract(int, int);
|
||
|
||
void g() { f(add, subtract);} â *end example*]
|
||
|
||
[25](#25)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/declarations.tex#L4243)
|
||
|
||
There is a syntactic ambiguity when an ellipsis occurs at the end
|
||
of a [*parameter-declaration-clause*](#nt:parameter-declaration-clause "9.3.4.6 Functions [dcl.fct]") without a preceding
|
||
comma[.](#25.sentence-1)
|
||
|
||
In this case, the ellipsis is parsed as part of the[*abstract-declarator*](dcl.name#nt:abstract-declarator "9.3.2 Type names [dcl.name]") if the type of the parameter either names
|
||
a template parameter pack that has not been expanded or contains auto;
|
||
otherwise, it is
|
||
parsed as part of the [*parameter-declaration-clause*](#nt:parameter-declaration-clause "9.3.4.6 Functions [dcl.fct]")[.](#25.sentence-2)[76](#footnote-76 "One can explicitly disambiguate the parse either by introducing a comma (so the ellipsis will be parsed as part of the parameter-declaration-clause) or by introducing a name for the parameter (so the ellipsis will be parsed as part of the declarator-id).")
|
||
|
||
[75)](#footnote-75)[75)](#footnoteref-75)
|
||
|
||
As indicated by syntax, cv-qualifiers are a significant component in function return types[.](#footnote-75.sentence-1)
|
||
|
||
[76)](#footnote-76)[76)](#footnoteref-76)
|
||
|
||
One can explicitly disambiguate the parse either by
|
||
introducing a comma (so the ellipsis will be parsed as part of the[*parameter-declaration-clause*](#nt:parameter-declaration-clause "9.3.4.6 Functions [dcl.fct]")) or by introducing a name for the
|
||
parameter (so the ellipsis will be parsed as part of the[*declarator-id*](dcl.decl.general#nt:declarator-id "9.3.1 General [dcl.decl.general]"))[.](#footnote-76.sentence-1)
|