[dcl.fct.default] # 9 Declarations [[dcl]](./#dcl) ## 9.3 Declarators [[dcl.decl]](dcl.decl#dcl.fct.default) ### 9.3.4 Meaning of declarators [[dcl.meaning]](dcl.meaning#dcl.fct.default) #### 9.3.4.7 Default arguments [dcl.fct.default] [1](#1) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/declarations.tex#L4263) If an [*initializer-clause*](dcl.init.general#nt:initializer-clause "9.5.1 General [dcl.init.general]") is specified in a[*parameter-declaration*](dcl.fct#nt:parameter-declaration "9.3.4.6 Functions [dcl.fct]") this[*initializer-clause*](dcl.init.general#nt:initializer-clause "9.5.1 General [dcl.init.general]") is used as a default argument[.](#1.sentence-1) [*Note [1](#note-1)*: Default arguments will be used in calls where trailing arguments are missing ([[expr.call]](expr.call "7.6.1.3 Function call"))[.](#1.sentence-2) — *end note*] [2](#2) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/declarations.tex#L4273) [*Example [1](#example-1)*: The declarationvoid point(int = 3, int = 4); declares a function that can be called with zero, one, or two arguments of typeint[.](#2.sentence-1) It can be called in any of these ways:point(1,2); point(1); point(); The last two calls are equivalent topoint(1,4) andpoint(3,4), respectively[.](#2.sentence-3) — *end example*] [3](#3) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/declarations.tex#L4294) A default argument shall be specified only in the[*parameter-declaration-clause*](dcl.fct#nt:parameter-declaration-clause "9.3.4.6 Functions [dcl.fct]") of a function declaration or [*lambda-declarator*](expr.prim.lambda.general#nt:lambda-declarator "7.5.6.1 General [expr.prim.lambda.general]") or in a[*template-parameter*](temp.param#nt:template-parameter "13.2 Template parameters [temp.param]") ([[temp.param]](temp.param "13.2 Template parameters"))[.](#3.sentence-1) A default argument shall not be specified for a template parameter pack or a function parameter pack[.](#3.sentence-2) If it is specified in a[*parameter-declaration-clause*](dcl.fct#nt:parameter-declaration-clause "9.3.4.6 Functions [dcl.fct]"), it shall not occur within a[*declarator*](dcl.decl.general#nt:declarator "9.3.1 General [dcl.decl.general]") or[*abstract-declarator*](dcl.name#nt:abstract-declarator "9.3.2 Type names [dcl.name]") of a[*parameter-declaration*](dcl.fct#nt:parameter-declaration "9.3.4.6 Functions [dcl.fct]")[.](#3.sentence-3)[77](#footnote-77 "This means that default arguments cannot appear, for example, in declarations of pointers to functions, references to functions, or typedef declarations.") [4](#4) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/declarations.tex#L4321) For non-template functions, default arguments can be added in later declarations of a function that have the same host scope[.](#4.sentence-1) Declarations that have different host scopes have completely distinct sets of default arguments[.](#4.sentence-2) That is, declarations in inner scopes do not acquire default arguments from declarations in outer scopes, and vice versa[.](#4.sentence-3) In a given function declaration, each parameter subsequent to a parameter with a default argument shall have a default argument supplied in this or a previous declaration, unless the parameter was expanded from a parameter pack, or shall be a function parameter pack[.](#4.sentence-4) [*Note [2](#note-2)*: A default argument cannot be redefined by a later declaration (not even to the same value) ([[basic.def.odr]](basic.def.odr "6.3 One-definition rule"))[.](#4.sentence-5) — *end note*] [*Example [2](#example-2)*: void g(int = 0, ...); // OK, ellipsis is not a parameter so it can follow// a parameter with a default argumentvoid f(int, int);void f(int, int = 7);void h() { f(3); // OK, calls f(3, 7)void f(int = 1, int); // error: does not use default from surrounding scope}void m() {void f(int, int); // has no defaults f(4); // error: wrong number of argumentsvoid f(int, int = 5); // OK f(4); // OK, calls f(4, 5);void f(int, int = 5); // error: cannot redefine, even to same value}void n() { f(6); // OK, calls f(6, 7)}template struct C {void f(int n = 0, T...);}; C c; // OK, instantiates declaration void C​::​f(int n = 0, int) — *end example*] For a given inline function defined in different translation units, the accumulated sets of default arguments at the end of the translation units shall be the same; no diagnostic is required[.](#4.sentence-6) If a friend declaration D specifies a default argument expression, that declaration shall be a definition and there shall be no other declaration of the function or function template which is reachable from D or from which D is reachable[.](#4.sentence-7) [5](#5) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/declarations.tex#L4375) The default argument has the same semantic constraints as the initializer in a declaration of a variable of the parameter type, using the copy-initialization semantics ([[dcl.init]](dcl.init "9.5 Initializers"))[.](#5.sentence-1) The names in the default argument are looked up, and the semantic constraints are checked, at the point where the default argument appears, except that an immediate invocation ([[expr.const]](expr.const "7.7 Constant expressions")) that is a potentially-evaluated subexpression ([[intro.execution]](intro.execution "6.10.1 Sequential execution")) of the [*initializer-clause*](dcl.init.general#nt:initializer-clause "9.5.1 General [dcl.init.general]") in a [*parameter-declaration*](dcl.fct#nt:parameter-declaration "9.3.4.6 Functions [dcl.fct]") is neither evaluated nor checked for whether it is a constant expression at that point[.](#5.sentence-2) Name lookup and checking of semantic constraints for default arguments of templated functions are performed as described in [[temp.inst]](temp.inst "13.9.2 Implicit instantiation")[.](#5.sentence-3) [*Example [3](#example-3)*: In the following code,g will be called with the valuef(2):int a = 1;int f(int);int g(int x = f(a)); // default argument: f(​::​a)void h() { a = 2; {int a = 3; g(); // g(f(​::​a))}} — *end example*] [*Note [3](#note-3)*: A default argument is a complete-class context ([[class.mem]](class.mem "11.4 Class members"))[.](#5.sentence-5) Access checking applies to names in default arguments as described in [[class.access]](class.access "11.8 Member access control")[.](#5.sentence-6) — *end note*] [6](#6) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/declarations.tex#L4419) Except for member functions of templated classes, the default arguments in a member function definition that appears outside of the class definition are added to the set of default arguments provided by the member function declaration in the class definition; the program is ill-formed if a default constructor ([[class.default.ctor]](class.default.ctor "11.4.5.2 Default constructors")), copy or move constructor ([[class.copy.ctor]](class.copy.ctor "11.4.5.3 Copy/move constructors")), or copy or move assignment operator ([[class.copy.assign]](class.copy.assign "11.4.6 Copy/move assignment operator")) is so declared[.](#6.sentence-1) Default arguments for a member function of a templated class shall be specified on the initial declaration of the member function within the templated class[.](#6.sentence-2) [*Example [4](#example-4)*: class C {void f(int i = 3); void g(int i, int j = 99);}; void C::f(int i = 3) {} // error: default argument already specified in class scopevoid C::g(int i = 88, int j) {} // in this translation unit, C​::​g can be called with no arguments — *end example*] [7](#7) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/declarations.tex#L4444) [*Note [4](#note-4)*: A local variable cannot be odr-used ([[basic.def.odr]](basic.def.odr#term.odr.use "6.3 One-definition rule")) in a default argument[.](#7.sentence-1) — *end note*] [*Example [5](#example-5)*: void f() {int i; extern void g(int x = i); // errorextern void h(int x = sizeof(i)); // OK// ...} — *end example*] [8](#8) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/declarations.tex#L4460) [*Note [5](#note-5)*: The keywordthis cannot appear in a default argument of a member function; see [[expr.prim.this]](expr.prim.this "7.5.3 This")[.](#8.sentence-1) [*Example [6](#example-6)*: class A {void f(A* p = this) { } // error}; — *end example*] — *end note*] [9](#9) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/declarations.tex#L4475) A default argument is evaluated each time the function is called with no argument for the corresponding parameter[.](#9.sentence-1) A parameter shall not appear as a potentially-evaluated expression in a default argument[.](#9.sentence-2) [*Note [6](#note-6)*: Parameters of a function declared before a default argument are in scope and can hide namespace and class member names[.](#9.sentence-3) — *end note*] [*Example [7](#example-7)*: int a;int f(int a, int b = a); // error: parameter a used as default argumenttypedef int I;int g(float I, int b = I(2)); // error: parameter I foundint h(int a, int b = sizeof(a)); // OK, [unevaluated operand](expr.context#def:unevaluated_operand "7.2.3 Context dependence [expr.context]") — *end example*] A non-static member shall not be designated in a default argument unless - [(9.1)](#9.1) it is designated by the [*id-expression*](expr.prim.id.general#nt:id-expression "7.5.5.1 General [expr.prim.id.general]") or [*splice-expression*](expr.prim.splice#nt:splice-expression "7.5.9 Expression splicing [expr.prim.splice]") of a class member access expression ([[expr.ref]](expr.ref "7.6.1.5 Class member access")), - [(9.2)](#9.2) it is designated by an expression used to form a pointer to member ([[expr.unary.op]](expr.unary.op "7.6.2.2 Unary operators")), or - [(9.3)](#9.3) it appears as 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-4) [*Example [8](#example-8)*: The declaration ofX​::​mem1() in the following example is ill-formed because no object is supplied for the non-static memberX​::​a used as an initializer[.](#9.sentence-5) int b;class X {int a; int mem1(int i = a); // error: non-static member a used as default argumentint mem2(int i = b); // OK, use X​::​bconsteval void mem3(std::meta::info r = ^^a) {} // OKint mem4(int i = [:^^a:]); // error: non-static member a designated in default argumentstatic int b;}; The declaration ofX​::​mem2() is meaningful, however, since no object is needed to access the static memberX​::​b[.](#9.sentence-6) Classes, objects, and members are described in [[class]](class "11 Classes")[.](#9.sentence-7) — *end example*] A default argument is not part of the type of a function[.](#9.sentence-8) [*Example [9](#example-9)*: int f(int = 0); void h() {int j = f(1); int k = f(); // OK, means f(0)}int (*p1)(int) = &f;int (*p2)() = &f; // error: type mismatch — *end example*] [*Note [7](#note-7)*: When an overload set contains a declaration of a function whose host scope is S, any default argument associated with any reachable declaration whose host scope is S is available to the call ([[over.match.viable]](over.match.viable "12.2.3 Viable functions"))[.](#9.sentence-9) — *end note*] [*Note [8](#note-8)*: The candidate might have been found through a [*using-declarator*](namespace.udecl#nt:using-declarator "9.10 The using declaration [namespace.udecl]") from which the declaration that provides the default argument is not reachable[.](#9.sentence-10) — *end note*] [10](#10) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/declarations.tex#L4560) A virtual function call ([[class.virtual]](class.virtual "11.7.3 Virtual functions")) uses the default arguments in the declaration of the virtual function determined by the static type of the pointer or reference denoting the object[.](#10.sentence-1) An overriding function in a derived class does not acquire default arguments from the function it overrides[.](#10.sentence-2) [*Example [10](#example-10)*: struct A {virtual void f(int a = 7);};struct B : public A {void f(int a);};void m() { B* pb = new B; A* pa = pb; pa->f(); // OK, calls pa->B​::​f(7) pb->f(); // error: wrong number of arguments for B​::​f()} — *end example*] [77)](#footnote-77)[77)](#footnoteref-77) This means that default arguments cannot appear, for example, in declarations of pointers to functions, references to functions, ortypedef declarations[.](#footnote-77.sentence-1)