Function Compliance with parameters of type const T & and T

I have a question regarding C ++ function matching for type parameters T and const T& . Let's say I have the following two functions:

 void f(int i) {} void f(const int &ri) {} 

If I call f with an argument of type const int , then this call is, of course, ambiguous. But why is calling f with an argument of type int also ambiguous? Wouldn't the first version of f be an exact match, and the second would be worse because the int argument must be converted to const int ?

 const int ci = 0; int i = 0; f(ci); // of course ambiguous f(i); // why also ambiguous? 

I know that such an overload does not make much sense, because calls to f almost always ambiguous, unless the parameter type T has an available copy constructor. But I'm just learning the rules for matching functions.

Regards, Kevin

EDIT: Make my question clearer. If I have two functions:

 void f(int *pi) {} void f(const int *pi) {} 

Then the following call is not ambiguous:

 int i = 0; f(&i); // not ambiguous, first version f(int*) chosen 

Although both versions of f can be called using &i , the first version is selected because the second version of f will include the conversion to const. That is, the first version is “the best match.” "But in two functions:

 void f(int i) {} and void f(const int &ri) {} 

This extra conversion to const ignored for some reason. Again, both versions of f can be invoked with int . But then again, the second version of f will require conversion to const , which would make a worse match than the first version of f(int).

 int i = 1; // f(int) requires no conversion // f(const int &) does require a const conversion // so why are both versions treated as "equally good" matches? // isnt this analogous to the f(int*) and f(const int*) example? f(i); // why ambiguous this time? 
+4
source share
3 answers

One call involves “lvalue-to-rvalue conversion”, the other requires identity conversion (for references) or “qualification adjustment” (for pointers), and they are treated the same way when it comes to overload resolution.

enter image description here

Thus, none of them are better based on different transformations.

However, in the standard, section 13.3.3.2, there is a special rule that applies only if both compared candidates accept the parameter by reference.

The standard conversion sequence S1 is a better conversion sequence than the standard conversion sequence S2 , if ... S1 and S2 are binding bindings (8.5.3), and the types to which the links belong are of the same type, with the exception of top-level cv-qualifiers, and the type to which the link initialized by the S2 mark refers is more of a cv qualification than the type to which the link initialized by S1 belongs.

There is the same rule for pointers.

Therefore, the compiler will prefer

 f(int*); f(int&); 

above

 f(const int*); f(const int&); 

respectively, but there is no preference for f(int) vs f(const int) vs f(const int&) , since the lvalue-to-rval transformation and qualification adjustment are considered as "Exact match".


In addition, from section 13.3.3.1.4:

When a reference type parameter is bound directly to the argument expression, the implicit conversion sequence is an identity conversion, unless the expression expression has a type that is a derived class of the parameter type, in which case the implicit conversion sequence is a derived-derived conversion.

+3
source

The second call to f(i) also ambiguous because void f(const int &ri) indicates that ri is a reference to i and is a constant. This means that it will not change the original i , which is passed to this function.

The choice of whether to pass the argument passed or not is in the hands of the executor, not the client programmer, who correctly uses this function.

+1
source

The reason the second call to f (i) is ambiguous is because both functions would be acceptable to the compiler. const-ness cannot be used to overload functions, because different constant versions of functions can be used for one reason. So in your example:

 int i = 0; fi(i); 

How does the compiler know which function you intend to call? The const specifier refers only to the definition of a function.

See overloading the const function for a more detailed explanation.

0
source

Source: https://habr.com/ru/post/1498649/


All Articles