a(a1, a2)
Yes R T::operator()(Arg1 &a1, Arg2 &a2, ...); N/A comma a, b
Yes T2& T::operator,(T2 &b); T2& operator,(const T &a, T2 &b); conditional operator a ? b : c
No N/A N/A
The function call operator provides function semantics for any object.
The conditional operator (colloquially referred to as ternary conditional ) checks the boolean value of the first expression and, depending on the resulting value, evaluates and returns either the second or the third expression.
[edit] Built-in function call operatorFunction call expressions have the following form:
function (
arg1,
arg2,
arg3,
...)
function - an expression function type or function pointer type arg1,
arg2,
arg3,
... - a possibly empty list of arbitrary expressions or brace-enclosed initializer lists(since C++11), except the comma operator is not allowed at the top level to avoid ambiguity
For a call to a non-member function or to a static member function, function can be an lvalue that refers to a function (in which case the function-to-pointer conversion is suppressed), or a prvalue of function pointer type.
The function (or member) name specified by function can be overloaded, overload resolution rules used to decide which overload is to be called.
If function specifies a member function, it may be virtual, in which case the final overrider of that function will be called, using dynamic dispatch at runtime.
Each function parameter is initialized with its corresponding argument after implicit conversion if necessary.
If the function is a variadic function, default argument promotions are applied to all arguments matched by the ellipsis parameter.
It is implementation-defined whether a parameter is destroyed when the function in which it is defined exits or at the end of the enclosing full-expression. Parameters are always destroyed in the reverse order of their construction.
The return type of a function call expression is the return type of the chosen function, decided using static binding (ignoring the virtual keyword), even if the overriding function that is actually called returns a different type. This allows the overriding functions to return pointers or references to classes that are derived from the return type returned by the base function, i.e. C++ supports covariant return types. If function specifies a destructor, the return type is void.
When an object of class type X
is passed to or returned from a function, if each copy constructor, move constructor, and destructor of X
is either trivial or deleted, and X
has at least one non-deleted copy or move constructor, implementations are permitted to create a temporary object to hold the function parameter or result object.
The temporary object is constructed from the function argument or return value, respectively, and the function's parameter or return object is initialized as if by using the non-deleted trivial constructor to copy the temporary (even if that constructor is inaccessible or would not be selected by overload resolution to perform a copy or move of the object).
This allows objects of small class types, such as std::complex or std::span, to be passed to or returned from functions in registers.
(since C++17)The value category of a function call expression is lvalue if the function returns an lvalue reference or an rvalue reference to function, is an xvalue if the function returns an rvalue reference to object, and is a prvalue otherwise. If the function call expression is a prvalue of object type, it must have complete type except when used as the operand of decltype
(or as the right operand of a built-in comma operator that is the operand of decltype)(since C++11).
Function call expression is similar in syntax to value initialization T(), to function-style cast expression T(A1), and to direct initialization of a temporary T(A1, A2, A3, ...), where T
is the name of a type.
#include <cstdio> struct S { int f1(double d) { return printf("%f \n", d); // variable argument function call } int f2() { return f1(7); // member function call, same as this->f1() // integer argument converted to double } }; void f() { puts("function called"); // function call } int main() { f(); // function call S s; s.f2(); // member function call }
Output:
[edit] Built-in comma operatorComma expressions have the following form:
In a comma expression E1, E2, the expression E1 is evaluated, its result is discarded (although if it has class type, it won't be destroyed until the end of the containing full expression), and its side effects are completed before evaluation of the expression E2 begins (note that a user-defined operator,
cannot guarantee sequencing)(until C++17).
The type, value, and value category of the result of the comma expression are exactly the type, value, and value category of the second operand, E2. If E2 is a temporary expression(since C++17), the result of the expression is that temporary expression(since C++17). If E2 is a bit-field, the result is a bit-field.
The comma in various comma-separated lists, such as function argument lists (f(a, b, c)) and initializer lists int a[] = {1, 2, 3}, is not the comma operator. If the comma operator needs to be used in such contexts, it has to be parenthesized: f(a, (n++, n + b), c).
Using an unparenthesized comma expression as second (right) argument of a subscript operator is deprecated.
For example, a[b, c] is deprecated and a[(b, c)] is not.
(since C++20)An unparenthesized comma expression cannot be second (right) argument of a subscript operator. For example, a[b, c] is either ill-formed or equivalent to a.operator[](b, c).
Parentheses are needed when using a comma expression as the subscript, e.g., a[(b, c)].
(since C++23)#include <iostream> int main() { // comma is often used to execute more than one expression // where the language grammar allows only one expression: // * in the third component of the for loop for (int i = 0, j = 10; i <= j; ++i, --j) // ^list separator ^comma operator std::cout << "i = " << i << " j = " << j << '\n'; // * in a return statement // return log("an error!"), -1; // * in an initializer expression // MyClass(const Arg& arg) // : member{ throws_if_bad(arg), arg } // etc. // comma operators can be chained; the result of the last // (rightmost) expression is the result of the whole chain: int n = 1; int m = (++n, std::cout << "n = " << n << '\n', ++n, 2 * n); // m is now 6 std::cout << "m = " << (++m, m) << '\n'; }
Output:
i = 0 j = 10 i = 1 j = 9 i = 2 j = 8 i = 3 j = 7 i = 4 j = 6 i = 5 j = 5 n = 2 m = 7[edit] Conditional operator
The conditional operator expressions have the form
E1 is evaluated and contextually converted to bool, if the result is true, the result of the conditional expression is the value of E2 ; otherwise the result of the conditional expression is the value of E3 .
The type and value category of the conditional expression E1 ? E2 : E3 are determined as follows:
[edit] Stage 1If both E2 and E3 are of type void, the result is an rvalue(until C++11)a prvalue(since C++11) of type void.
If exactly one of E2 and E3 is of type void:
If neither of E2 and E3 is of type void, proceed to the next stage.
2 + 2 == 4 ? throw 123 : throw 456; // the result is of type âvoidâ 2 + 2 != 4 ? "OK" : throw "error"; // the result is of type âconst char[3]â // even if an exception is always thrown[edit] Stage 2
If E2 or E3 are lvalue bit-fields(until C++11)glvalue bit-fields of the same value category(since C++11) and of types cv1 T
and cv2 T
, respectively, the operands are considered to be of type cv T
for the remaining process, where cv is the union of cv1 and cv2.
If E2 and E3 have different types, and any of the following conditions is satisfied, proceed to stage 3:
Otherwise, proceed to stage 4.
[edit] Stage 3Attempts are made to form an implicit conversion sequence[2] from an operand expression X of type TX
to a target type related to the type TY
of the operand expression Y as follows:
TY&
, but an implicit conversion sequence can only be formed if the reference would bind directly to an lvalue(until C++11)a glvalue(since C++11).TY&&
, but an implicit conversion sequence can only be formed if the reference would bind directly.TX
and TY
is a (possibly cv-qualified) class type:
TX
and TY
are the same class type (ignoring cv-qualification):
TY
is at least as cv-qualified as TX
, the target type is TY
.TY
is a base class of TX
, the target type is TY
with the cv-qualifiers of TX
.Using this process, it is determined whether an implicit conversion sequence can be formed from E2 to the target type determined for the E3, and vice versa.
struct A {}; struct B : A {}; using T = const B; A a = true ? A() : T(); // Y = A(), TY = A, X = T(), TX = const B, Target = const A[edit] Stage 4
If E2 and E3 are lvalues of the same type, then the result is an lvalue of that type, and is a bit-field if at least one of E2 and E3 is a bit-field.
(until C++11)If E2 and E3 are glvalues of the same type and the same value category, then the result has the same type and value category, and is a bit-field if at least one of E2 and E3 is a bit-field.
(since C++11)Otherwise, the result is an rvalue(until C++11)a prvalue(since C++11).
Overload resolution is performed using the built-in candidates to attempt to convert the operands to built-in types:
The array-to-pointer and function-to-pointer conversions are applied to (possibly-converted) E2 and E3. After those conversions, at least one of the following conditions must hold, otherwise the program is ill-formed:
int* intPtr; using Mixed = decltype(true ? nullptr : intPtr); static_assert(std::is_same_v<Mixed, int*>); // nullptr becoming int* struct A { int* m_ptr; } a; int* A::* memPtr = &A::m_ptr; // memPtr is a pointer to member m_ptr of A // memPtr makes nullptr as type of pointer to member m_ptr of A static_assert(std::is_same_v<decltype(false ? memPtr : nullptr), int*A::*>); // a.*memPtr is now just pointer to int and nullptr also becomes pointer to int static_assert(std::is_same_v<decltype(false ? a.*memPtr : nullptr), int*>);
The result type of a conditional operator is also accessible as the binary type trait std::common_type.
(since C++11) [edit] OverloadsFor every pair of promoted arithmetic types L
and R
and for every type P
, where P
is a pointer, pointer-to-member, or scoped enumeration type, the following function signatures participate in overload resolution:
LR operator?:(bool, L, R);
P operator?:(bool, P, P);
where LR is the result of usual arithmetic conversions performed on L
and R
.
The operator â?:
â cannot be overloaded, these function signatures only exist for the purpose of overload resolution.
#include <iostream> #include <string> struct Node { Node* next; int data; // deep-copying copy constructor Node(const Node& other) : next(other.next ? new Node(*other.next) : NULL) , data(other.data) {} Node(int d) : next(NULL), data(d) {} ~Node() { delete next; } }; int main() { // simple rvalue example int n = 1 > 2 ? 10 : 11; // 1 > 2 is false, so n = 11 // simple lvalue example int m = 10; (n == m ? n : m) = 7; // n == m is false, so m = 7 //output the result std::cout << "n = " << n << "\nm = " << m; }
Output:
[edit] Standard libraryMany classes in the standard library overload operator()
to be used as function objects.
std::default_delete<T>
) [edit] returns the sum of two arguments
std::plus<T>
) [edit] returns the difference between two arguments
std::minus<T>
) [edit] returns the product of two arguments
std::multiplies<T>
) [edit] returns the result of the division of the first argument by the second argument
std::divides<T>
) [edit] returns the remainder from the division of the first argument by the second argument
std::modulus<T>
) [edit] returns the negation of the argument
std::negate<T>
) [edit] checks if the arguments are equal
std::equal_to<T>
) [edit] checks if the arguments are not equal
std::not_equal_to<T>
) [edit] checks if the first argument is greater than the second
std::greater<T>
) [edit] checks if the first argument is less than the second
std::less<T>
) [edit] checks if the first argument is greater than or equal to the second
std::greater_equal<T>
) [edit] checks if the first argument is less than or equal to the second
std::less_equal<T>
) [edit] returns the logical AND of the two arguments
std::logical_and<T>
) [edit] returns the logical OR of the two arguments
std::logical_or<T>
) [edit] returns the logical NOT of the argument
std::logical_not<T>
) [edit] returns the result of bitwise AND of two arguments
std::bit_and<T>
) [edit] returns the result of bitwise OR of two arguments
std::bit_or<T>
) [edit] returns the result of bitwise XOR of two arguments
std::bit_xor<T>
) [edit] returns the logical complement of the result of a call to the stored predicate
std::unary_negate<Predicate>
) [edit] returns the logical complement of the result of a call to the stored predicate
std::binary_negate<Predicate>
) [edit] calls the stored function
std::reference_wrapper<T>
) [edit] invokes the target
std::function<R(Args...)>
) [edit] invokes the target
std::move_only_function
) [edit] invokes the target
std::copyable_function
) [edit] resumes execution of the coroutine
std::coroutine_handle<Promise>
) [edit] lexicographically compares two strings using this locale's collate facet
std::locale
) [edit] compares two values of type value_type
std::map<Key,T,Compare,Allocator>::value_compare
) [edit] compares two values of type value_type
std::multimap<Key,T,Compare,Allocator>::value_compare
) [edit] executes the function
std::packaged_task<R(Args...)>
) [edit] advances the engine's state and returns the generated value
std::linear_congruential_engine<UIntType,a,c,m>
) [edit] generates the next random number in the distribution
std::uniform_int_distribution<IntType>
) [edit]
The comma operator is not overloaded by any class in the standard library. The boost library uses operator, in boost.assign, boost.spirit, and other libraries. The database access library SOCI also overloads operator,.
[edit] Defect reportsThe following behavior-changing defect reports were applied retroactively to previously published C++ standards.
DR Applied to Behavior as published Correct behavior CWG 446 C++98 it was unspecified whether a temporary is created for anTX
and TY
are the same class type and TX
is
TY
, an implicit conversion
Operator precedence
Operator overloading
a = b
a += b
a -= b
a *= b
a /= b
a %= b
a &= b
a |= b
a ^= b
a <<= b
a >>= b
++a
--a
a++
a--
+a
-a
a + b
a - b
a * b
a / b
a % b
~a
a & b
a | b
a ^ b
a << b
a >> b
!a
a && b
a || b
a == b
a != b
a < b
a > b
a <= b
a >= b
a <=> b
a[...]
*a
&a
a->b
a.b
a->*b
a.*b
a(...)
commaa, b
conditionala ? b : c
Special operatorsstatic_cast converts one type to another related type
dynamic_cast converts within inheritance hierarchies
const_cast adds or removes cv-qualifiers
reinterpret_cast converts type to unrelated type
C-style cast converts one type to another by a mix of static_cast, const_cast, and reinterpret_cast
new creates objects with dynamic storage duration
delete destructs objects previously created by the new expression and releases obtained memory area
sizeof queries the size of a type
sizeof... queries the size of a pack (since C++11)
typeid queries the type information of a type
noexcept checks if an expression can throw an exception (since C++11)
alignof queries alignment requirements of a type (since C++11)
RetroSearch is an open source project built by @garambo | Open a GitHub Issue
Search and Browse the WWW like it's 1997 | Search results from DuckDuckGo
HTML:
3.2
| Encoding:
UTF-8
| Version:
0.7.4