273 lines
13 KiB
Markdown
273 lines
13 KiB
Markdown
[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<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.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)
|