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

378 lines
18 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.

[expr.call]
# 7 Expressions [[expr]](./#expr)
## 7.6 Compound expressions [[expr.compound]](expr.compound#expr.call)
### 7.6.1 Postfix expressions [[expr.post]](expr.post#expr.call)
#### 7.6.1.3 Function call [expr.call]
[1](#1)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/expressions.tex#L3749)
A function call is a postfix expression followed by parentheses
containing a possibly empty, comma-separated list of[*initializer-clause*](dcl.init.general#nt:initializer-clause "9.5.1General[dcl.init.general]")*s* which
constitute the arguments to the function[.](#1.sentence-1)
[*Note [1](#note-1)*:
If the postfix expression is a function or member function name,
the appropriate function and the validity of the call
are determined according to the rules in [[over.match]](over.match "12.2Overload resolution")[.](#1.sentence-2)
— *end note*]
The postfix expression shall
have function type or function pointer type[.](#1.sentence-3)
For a call to a non-member function or to a static member function,
the postfix expression shall be either an lvalue that refers to a
function (in which case the function-to-pointer standard
conversion ([[conv.func]](conv.func "7.3.4Function-to-pointer conversion")) is suppressed on the postfix expression),
or a prvalue of function pointer type[.](#1.sentence-4)
[2](#2)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/expressions.tex#L3770)
If the selected
function is non-virtual, or if the [*id-expression*](expr.prim.id.general#nt:id-expression "7.5.5.1General[expr.prim.id.general]") in the class
member access expression is a [*qualified-id*](expr.prim.id.qual#nt:qualified-id "7.5.5.3Qualified names[expr.prim.id.qual]"), that function is
called[.](#2.sentence-1)
Otherwise, its [final overrider](class.virtual#def:final_overrider "11.7.3Virtual functions[class.virtual]") in the dynamic type
of the object expression is called; such a call is referred to as a[*virtual function call*](#def:function,virtual_function_call "7.6.1.3Function call[expr.call]")[.](#2.sentence-2)
[*Note [2](#note-2)*:
The dynamic type is the type of the object referred to by the
current value of the object expression[.](#2.sentence-3)
[[class.cdtor]](class.cdtor "11.9.5Construction and destruction") describes the
behavior of virtual function calls when the object expression
refers to
an object under construction or destruction[.](#2.sentence-4)
— *end note*]
[3](#3)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/expressions.tex#L3785)
[*Note [3](#note-3)*:
If a function or member function name is used, and [name
lookup](basic.lookup "6.5Name lookup[basic.lookup]") does not find a declaration of that name,
the program is ill-formed[.](#3.sentence-1)
No function is implicitly declared by such a
call[.](#3.sentence-2)
— *end note*]
[4](#4)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/expressions.tex#L3793)
If the [*postfix-expression*](expr.post.general#nt:postfix-expression "7.6.1.1General[expr.post.general]") names
a destructor or pseudo-destructor ([[expr.prim.id.dtor]](expr.prim.id.dtor "7.5.5.5Destruction")),
the type of the function call expression is void; otherwise, the
type of the function call expression is the return type of the
statically chosen function (i.e., ignoring the virtual keyword),
even if the type of the function actually called is different[.](#4.sentence-1)
If the [*postfix-expression*](expr.post.general#nt:postfix-expression "7.6.1.1General[expr.post.general]") names a pseudo-destructor
(in which case the [*postfix-expression*](expr.post.general#nt:postfix-expression "7.6.1.1General[expr.post.general]") is a possibly-parenthesized class member access),
the function call destroys
the object of scalar type
denoted by the object expression
of the class member access ([[expr.ref]](expr.ref "7.6.1.5Class member access"), [[basic.life]](basic.life "6.8.4Lifetime"))[.](#4.sentence-2)
[5](#5)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/expressions.tex#L3809)
A type Tcall is[*call-compatible*](#def:call-compatible "7.6.1.3Function call[expr.call]") with a function type Tfunc if Tcall is the same type as Tfunc or
if the type “pointer to Tfunc” can be
converted to type “pointer to Tcall”
via a function pointer conversion ([[conv.fctptr]](conv.fctptr "7.3.14Function pointer conversions"))[.](#5.sentence-1)
Calling a function through an
expression whose function type
is not call-compatible with the
type of the called function's
definition results in undefined behavior[.](#5.sentence-2)
[*Note [4](#note-4)*:
This requirement allows the case
when the expression has the type of a
potentially-throwing function, but the called function has
a non-throwing exception specification,
and the function types are otherwise the same[.](#5.sentence-3)
— *end note*]
[6](#6)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/expressions.tex#L3829)
When a function is called, each parameter ([[dcl.fct]](dcl.fct "9.3.4.6Functions")) is
initialized ([[dcl.init]](dcl.init "9.5Initializers"), [[class.copy.ctor]](class.copy.ctor "11.4.5.3Copy/move constructors")) with
its corresponding argument,
and each precondition assertion of the function
is evaluated ([[dcl.contract.func]](dcl.contract.func "9.4.1General"))[.](#6.sentence-1)
If the function is an explicit object member function and
there is an implied object argument ([[over.call.func]](over.call.func "12.2.2.2.2Call to designated function")),
the list of provided arguments is preceded by the implied object argument
for the purposes of this correspondence[.](#6.sentence-2)
If there is no corresponding argument,
the default argument for the parameter is used[.](#6.sentence-3)
[*Example [1](#example-1)*: template<typename ...T> int f(int n = 0, T ...t);int x = f<int>(); // error: no argument for second function parameter — *end example*]
If the function is an implicit object member
function,
the object expression of the class member access shall be a glvalue and
the implicit object parameter of the function ([[over.match.funcs]](over.match.funcs "12.2.2Candidate functions and argument lists"))
is initialized with that glvalue,
converted as if by an [explicit type conversion](expr.cast "7.6.3Explicit type conversion (cast notation)[expr.cast]")[.](#6.sentence-4)
[*Note [5](#note-5)*:
There is no access or ambiguity checking on this conversion; the access
checking and disambiguation are done as part of the (possibly implicit)
class member access operator[.](#6.sentence-5)
See [[class.member.lookup]](class.member.lookup "6.5.2Member name lookup"), [[class.access.base]](class.access.base "11.8.3Accessibility of base classes and base class members"),
and [[expr.ref]](expr.ref "7.6.1.5Class member access")[.](#6.sentence-6)
— *end note*]
When a function is called, the type of any parameter
shall not be a class type that is either incomplete or abstract[.](#6.sentence-7)
[*Note [6](#note-6)*:
This still allows a parameter to be a pointer or reference to such
a type[.](#6.sentence-8)
However, it prevents a passed-by-value parameter
to have an incomplete or abstract class type[.](#6.sentence-9)
— *end note*]
It is implementation-defined
whether a parameter is destroyed
when the function in which it is defined exits ([[stmt.return]](stmt.return "8.8.4The return statement"), [[except.ctor]](except.ctor "14.3Stack unwinding"), [[expr.await]](expr.await "7.6.2.4Await"))
or at the end of the enclosing full-expression;
parameters are always destroyed in the reverse order of their construction[.](#6.sentence-10)
The initialization and destruction of each parameter occurs
within the context of the full-expression ([[intro.execution]](intro.execution "6.10.1Sequential execution"))
where the function call appears[.](#6.sentence-11)
[*Example [2](#example-2)*:
The access ([[class.access.general]](class.access.general "11.8.1General")) of the
constructor, conversion functions, or destructor is
checked at the point of call[.](#6.sentence-12)
If a constructor
or destructor for a function parameter throws an exception,
any [*function-try-block*](except.pre#nt:function-try-block "14.1Preamble[except.pre]") ([[except.pre]](except.pre "14.1Preamble"))
of the called function
with a handler that can handle the exception
is not considered[.](#6.sentence-13)
— *end example*]
[7](#7)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/expressions.tex#L3890)
The [*postfix-expression*](expr.post.general#nt:postfix-expression "7.6.1.1General[expr.post.general]") is sequenced before
each [*expression*](expr.comma#nt:expression "7.6.20Comma operator[expr.comma]") in the [*expression-list*](expr.post.general#nt:expression-list "7.6.1.1General[expr.post.general]") and any default argument[.](#7.sentence-1)
The initialization of a parameter or,
if the implementation introduces any temporary objects
to hold the values of function parameters ([[class.temporary]](class.temporary "6.8.7Temporary objects")),
the initialization of those temporaries,
including every associated value computation and side effect,
is indeterminately sequenced with respect to that of any other parameter[.](#7.sentence-2)
These evaluations are
sequenced before
the evaluation of the precondition assertions of the function,
which are evaluated in sequence ([[dcl.contract.func]](dcl.contract.func "9.4.1General"))[.](#7.sentence-3)
For any temporaries
introduced to hold the values of function parameters,
the initialization of the parameter objects from those temporaries
is indeterminately sequenced with respect to
the evaluation of each precondition assertion[.](#7.sentence-4)
[*Note [7](#note-7)*:
All side effects of
argument evaluations are sequenced before the function is
entered (see [[intro.execution]](intro.execution "6.10.1Sequential execution"))[.](#7.sentence-5)
— *end note*]
[*Example [3](#example-3)*: void f() { std::string s = "but I have heard it works even if you don't believe in it";
s.replace(0, 4, "").replace(s.find("even"), 4, "only").replace(s.find(" don't"), 6, "");
assert(s == "I have heard it works only if you believe in it"); // OK} — *end example*]
[*Note [8](#note-8)*:
If an operator function is invoked
using operator notation,
argument evaluation is sequenced
as specified for the built-in operator;
see [[over.match.oper]](over.match.oper "12.2.2.3Operators in expressions")[.](#7.sentence-6)
— *end note*]
[*Example [4](#example-4)*: struct S { S(int);};int operator<<(S, int);int i, j;int x = S(i=1) << (i=2);int y = operator<<(S(j=1), j=2);
After performing the initializations,
the value of i is 2 (see [[expr.shift]](expr.shift "7.6.7Shift operators")),
but it is unspecified whether the value of j is 1 or 2[.](#7.sentence-7)
— *end example*]
[8](#8)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/expressions.tex#L3948)
The result of a function call is the result of the possibly-converted operand
of the return statement ([[stmt.return]](stmt.return "8.8.4The return statement"))
that transferred control out of the called function (if any),
except in a virtual function call if the return type of the
final overrider is different from the return type of the statically
chosen function, the value returned from the final overrider is
converted to the return type of the statically chosen function[.](#8.sentence-1)
[9](#9)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/expressions.tex#L3957)
When the called function exits normally ([[stmt.return]](stmt.return "8.8.4The return statement"), [[expr.await]](expr.await "7.6.2.4Await")),
all postcondition assertions of the function
are evaluated in sequence ([[dcl.contract.func]](dcl.contract.func "9.4.1General"))[.](#9.sentence-1)
If the implementation introduces any temporary objects
to hold the result value as specified in [[class.temporary]](class.temporary "6.8.7Temporary objects"),
the evaluation of each postcondition assertion
is indeterminately sequenced with respect to
the initialization of any of those temporaries or the result object[.](#9.sentence-2)
These evaluations, in turn, are sequenced before
the destruction of any function parameters[.](#9.sentence-3)
[10](#10)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/expressions.tex#L3969)
[*Note [9](#note-9)*:
A function can change the values of its non-const parameters, but these
changes cannot affect the values of the arguments except where a
parameter is of a reference type ([[dcl.ref]](dcl.ref "9.3.4.3References")); if the reference is to
a const-qualified type, const_cast needs to be used to
cast away the constness in order to modify the argument's value[.](#10.sentence-1)
Where a
parameter is of const reference type a temporary object is
introduced if
needed ([[dcl.type]](dcl.type "9.2.9Type specifiers"), [[lex.literal]](lex.literal "5.13Literals"), [[lex.string]](lex.string "5.13.5String literals"), [[dcl.array]](dcl.array "9.3.4.5Arrays"), [[class.temporary]](class.temporary "6.8.7Temporary objects"))[.](#10.sentence-2)
In addition, it is possible to modify the values of non-constant objects through
pointer parameters[.](#10.sentence-3)
— *end note*]
[11](#11)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/expressions.tex#L3989)
A function can be declared to accept fewer arguments (by declaring [default
arguments](dcl.fct.default "9.3.4.7Default arguments[dcl.fct.default]")) or more arguments (by using the ellipsis,..., or a function parameter pack ([[dcl.fct]](dcl.fct "9.3.4.6Functions"))) than the number of
parameters in the [function definition](dcl.fct.def "9.6Function definitions[dcl.fct.def]")[.](#11.sentence-1)
[*Note [10](#note-10)*:
This implies that, except where the ellipsis (...) or a function
parameter pack is used, a parameter is available for each argument[.](#11.sentence-2)
— *end note*]
[12](#12)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/expressions.tex#L4001)
When there is no parameter for a given argument, the argument is passed
in such a way that the receiving function can obtain the value of the
argument by invoking va_arg ([[support.runtime]](support.runtime "17.14Other runtime support"))[.](#12.sentence-1)
[*Note [11](#note-11)*:
This paragraph does not apply to arguments passed to a function parameter pack[.](#12.sentence-2)
Function parameter packs are expanded during template instantiation ([[temp.variadic]](temp.variadic "13.7.4Variadic templates")),
thus each such argument has a corresponding parameter when a function template
specialization is actually called[.](#12.sentence-3)
— *end note*]
The[lvalue-to-rvalue](conv.lval "7.3.2Lvalue-to-rvalue conversion[conv.lval]"), [array-to-pointer](conv.array "7.3.3Array-to-pointer conversion[conv.array]"),
and [function-to-pointer](conv.func "7.3.4Function-to-pointer conversion[conv.func]") standard conversions are
performed on the argument expression[.](#12.sentence-4)
An argument that has type cv std::nullptr_t is converted
to type void* ([[conv.ptr]](conv.ptr "7.3.12Pointer conversions"))[.](#12.sentence-5)
After these conversions, if the
argument does not have arithmetic, enumeration, pointer, pointer-to-member,
or class type, the program is ill-formed[.](#12.sentence-6)
Passing a potentially-evaluated argument
of a scoped enumeration type ([[dcl.enum]](dcl.enum "9.8.1Enumeration declarations")) or
of a class type ([[class]](class "11Classes")) having
an eligible non-trivial copy constructor ([[special]](special "11.4.4Special member functions"), [[class.copy.ctor]](class.copy.ctor "11.4.5.3Copy/move constructors")),
an eligible non-trivial move constructor, or
a non-trivial destructor ([[class.dtor]](class.dtor "11.4.7Destructors")),
with no corresponding parameter, is conditionally-supported withimplementation-defined semantics[.](#12.sentence-7)
If the argument has
integral or enumeration type that is subject to the [integral
promotions](conv.prom "7.3.7Integral promotions[conv.prom]"), or a floating-point type that is subject to the[floating-point promotion](conv.fpprom "7.3.8Floating-point promotion[conv.fpprom]"), the value of the argument is converted to the
promoted type before the call[.](#12.sentence-8)
These promotions are referred to as
the [*default argument promotions*](#def:promotion,default_argument_promotion "7.6.1.3Function call[expr.call]")[.](#12.sentence-9)
[13](#13)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/expressions.tex#L4035)
Recursive calls are permitted, except to the [main function](basic.start.main "6.10.3.1main function[basic.start.main]")[.](#13.sentence-1)
[14](#14)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/expressions.tex#L4040)
A function call is an lvalue
if the result type is an lvalue reference type or an rvalue reference to function type,
an xvalue if the result type is an rvalue reference to object type, and a prvalue
otherwise[.](#14.sentence-1)
If it is a non-void prvalue,
the type of the function call expression shall be complete,
except as specified in [[dcl.type.decltype]](dcl.type.decltype "9.2.9.6Decltype specifiers")[.](#14.sentence-2)