Files
2025-10-25 03:02:53 +03:00

564 lines
31 KiB
Markdown
Raw Permalink Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

[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.6Functions[dcl.fct]") ) [*cv-qualifier-seq*](dcl.decl.general#nt:cv-qualifier-seq "9.3.1General[dcl.decl.general]")opt
[*ref-qualifier*](dcl.decl.general#nt:ref-qualifier "9.3.1General[dcl.decl.general]")opt [*noexcept-specifier*](except.spec#nt:noexcept-specifier "14.5Exception specifications[except.spec]")opt [*attribute-specifier-seq*](dcl.attr.grammar#nt:attribute-specifier-seq "9.13.1Attribute syntax and semantics[dcl.attr.grammar]")opt [*trailing-return-type*](dcl.decl.general#nt:trailing-return-type "9.3.1General[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.2Unqualified names[expr.prim.id.unqual]") of the [*declarator-id*](dcl.decl.general#nt:declarator-id "9.3.1General[dcl.decl.general]") is a [*conversion-function-id*](class.conv.fct#nt:conversion-function-id "11.4.8.3Conversion 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.1General[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.1General[dcl.decl.general]") is present,T shall be the single [*type-specifier*](dcl.type.general#nt:type-specifier "9.2.9.1General[dcl.type.general]") auto, andU is the type specified by the [*trailing-return-type*](dcl.decl.general#nt:trailing-return-type "9.3.1General[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.3Conversion 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.1General[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.1General[dcl.decl.general]")opt [*ref-qualifier*](dcl.decl.general#nt:ref-qualifier "9.3.1General[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.6Functions[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.5Exception specifications")) is non-throwing[.](#1.sentence-3)
Such a type is a [*function type*](#def:type,function "9.3.4.6Functions[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.1Attribute 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.6Functions[dcl.fct]")
...
[*parameter-declaration-list*](#nt:parameter-declaration-list "9.3.4.6Functions[dcl.fct]")opt
[*parameter-declaration-list*](#nt:parameter-declaration-list "9.3.4.6Functions[dcl.fct]") , ...
[*parameter-declaration-list*](#nt:parameter-declaration-list "9.3.4.6Functions[dcl.fct]") ...
[parameter-declaration-list:](#nt:parameter-declaration-list "9.3.4.6Functions[dcl.fct]")
[*parameter-declaration*](#nt:parameter-declaration "9.3.4.6Functions[dcl.fct]")
[*parameter-declaration-list*](#nt:parameter-declaration-list "9.3.4.6Functions[dcl.fct]") , [*parameter-declaration*](#nt:parameter-declaration "9.3.4.6Functions[dcl.fct]")
[parameter-declaration:](#nt:parameter-declaration "9.3.4.6Functions[dcl.fct]")
[*attribute-specifier-seq*](dcl.attr.grammar#nt:attribute-specifier-seq "9.13.1Attribute syntax and semantics[dcl.attr.grammar]")opt thisopt [*decl-specifier-seq*](dcl.spec.general#nt:decl-specifier-seq "9.2.1General[dcl.spec.general]") [*declarator*](dcl.decl.general#nt:declarator "9.3.1General[dcl.decl.general]")
[*attribute-specifier-seq*](dcl.attr.grammar#nt:attribute-specifier-seq "9.13.1Attribute syntax and semantics[dcl.attr.grammar]")opt [*decl-specifier-seq*](dcl.spec.general#nt:decl-specifier-seq "9.2.1General[dcl.spec.general]") [*declarator*](dcl.decl.general#nt:declarator "9.3.1General[dcl.decl.general]") = [*initializer-clause*](dcl.init.general#nt:initializer-clause "9.5.1General[dcl.init.general]")
[*attribute-specifier-seq*](dcl.attr.grammar#nt:attribute-specifier-seq "9.13.1Attribute syntax and semantics[dcl.attr.grammar]")opt thisopt [*decl-specifier-seq*](dcl.spec.general#nt:decl-specifier-seq "9.2.1General[dcl.spec.general]") [*abstract-declarator*](dcl.name#nt:abstract-declarator "9.3.2Type names[dcl.name]")opt
[*attribute-specifier-seq*](dcl.attr.grammar#nt:attribute-specifier-seq "9.13.1Attribute syntax and semantics[dcl.attr.grammar]")opt [*decl-specifier-seq*](dcl.spec.general#nt:decl-specifier-seq "9.2.1General[dcl.spec.general]") [*abstract-declarator*](dcl.name#nt:abstract-declarator "9.3.2Type names[dcl.name]")opt = [*initializer-clause*](dcl.init.general#nt:initializer-clause "9.5.1General[dcl.init.general]")
The optional [*attribute-specifier-seq*](dcl.attr.grammar#nt:attribute-specifier-seq "9.13.1Attribute syntax and semantics[dcl.attr.grammar]") in a [*parameter-declaration*](#nt:parameter-declaration "9.3.4.6Functions[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.6Functions[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.6Functions[dcl.fct]") is used to convert the arguments specified on the function call;
see [[expr.call]](expr.call "7.6.1.3Function call")[.](#3.sentence-2)
— *end note*]
If the[*parameter-declaration-clause*](#nt:parameter-declaration-clause "9.3.4.6Functions[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.4Deprecated volatile types")[.](#3.sentence-6)
If the[*parameter-declaration-clause*](#nt:parameter-declaration-clause "9.3.4.6Functions[dcl.fct]")terminates with an ellipsis or a function parameter
pack ([[temp.variadic]](temp.variadic "13.7.4Variadic 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.2Type names[dcl.name]"),
“...”
is synonymous with
“, ...”[.](#3.sentence-8)
A [*parameter-declaration-clause*](#nt:parameter-declaration-clause "9.3.4.6Functions[dcl.fct]") of the form[*parameter-declaration-list*](#nt:parameter-declaration-list "9.3.4.6Functions[dcl.fct]") ... is deprecated ([[depr.ellipsis.comma]](depr.ellipsis.comma "D.5Non-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.2Header <cstdarg> synopsis[cstdarg.syn]") contains a mechanism for accessing arguments passed using the ellipsis
(see [[expr.call]](expr.call "7.6.1.3Function call") and [[support.runtime]](support.runtime "17.14Other 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.6Functions[dcl.fct]") ([[dcl.decl]](dcl.decl "9.3Declarators"))[.](#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.1General[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.6Functions[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.6Functions[dcl.fct]") is
a [*parameter-declaration*](#nt:parameter-declaration "9.3.4.6Functions[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.6Functions[dcl.fct]") of
a [*parameter-declaration-list*](#nt:parameter-declaration-list "9.3.4.6Functions[dcl.fct]") of one of:
- [(5.1)](#5.1)
a declaration of
a member function or member function template ([[class.mem]](class.mem "11.4Class members")), or
- [(5.2)](#5.2)
an explicit instantiation ([[temp.explicit]](temp.explicit "13.9.3Explicit instantiation")) or
explicit specialization ([[temp.expl.spec]](temp.expl.spec "13.9.4Explicit specialization")) of
a templated member function, or
- [(5.3)](#5.3)
a [*lambda-declarator*](expr.prim.lambda.general#nt:lambda-declarator "7.5.6.1General[expr.prim.lambda.general]") ([[expr.prim.lambda]](expr.prim.lambda "7.5.6Lambda expressions"))[.](#5.sentence-2)
A [*member-declarator*](class.mem.general#nt:member-declarator "11.4.1General[class.mem.general]") with an explicit-object-parameter-declaration
shall not include
a [*ref-qualifier*](dcl.decl.general#nt:ref-qualifier "9.3.1General[dcl.decl.general]") or a [*cv-qualifier-seq*](dcl.decl.general#nt:cv-qualifier-seq "9.3.1General[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.6Functions[dcl.fct]")[.](#6.sentence-1)
An explicit object parameter shall not be
a function parameter pack ([[temp.variadic]](temp.variadic "13.7.4Variadic templates"))[.](#6.sentence-2)
An [*explicit object member function*](#def:member_function,explicit_object "9.3.4.6Functions[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.6Functions[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.6Functions[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.2Candidate 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.6Functions[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.6Functions[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.1General[dcl.decl.general]") or a[*ref-qualifier*](dcl.decl.general#nt:ref-qualifier "9.3.1General[dcl.decl.general]") (including a type denoted by[*typedef-name*](dcl.typedef#nt:typedef-name "9.2.4The typedef specifier[dcl.typedef]") ([[dcl.typedef]](dcl.typedef "9.2.4The typedef specifier"), [[temp.param]](temp.param "13.2Template 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.1Preamble[dcl.pre]"),
- [(9.4)](#9.4)
the [*type-id*](dcl.name#nt:type-id "9.3.2Type names[dcl.name]") in the default argument of a[*type-parameter*](temp.param#nt:type-parameter "13.2Template parameters[temp.param]") ([[temp.param]](temp.param "13.2Template parameters")),
- [(9.5)](#9.5)
the [*type-id*](dcl.name#nt:type-id "9.3.2Type names[dcl.name]") of a [*template-argument*](temp.names#nt:template-argument "13.3Names of template specializations[temp.names]") for a[*type-parameter*](temp.param#nt:type-parameter "13.2Template parameters[temp.param]") ([[temp.arg.type]](temp.arg.type "13.4.2Type template arguments")), or
- [(9.6)](#9.6)
the operand of a [*reflect-expression*](expr.reflect#nt:reflect-expression "7.6.2.10The reflection operator[expr.reflect]") ([[expr.reflect]](expr.reflect "7.6.2.10The 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.1General[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.1General[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.1General[dcl.decl.general]"),
the [*cv-qualifier-seq*](dcl.decl.general#nt:cv-qualifier-seq "9.3.1General[dcl.decl.general]"), and
the exception specification,
but not the default arguments ([[dcl.fct.default]](dcl.fct.default "9.3.4.7Default arguments"))
or the trailing [*requires-clause*](temp.pre#nt:requires-clause "13.1Preamble[temp.pre]") ([[dcl.decl]](dcl.decl "9.3Declarators")),
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.9Type 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 "12Overloading"))[.](#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.4Deprecated 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.6Function 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.6Function 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.1General[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.1General[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.1General[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.6Functions[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.6Functions[dcl.fct]") is a function declaration that has
one or more generic parameter type placeholders ([[dcl.spec.auto]](dcl.spec.auto "9.2.9.7Placeholder type specifiers"))[.](#21.sentence-1)
An abbreviated function template is equivalent to
a function template ([[temp.fct]](temp.fct "13.7.7Function templates"))
whose [*template-parameter-list*](temp.pre#nt:template-parameter-list "13.1Preamble[temp.pre]") includes
one invented [*type-parameter*](temp.param#nt:type-parameter "13.2Template 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.1General[dcl.spec.auto.general]") of the form auto,
the invented parameter is
an unconstrained [*type-parameter*](temp.param#nt:type-parameter "13.2Template parameters[temp.param]")[.](#21.sentence-3)
For a [*placeholder-type-specifier*](dcl.spec.auto.general#nt:placeholder-type-specifier "9.2.9.7.1General[dcl.spec.auto.general]") of the form[*type-constraint*](temp.param#nt:type-constraint "13.2Template parameters[temp.param]") auto,
the invented parameter is a [*type-parameter*](temp.param#nt:type-parameter "13.2Template parameters[temp.param]") with
that [*type-constraint*](temp.param#nt:type-constraint "13.2Template parameters[temp.param]")[.](#21.sentence-4)
The invented [*type-parameter*](temp.param#nt:type-parameter "13.2Template parameters[temp.param]") declares
a template parameter pack
if the corresponding [*parameter-declaration*](#nt:parameter-declaration "9.3.4.6Functions[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.6Functions[dcl.fct]") by
replacing each occurrence of a placeholder with
the name of the corresponding invented [*type-parameter*](temp.param#nt:type-parameter "13.2Template 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.1Preamble[temp.pre]")[.](#22.sentence-1)
The invented [*type-parameter*](temp.param#nt:type-parameter "13.2Template parameters[temp.param]")*s* are
appended to the [*template-parameter-list*](temp.pre#nt:template-parameter-list "13.1Preamble[temp.pre]") after
the explicitly declared [*template-parameter*](temp.param#nt:template-parameter "13.2Template 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.1General[dcl.decl.general]") or [*abstract-declarator*](dcl.name#nt:abstract-declarator "9.3.2Type names[dcl.name]") containing an ellipsis shall only
be used in a [*parameter-declaration*](#nt:parameter-declaration "9.3.4.6Functions[dcl.fct]")[.](#24.sentence-1)
When it is part of a[*parameter-declaration-clause*](#nt:parameter-declaration-clause "9.3.4.6Functions[dcl.fct]"),
the [*parameter-declaration*](#nt:parameter-declaration "9.3.4.6Functions[dcl.fct]") declares a
function parameter pack ([[temp.variadic]](temp.variadic "13.7.4Variadic templates"))[.](#24.sentence-2)
Otherwise, the [*parameter-declaration*](#nt:parameter-declaration "9.3.4.6Functions[dcl.fct]") is part of a[*template-parameter-list*](temp.pre#nt:template-parameter-list "13.1Preamble[temp.pre]") and declares a
template parameter pack; see [[temp.param]](temp.param "13.2Template parameters")[.](#24.sentence-3)
A function parameter pack is a pack expansion ([[temp.variadic]](temp.variadic "13.7.4Variadic 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.6Functions[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.2Type 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.6Functions[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.6Functions[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.1General[dcl.decl.general]"))[.](#footnote-76.sentence-1)