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

273 lines
13 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.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.1General[dcl.init.general]") is specified in a[*parameter-declaration*](dcl.fct#nt:parameter-declaration "9.3.4.6Functions[dcl.fct]") this[*initializer-clause*](dcl.init.general#nt:initializer-clause "9.5.1General[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.3Function 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.6Functions[dcl.fct]") of a function declaration
or [*lambda-declarator*](expr.prim.lambda.general#nt:lambda-declarator "7.5.6.1General[expr.prim.lambda.general]") or in a[*template-parameter*](temp.param#nt:template-parameter "13.2Template parameters[temp.param]") ([[temp.param]](temp.param "13.2Template 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.6Functions[dcl.fct]"),
it shall not occur within a[*declarator*](dcl.decl.general#nt:declarator "9.3.1General[dcl.decl.general]") or[*abstract-declarator*](dcl.name#nt:abstract-declarator "9.3.2Type names[dcl.name]") of a[*parameter-declaration*](dcl.fct#nt:parameter-declaration "9.3.4.6Functions[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.3One-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<class ... T> struct C {void f(int n = 0, T...);};
C<int> 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.5Initializers"))[.](#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.7Constant expressions")) that
is a potentially-evaluated subexpression ([[intro.execution]](intro.execution "6.10.1Sequential execution")) of
the [*initializer-clause*](dcl.init.general#nt:initializer-clause "9.5.1General[dcl.init.general]") in a [*parameter-declaration*](dcl.fct#nt:parameter-declaration "9.3.4.6Functions[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.2Implicit 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.4Class members"))[.](#5.sentence-5)
Access checking applies to names in default arguments as
described in [[class.access]](class.access "11.8Member 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.2Default constructors")),
copy or move constructor ([[class.copy.ctor]](class.copy.ctor "11.4.5.3Copy/move constructors")), or
copy or move assignment operator ([[class.copy.assign]](class.copy.assign "11.4.6Copy/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.3One-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.3This")[.](#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.3Context 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.1General[expr.prim.id.general]") or [*splice-expression*](expr.prim.splice#nt:splice-expression "7.5.9Expression splicing[expr.prim.splice]") of a class member access expression ([[expr.ref]](expr.ref "7.6.1.5Class 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.2Unary operators")), or
- [(9.3)](#9.3)
it appears as 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-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 "11Classes")[.](#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.3Viable 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.10The 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.3Virtual 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)