General topics | ||||||||||||||||
Flow control | ||||||||||||||||
Conditional execution statements | ||||||||||||||||
Iteration statements (loops) | ||||||||||||||||
Jump statements | ||||||||||||||||
Functions | ||||||||||||||||
Function declaration | ||||||||||||||||
Lambda function expression | ||||||||||||||||
inline specifier | ||||||||||||||||
Dynamic exception specifications(until C++17*) | ||||||||||||||||
noexcept specifier(C++11) | ||||||||||||||||
Exceptions | ||||||||||||||||
Namespaces | ||||||||||||||||
Types | ||||||||||||||||
Specifiers | ||||||||||||||||
| ||||||||||||||||
Storage duration specifiers | ||||||||||||||||
Initialization | ||||||||||||||||
Expressions | ||||||||||||||||
Alternative representations | ||||||||||||||||
Literals | ||||||||||||||||
Boolean -Integer -Floating-point | ||||||||||||||||
Character -String -nullptr(C++11) | ||||||||||||||||
User-defined(C++11) | ||||||||||||||||
Utilities | ||||||||||||||||
Attributes(C++11) | ||||||||||||||||
Types | ||||||||||||||||
typedef declaration | ||||||||||||||||
Type alias declaration(C++11) | ||||||||||||||||
Casts | ||||||||||||||||
Memory allocation | ||||||||||||||||
Classes | ||||||||||||||||
Class-specific function properties | ||||||||||||||||
| ||||||||||||||||
Special member functions | ||||||||||||||||
Templates | ||||||||||||||||
Miscellaneous | ||||||||||||||||
Declarations | ||||
Function declaration | ||||
Function parameter list | ||||
Function definition | ||||
Function contract specifiers(C++26) | ||||
Default arguments | ||||
Variadic arguments | ||||
inline specifier | ||||
Lambda expressions(C++11) | ||||
Coroutines(C++20) | ||||
Replacement functions | ||||
Function calls | ||||
Argument-Dependent Lookup (ADL) | ||||
Function-call operator | ||||
Function objects | ||||
Overloading | ||||
Overload resolution | ||||
Operator overloading | ||||
Address of an overload set |
In order to compile a function call, the compiler must first performname lookup, which, for functions, may involveargument-dependent lookup, and for function templates may be followed bytemplate argument deduction.
If the name refers to more than one entity, it is said to beoverloaded, and the compiler must determine which overload to call. In simple terms, the overload whose parameters match the arguments most closely is the one that is called.
In detail, overload resolution proceeds through the following steps:
void f(long);void f(float); f(0L);// calls f(long)f(0);// error: ambiguous overload
Besides function calls, overloaded function names may appear in several additional contexts, where different rules apply: seeAddress of an overloaded function.
If a function cannot be selected by overload resolution, it cannot be used (e.g. it is atemplated entity with a failedconstraint).
Before overload resolution begins, the functions selected by name lookup and template argument deduction are combined to form the set ofcandidate functions. The exact details depend on the context in which overload resolution will take place.
IfE in afunction call expressionE(args) names a set of overloaded functions and/or function templates (but not callable objects), the following rules are followed:
T
), thenB islooked up as a member function ofT
. The function declarations found by that lookup are the candidate functions. The argument list for the purpose of overload resolution has the implied object argument of typecvT
.T
, in which case, ifthis is in scope and is a pointer toT
or to a derived class ofT
,*this is used as the implied object argument. Otherwise (ifthis is not in scope or does not point toT
), a fake object of typeT
is used as the implied object argument, and if overload resolution subsequently selects a non-static member function, the program is ill-formed.IfE in afunction call expressionE(args) has class typecvT
, then
T
are obtained by ordinarylookup of the nameoperator() in the context of the expression(E).operator(), and every declaration found is added to the set of candidate functions.explicit
user-defined conversion function inT
or in a base ofT
(unless hidden), whose cv-qualifiers are the same or greater thanT
's cv-qualifiers, and where the conversion function converts to:In any case, the argument list for the purpose of overload resolution is the argument list of the function call expression preceded by the implied object argumentE (when matching against the surrogate function, the user-defined conversion will automatically convert the implied object argument to the first argument of the surrogate function).
int f1(int);int f2(float); struct A{using fp1=int(*)(int); operator fp1(){return f1;}// conversion function to pointer to functionusing fp2=int(*)(float); operator fp2(){return f2;}// conversion function to pointer to function} a; int i= a(1);// calls f1 via pointer returned from conversion function
If at least one of the arguments to an operator in an expression has a class type or an enumeration type, bothbuiltin operators anduser-defined operator overloads participate in overload resolution, with the set of candidate functions selected as follows:
For a unary operator@
whose argument has typeT1
(after removing cv-qualifications), or binary operator@
whose left operand has typeT1
and right operand of typeT2
(after removing cv-qualifications), the following sets of candidate functions are prepared:
T1
is a complete class or a class currently being defined, the set of member candidates is the result ofqualified name lookup ofT1::operator@
. In all other cases, the set of member candidates is empty.operator@
in the context of the expression (which may involveADL), except that member function declarations are ignored and do not prevent the lookup from continuing into the next enclosing scope. If both operands of a binary operator or the only operand of a unary operator has enumeration type, the only functions from the lookup set that become non-member candidates are the ones whose parameter has that enumeration type (or reference to that enumeration type)4)rewritten candidates:
In all cases, rewritten candidates are not considered in the context of the rewritten expression. For all other operators, the rewritten candidate set is empty. | (since C++20) |
The set of candidate functions to be submitted for overload resolution is a union of the sets above. The argument list for the purpose of overload resolution consists of the operands of the operator except foroperator->
, where the second operand is not an argument for the function call (seemember access operator).
struct A{ operatorint();// user-defined conversion};A operator+(const A&,const A&);// non-member user-defined operator void m(){ A a, b; a+ b;// member-candidates: none// non-member candidates: operator+(a, b)// built-in candidates: int(a) + int(b)// overload resolution chooses operator+(a, b)}
If the overload resolution selects a built-in candidate, theuser-defined conversion sequence from an operand of class type is not allowed to have a second standard conversion sequence: the user-defined conversion function must give the expected operand type directly:
struct Y{ operatorint*();};// Y is convertible to int*int*a= Y()+100.0;// error: no operator+ between pointer and double
Foroperator,, the unaryoperator&, andoperator->, if there are no viable functions (see below) in the set of candidate functions, then the operator is reinterpreted as a built-in.
If a rewrittenoperator<=> candidate is selected by overload resolution for an operator If a rewrittenoperator== candidate is selected by overload resolution for an operator Overload resolution in this case has a final tiebreaker preferring non-rewritten candidates to rewritten candidates, and preferring non-synthesized rewritten candidates to synthesized rewritten candidates. This lookup with the reversed arguments order makes it possible to write justoperator<=>(std::string,constchar*) andoperator==(std::string,constchar*) to generate all comparisons betweenstd::string andconstchar*, both ways. Seedefault comparisons for more detail. | (since C++20) |
When an object of class type isdirect-initialized ordefault-initialized (including default-initialization in the context ofcopy-list-initialization)(since C++11), the candidate functions are all constructors of the class being initialized. The argument list is the expression list of the initializer.
Otherwise, the candidate functions are allconverting constructors of the class being initialized. The argument list is the expression of the initializer.
For default-initialization in the context of copy-list-initialization, if an | (since C++11) |
Ifcopy-initialization of an object of class type requires that a user-defined conversion is called to convert the initializer expression of typecvS
to the typecvT
of the object being initialized, the following functions are candidate functions:
T
explicit
conversion functions fromS
and its base classes (unless hidden) toT
or class derived fromT
or a reference to such. If this copy-initialization is part of the direct-initialization sequence ofcvT
(initializing a reference to be bound to the first parameter of a constructor that takes a reference tocvT
), then explicit conversion functions are also considered.Either way, the argument list for the purpose of overload resolution consists of a single argument which is the initializer expression, which will be compared against the first argument of the constructor or against the implicit object argument of the conversion function.
When initialization of an object of non-class typecv1T
requires auser-defined conversion function to convert from an initializer expression of class typecvS
, the following functions are candidates:
S
and its base classes (unless hidden) that produce typeT
or a type convertible toT
by astandard conversion sequence, or a reference to such type. cv-qualifiers on the returned type are ignored for the purpose of selecting candidate functions.S
and its base classes (unless hidden) that produce typeT
or a type convertible toT
by aqualification conversion, or a reference to such type, are also considered.Either way, the argument list for the purpose of overload resolution consists of a single argument which is the initializer expression, which will be compared against the implicit object argument of the conversion function.
Duringreference initialization, where the reference tocv1T
is bound to the lvalue or rvalue result of a conversion from the initializer expression from the class typecv2S
, the following functions are selected for the candidate set:
S
and its base classes (unless hidden) to the typeT2
T2
or rvalue reference tocv2T2
T2
isreference-compatible withcv1T
.T2
is the same type asT
or can be converted to typeT
with a qualification conversion.Either way, the argument list for the purpose of overload resolution consists of a single argument which is the initializer expression, which will be compared against the implicit object argument of the conversion function.
When an object of non-aggregate class typeT
islist-initialized, two-phase overload resolution takes place.
T
and the argument list for the purpose of overload resolution consists of a single initializer list argumentT
and the argument list for the purpose of overload resolution consists of the individual elements of the initializer list.If the initializer list is empty andT
has a default constructor, phase 1 is skipped.
In copy-list-initialization, if phase 2 selects an explicit constructor, the initialization is ill-formed (as opposed to all over copy-initializations where explicit constructors are not even considered).
If name lookup found a function template,template argument deduction and checking of any explicit template arguments are performed to find the template argument values (if any) that can be used in this case:
If a name refers to one or more function templates and also to a set of overloaded non-template functions, those functions and the specializations generated from the templates are all candidates.
Seefunction template overloading for further detail.
If a constructor template or conversion function template has aconditional explicit specifier which happens to bevalue-dependent, after deduction, if the context requires a candidate that is not explicit and the generated specialization is explicit, it is removed from the candidate set. | (since C++20) |
Defaultedmove constructors andmove assignment operators that are defined as deleted are excluded in the set of candidate functions. A constructorinherited from class type
| (since C++11) |
If any candidate function is amember function (static or non-static) that does not have anexplicit object parameter(since C++23), but not a constructor, it is treated as if it has an extra parameter (implicit object parameter) which represents the object for which they are called and appears before the first of the actual parameters.
Similarly, the object on which a member function is being called is prepended to the argument list as theimplied object argument.
For member functions of classX
, the type of the implicit object parameter is affected by cv-qualifications and ref-qualifications of the member function as described inmember functions.
The user-defined conversion functions are considered to be members of theimplied object argument for the purpose of determining the type of theimplicit object parameter.
The member functions introduced by a using-declaration into a derived class are considered to be members of the derived class for the purpose of defining the type of theimplicitobject parameter.
For the static member functions, theimplicit object parameter is considered to match any object: its type is not examined and no conversion sequence is attempted for it. | (until C++23) |
For the rest of overload resolution, theimplied object argument is indistinguishable from other arguments, but the following special rules apply to theimplicit object parameter:
struct B{void f(int);};struct A{ operator B&();}; A a;a.B::f(1);// Error: user-defined conversions cannot be applied// to the implicit object parameterstatic_cast<B&>(a).f(1);// OK
Given the set of candidate functions, constructed as described above, the next step of overload resolution is examining arguments and parameters to reduce the set to the set ofviable functions
To be included in the set of viable functions, the candidate function must satisfy the following:
M
arguments, the candidate function that has exactlyM
parameters is viableM
parameters and theM+1
'st parameter and all parameters that follow have default arguments, it is viable. For the rest of overload resolution, the parameter list is truncated atM
.4) If the function has an associatedconstraint, it must be satisfied | (since C++20) |
User-defined conversions (both converting constructors and user-defined conversion functions) are prohibited from taking part in implicit conversion sequence where it would make it possible to apply more than one user-defined conversion. Specifically, they are not considered if the target of the conversion is the first parameter of a constructor or the implicit object parameter of a user-defined conversion function, and that constructor/user-defined conversion is a candidate for
struct A{ A(int);};struct B{ B(A);}; B b{{0}};// list-initialization of B // candidates: B(const B&), B(B&&), B(A)// {0} -> B&& not viable: would have to call B(A)// {0} -> const B&: not viable: would have to bind to rvalue, would have to call B(A)// {0} -> A viable. Calls A(int): user-defined conversion to A is not banned | (since C++11) |
For each pair of viable functionF1
andF2
, the implicit conversion sequences from thei
th argument toi
th parameter are ranked to determine which one is better (except the first argument, theimplicit object argument for static member functions has no effect on the ranking)
F1
is determined to be a better function thanF2
if implicit conversions for all arguments ofF1
arenot worse than the implicit conversions for all arguments of F2, and
F1
whose implicit conversion isbetter than the corresponding implicit conversion for that argument ofF2
, or, if not that,F1
to the type being initialized isbetter than the standard conversion sequence from the result ofF2
, or, if not that,3) (only in context of initialization by conversion function for direct reference binding of a reference to function type), the result of F1 is the same kind of reference (lvalue or rvalue) as the reference being initialized, and the result ofF2 is not, or, if not that, | (since C++11) |
F1
is a non-template function whileF2
is a template specialization, or, if not that,F1
andF2
are both template specializations andF1
is more specialized according to thepartial ordering rules for template specializations, or, if not that,6) F1 andF2 are non-template functions andF1 ismore partial-ordering-constrained thanF2 :template<typename T=int>struct S{constexprvoid f();// #1constexprvoid f(this S&) requirestrue;// #2}; void test(){ S<> s; s.f();// calls #2} , or, if not that, | (since C++20) |
7) F1 is a constructor for a classD ,F2 is a constructor for a base classB ofD , and for all arguments the corresponding parameters ofF1 andF2 have the same type:struct A{ A(int=0);}; struct B: A{using A::A; B();}; B b;// OK, B::B() , or, if not that, | (since C++11) |
8) F2 is a rewritten candidate andF1 is not, or, if not that,9) F1 andF2 are both rewritten candidates, andF2 is a synthesized rewritten candidate with reversed order of parameters andF1 is not, or, if not that, | (since C++20) |
12) F1 is generated from a non-template constructor andF2 is generated from a constructor template:template<class T>struct A{using value_type= T; A(value_type);// #1 A(const A&);// #2 A(T, T,int);// #3 template<class U> A(int, T, U);// #4};// #5 is A(A), the copy deduction candidate A x(1,2,3);// uses #3, generated from a non-template constructor template<class T>A(T)-> A<T>;// #6, less specialized than #5 A a(42);// uses #6 to deduce A<int> and #1 to initializeA b= a;// uses #5 to deduce A<int> and #2 to initialize template<class T>A(A<T>)-> A<A<T>>;// #7, as specialized as #5A b2= a;// uses #7 to deduce A<A<int>> and #1 to initialize | (since C++17) |
These pair-wise comparisons are applied to all viable functions. If exactly one viable function is better than all others, overload resolution succeeds and this function is called. Otherwise, compilation fails.
void Fcn(constint*,short);// overload #1void Fcn(int*,int);// overload #2 int i;short s=0; void f(){ Fcn(&i,1L);// 1st argument: &i -> int* is better than &i -> const int*// 2nd argument: 1L -> short and 1L -> int are equivalent// calls Fcn(int*, int) Fcn(&i,'c');// 1st argument: &i -> int* is better than &i -> const int*// 2nd argument: 'c' -> int is better than 'c' -> short// calls Fcn(int*, int) Fcn(&i, s);// 1st argument: &i -> int* is better than &i -> const int*// 2nd argument: s -> short is better than s -> int// no winner, compilation error}
If the best viable function resolves to a function for which multiple declarations were found, and if any two of these declarations inhabit different scopes and specify a default argument that made the function viable, the program is ill-formed.
namespace A{extern"C"void f(int=5);} namespace B{extern"C"void f(int=5);} using A::f;using B::f; void use(){ f(3);// OK, default argument was not used for viability f();// error: found default argument twice}
The argument-parameter implicit conversion sequences considered by overload resolution correspond toimplicit conversions used incopy initialization (for non-reference parameters), except that when considering conversion to the implicit object parameter or to the left-hand side of assignment operator, conversions that create temporary objects are not considered.When the parameter is the implicit object parameter of a static member function, the implicit conversion sequence is a standard conversion sequence that is neither better nor worse than any other standard conversion sequence.(since C++23)
Eachtype of standard conversion sequence is assigned one of three ranks:
The rank of the standard conversion sequence is the worst of the ranks of the standard conversions it holds (there may be up tothree conversions)
Binding of a reference parameter directly to the argument expression is either identity or a derived-to-base conversion:
struct Base{};struct Derived: Base{} d; int f(Base&);// overload #1int f(Derived&);// overload #2 int i= f(d);// d -> Derived& has rank Exact Match// d -> Base& has rank Conversion// calls f(Derived&)
Since ranking of conversion sequences operates with types and value categories only, abit field can bind to a reference argument for the purpose of ranking, but if that function gets selected, it will be ill-formed.
S1
isbetter than a standard conversion sequenceS2
ifS1
is a proper subsequence ofS2
, excluding lvalue transformations; the identity conversion sequence is considered a subsequence of any non-identity conversion, or, if not that,S1
is better than the rank ofS2
, or, if not that,S1
andS2
are binding to a reference parameter to something other than the implicit object parameter of a ref-qualified member function, andS1
binds an rvalue reference to an rvalue whileS2
binds an lvalue reference to an rvalue:int i;int f1(); int g(constint&);// overload #1int g(constint&&);// overload #2 int j= g(i);// lvalue int -> const int& is the only valid conversionint k= g(f1());// rvalue int -> const int&& better than rvalue int -> const int&
S1
andS2
are binding to a reference parameter andS1
binds an lvalue reference to function whileS2
binds an rvalue reference to function:int f(void(&)());// overload #1int f(void(&&)());// overload #2 void g();int i1= f(g);// calls #1
S1
andS2
only differ in qualification conversion, andthe cv-qualification of the result of | (until C++20) |
the result of | (since C++20) |
int f(constint*);int f(int*); int i;int j= f(&i);// &i -> int* is better than &i -> const int*, calls f(int*)
S1
andS2
are binding to a reference parameters only different in top-level cv-qualification, andS1
's type isless cv-qualified thanS2
's:int f(constint&);// overload #1int f(int&);// overload #2 (both references) int g(constint&);// overload #1int g(int);// overload #2 int i;int j= f(i);// lvalue i -> int& is better than lvalue int -> const int&// calls f(int&)int k= g(i);// lvalue i -> const int& ranks Exact Match// lvalue i -> rvalue int ranks Exact Match// ambiguous overload: compilation error
S1
andS2
bind the same reference type “reference toT
” and have source typesV1
andV2
, respectively, where the standard conversion sequence fromV1* toT* is better than the standard conversion sequence fromV2* toT*:struct Z{}; struct A{ operator Z&(); operatorconst Z&();// overload #1}; struct B{ operator Z(); operatorconst Z&&();// overload #2}; const Z& r1= A();// OK, uses #1const Z&& r2= B();// OK, uses #2
U1
isbetter than a user-defined conversion sequenceU2
if they call the same constructor/user-defined conversion function or initialize the same class with aggregate-initialization, and in either case the second standard conversion sequence inU1
is better than the second standard conversion sequence inU2
struct A{ operatorshort();// user-defined conversion function} a; int f(int);// overload #1int f(float);// overload #2 int i= f(a);// A -> short, followed by short -> int (rank Promotion)// A -> short, followed by short -> float (rank Conversion)// calls f(int)
L1
isbetter than list-initialization sequenceL2
ifL1
initializes anstd::initializer_list parameter, whileL2
does not.void f1(int);// #1void f1(std::initializer_list<long>);// #2void g1(){ f1({42});}// chooses #2 void f2(std::pair<constchar*,constchar*>);// #3void f2(std::initializer_list<std::string>);// #4void g2(){ f2({"foo","bar"});}// chooses #4
6) A list-initialization sequence L1 isbetter than list-initialization sequenceL2 if the corresponding parameters are references to arrays, and L1 converts to type “array of N1 T”, L2 converts to “array of N2 T”, and N1 is smaller than N2. | (since C++11) (until C++20) |
6) A list-initialization sequence L1 isbetter than list-initialization sequenceL2 if the corresponding parameters are references to arrays, and L1 and L2 convert to arrays of same element type, and either
void f(int(&&)[]);// overload #1void f(double(&&)[]);// overload #2void f(int(&&)[2]);// overload #3 f({1});// #1: Better than #2 due to conversion, better than #3 due to boundsf({1.0});// #2: double -> double is better than double -> intf({1.0,2.0});// #2: double -> double is better than double -> intf({1,2});// #3: -> int[2] is better than -> int[],// and int -> int is better than int -> double | (since C++20) |
If two conversion sequences are indistinguishable because they have the same rank, the following additional rules apply:
2) Conversion that promotes anenumeration whose underlying type is fixed to its underlying type is better than one that promotes to the promoted underlying type, if the two types are different. enum num:char{ one='0'};std::cout<< num::one;// '0', not 48 | (since C++11) |
3) A conversion in either direction between floating-point type FP1 and floating-point typeFP2 is better than a conversion in the same direction betweenFP1 and arithmetic typeT3 if
int f(std::float32_t);int f(std::float64_t);int f(longlong); float x;std::float16_t y; int i= f(x);// calls f(std::float32_t) on implementations where// float and std::float32_t have equal conversion ranksint j= f(y);// error: ambiguous, no equal conversion rank | (since C++23) |
Mid
is derived (directly or indirectly) fromBase
, andDerived
is derived (directly or indirectly) fromMid
Derived
toMid& orMid&& is better thanDerived
toBase& orBase&&Derived
toMid
is better thanDerived
toBase
Mid
toBase& orBase&& is better thanDerived
toBase& orBase&&Mid
toBase
is better thanDerived
toBase
Ambiguous conversion sequences are ranked as user-defined conversion sequences because multiple conversion sequences for an argument can exist only if they involve different user-defined conversions:
class B; class A{ A(B&);};// converting constructorclass B{ operator A();};// user-defined conversion functionclass C{ C(B&);};// converting constructor void f(A){}// overload #1void f(C){}// overload #2 B b;f(b);// B -> A via ctor or B -> A via function (ambiguous conversion)// b -> C via ctor (user-defined conversion)// the conversions for overload #1 and for overload #2// are indistinguishable; compilation fails
Inlist initialization, the argument is abraced-init-list, which isn't an expression, so the implicit conversion sequence into the parameter type for the purpose of overload resolution is decided by the following special rules:
X
and the initializer list consists of exactly one element of same or derived class (possibly cv-qualified), the implicit conversion sequence is the one required to convert the element to the parameter type.X
, the implicit conversion sequence for the purpose of overload resolution is the worst conversion necessary. If the braced-init-list is empty, the conversion sequence is the identity conversion.struct A{ A(std::initializer_list<double>);// #1 A(std::initializer_list<complex<double>>);// #2 A(std::initializer_list<std::string>);// #3};A a{1.0,2.0};// selects #1 (rvalue double -> double: identity conv) void g(A);g({"foo","bar"});// selects #3 (lvalue const char[4] -> std::string: user-def conv)
{}
if the list is shorter than N) toT
is the one used.
| (since C++20) |
typedefint IA[3]; void h(const IA&);void g(int(&&)[]); h({1,2,3});// int->int identity conversiong({1,2,3});// same as above since C++20
X
, overload resolution picks the constructor C of X to initialize from the argument initializer listIf multiple constructors are viable but none is better than the others, the implicit conversion sequence is the ambiguous conversion sequence.
struct A{ A(std::initializer_list<int>);};void f(A); struct B{ B(int,double);};void g(B); g({'a','b'});// calls g(B(int, double)), user-defined conversion// g({1.0, 1,0}); // error: double->int is narrowing, not allowed in list-init void f(B);// f({'a', 'b'}); // f(A) and f(B) both user-defined conversions
struct A{int m1;double m2;}; void f(A);f({'a','b'});// calls f(A(int, double)), user-defined conversion
struct A{int m1;double m2;}; void f(const A&);f({'a','b'});// temporary created, f(A(int, double)) called. User-defined conversion
If the argument is a designated initializer list and the parameter is not a reference, a conversion is only possible if the parameter has an aggregate type that can be initialized from that initializer list according to the rules foraggregate initialization, in which case the implicit conversion sequence is a user-defined conversion sequence whose second standard conversion sequence is an identity conversion. If, after overload resolution, the order of declaration of the aggregate's members does not match for the selected overload, the initialization of the parameter will be ill-formed. struct A{int x, y;};struct B{int y, x;}; void f(A a,int);// #1void f(B b, ...);// #2void g(A a);// #3void g(B b);// #4 void h(){ f({.x=1, .y=2},0);// OK; calls #1 f({.y=2, .x=1},0);// error: selects #1, initialization of a fails// due to non-matching member order g({.x=1, .y=2});// error: ambiguous between #3 and #4} | (since C++20) |
The following behavior-changing defect reports were applied retroactively to previously published C++ standards.
DR | Applied to | Behavior as published | Correct behavior |
---|---|---|---|
CWG 1 | C++98 | the behavior was unspecified when the same function with possibly different default arguments (from different scopes) is selected | the program is ill- formed in this case |
CWG 83 | C++98 | the conversion sequence from a string literal tochar* was better than that toconstchar* even though the former is deprecated | the rank of the deprecated conversion is lowered (it was removed in C++11) |
CWG 162 | C++98 | it was invalid if the overload set named byF containsa non-static member function in the case of &F(args) | only invalid if overload resolution selects a non-static member function in this case |
CWG 233 | C++98 | references and pointers were handled inconsistently in overloading resolution with user defined conversions | they are handled consistently |
CWG 280 | C++98 | surrogate call functions were not added to the set of candidate functions for conversion functions declared in inaccessible base classes | removed the accessibility constraint, the program is ill-formed if a surrogate call function is selected and the corresponding conversion function cannot be called |
CWG 415 | C++98 | when a function template is selected as a candidate, its specializations were instantiated using template argument deduction | no instantiation will occur in this case, their declarations will be synthesized |
CWG 495 | C++98 | when the implicit conversions for arguments are equally good, a non-template conversion function was always better than a conversion function template, even if the latter may have a better standard conversion sequence | standard conversion sequences are compared before specialization levels |
CWG 1307 | C++11 | overload resolution based on size of arrays was not specified | a shorter array is better when possible |
CWG 1328 | C++11 | the determination of the candidate functions when binding a reference to a conversion result was not clear | made clear |
CWG 1374 | C++98 | qualification conversion was checked before reference binding when comparing standard conversion sequences | reversed |
CWG 1385 | C++11 | a non-explicit user-defined conversion function declared with a ref-qualifier did not have a corresponding surrogate function | it has a corresponding surrogate function |
CWG 1467 | C++11 | same-type list-initialization of aggregates and arrays was omitted | initialization defined |
CWG 1601 | C++11 | conversion from enum to its underlying type did not prefer the fixed underlying type | fixed type is preferred to what it promotes to |
CWG 1608 | C++98 | the set of member candidates of a unary operator@ whose argument has type T1 was empty ifT1 is a class currently being defined | the set is the result of qualified name lookup of T1::operator@ in this case |
CWG 1687 | C++98 | when a built-in candidate is selected by overload resolution, the operands would undergo conversion without restriction | only convert class type operands, and disabled the second standard conversion sequence |
CWG 2052 | C++98 | ill-formed synthesized function template specializations could be added to the candidate set, making the program ill-formed | they are not added to the candidate set |
CWG 2076 | C++11 | user-defined conversion is applied to the single initializer in a nested initializer list during list-initialization due to the resolution ofCWG issue 1467 | not applied |
CWG 2137 | C++11 | initializer list constructors lost to copy constructors when list-initializing X from{X} | non-aggregates consider initializer lists first |
CWG 2273 | C++11 | there was no tiebreaker between inherited and non-inherited constructors | non-inherited constructor wins |
CWG 2673 | C++20 | built-in candidates with the same parameter list as a rewritten non-member candidate were added to the list of built-in candidates | not added |
CWG 2712 | C++98 | when a built-in assignment operator is considered, the first parameter could not bound to a temporary, which is already impossible[1] | removed the redundant requirement |
CWG 2713 | C++20 | the conversion restriction regarding designated initializer lists was applied even if the parameter is a reference | not restricted in this case |
CWG 2789 | C++23 | the explicit object parameter was included when comparing parameter-type-lists | excluded |
CWG 2856 | C++11 | the overload resolution for default-initialization in the context of copy-list-initialization only considered converting constructor | considers all constructors |
CWG 2919 | C++98 | the candidate set of reference initialization by conversion depended on the target type of the initialization | depends on the target type of the conversion |
P2468R2 | C++20 | rewritten candidates based onoperator== are added fora!= b even if a matchingoperator!= exists | not added |
T
”. References of this type cannot bound to a temporary.