[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.syn#header:%3ccstdarg%3e "17.14.2 Header 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 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 std::move(c).g(42); // OK, calls C​::​g} — *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 auto add(T t, U u) -> decltype(t + u); rather thantemplate 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 concept C1 = /* ... */;template concept C2 = /* ... */;template 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 void g1(const T*, U&);template void g2(Ts&...);template void g3(Ts...);template void g4(T); Abbreviated function templates can be specialized like all function templates[.](#21.sentence-9) template<> void g1(const int*, const double&); // OK, specialization of g1 — *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 concept C = /* ... */; template void g(T x, U y, C auto z); This is functionally equivalent to each of the following two declarations[.](#22.sentence-3) templatevoid g(T x, U y, W z); templaterequires C && Cvoid 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 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)