Overload resolution and arrays: which function should be called?
First, the conversion sequence of all three is the same, except that for the first two, there is an lvalue transformation (lvalue to rvalue conversion), which however is not used in ordering conversion sequences. All three are exact matches (the function template specialization has parameter type char const(&)[2]
).
If you iterate over the rules at 13.3.3.2p3
, you stop at this paragraph
S1 and S2 are reference bindings (8.5.3) and neither refers to an implicit object parameter of a non-static member function declared without a ref-qualifier, and S1 binds an rvalue reference to an rvalue and S2 binds an lvalue reference.
A conversion sequence cannot be formed if it requires binding an rvalue reference to an lvalue, the spec says at 13.3.3.1.4p3. If you look at how reference binding works at 8.5.3p5 last bullet, it will create a temporary (I think they meant rvalue temporary) of type char const*
from the array lvalue and bind the reference to that temporary. Therefor, I think (1)
is better than (2)
. Same holds for (1)
against (3)
, although we wouldn't need this because (3)
is a template so in a tie, we would choose (1)
again.
In n3225
, they changed the reference binding rules so that rvalue references can bind to initializer expressions that are lvalues, as long as the reference will be bound to an rvalue (possibly created by converting the initializer properly before). This could influence the handling by Visual C++, which may not be up to date here.
I'm not sure about clang. Even if it would ignore (1)
, then it would end up in a tie between (2)
and (3)
, and would need to choose (2)
because it's a non-template.
I think that 8.5.3p5 last bullet is confusing because it says "Otherwise a temporary of type ..". It's not clear whether the temporary is regarded as an lvalue or as an rvalue by 13.3.3.1.4p3, which means I'm not sure how the following should really behave according to the exact words of the spec
void f(int &);
void f(int &&);
int main() {
int n = 0;
f(n);
}
If we assume the temporary is treated as an rvalue by clause 13, then we bind an rvalue ref to an rvalue in the second function and an lvalue in the first. Therefor, we will choose the second function and then get a diagnostic by 8.5.3p5 last bullet because T1
and T2
are reference-related. If we assume the temporary is treated as an lvalue by clause 13, then the following would not work
void f(int &&);
int main() {
f(0);
}
Because we would bind an rvalue ref to an lvalue which by clause 13 will make the function non-viable. And if we interpret "binding an rvalue ref to an lvalue" to refer to the initializer expression instead of the final expression bound to, we won't accept the following
void f(float &&);
int main() {
int n = 0;
f(n);
}
This however is valid as of n3225. So there seems to be some confusion - I sent a DR to the committee about this.
What part of overload resolution (or more generally of the function call processing) does the value category of the argument play a role in?
why the value category is not mentioned at all in the points above?
It is mentioned in the book as can be seen as quoted below. In particular, if you continue reading further then you'll see that the section C.2.2 titled Refining the Perfect Match does mention the part about distinguishing between different perfect matches:
With the addition of rvalue references in C++11, another common case of two perfect matches needing to be distinguished is illustrated by the following example:
struct Value {
...
};
void pass(Value const&); // #1
void pass(Value&&);// #2
void g(X&& x)
{
pass(x); // calls #1 , because x is an lvalue
pass(X()); // calls #2 , because X() is an rvalue (in fact, prvalue)
pass(std::move(x)); // calls #2 , because std::move(x) is an rvalue (in fact, xvalue)
}This time, the version taking an rvalue reference is considered a better match for RVALUES, but it cannot match lvalues.
Note the bold part in the above quoted example.
Similarly, it even has the following example:
void report(int&); // #1
void report(int const&); // #2
int main()
{
for (int k = 0; k<10; ++k) {
report(k); // calls #1
}
report(42); // calls #2
}Here, the version without the extra const is preferred for LVALUES, whereas only the version with const can match RVALUES.
Overload resolution and array-to-pointer decay - why is int (&a)[2] and int* a considered equally exact regarding overload resolution
@463035818_is_not_a_number already explained in their answer why void foo(int* a);
is a better match than template<std::size_t N> void foo(int (&a)[N])
.
This answer only applies to the second example in the question:
void foo(int (&a)[2]);
void foo(int* a);
// why is this call ambiguous?
int arr[2];
foo(arr);
1. Finding the best matching function
Both functions can be found by name lookup, are candidate functions and viable functions.
So which function will be called (or if the call is ambiguous) is based on wether any of them is a better viable function than the other.
As per 12.4.3 Best viable function [over.match.best] (2):
(2) Given these definitions, a viable function F1 is defined to be a better function than another viable function F2 if for all arguments i, ICSi(F1) is not a worse conversion sequence than ICSi(F2), and then
[...]
(2.1) for some argument j, ICSj(F1) is a better conversion sequence than ICSj(F2), [...]
So to determine if any of the two functions is better we need to check the conversion sequences of their arguments and compare them.
2. Comparing the conversion sequences
2.1 Required conversion sequences
Let's first determine which conversion sequences we need for both calls:
void foo(int (&a)[2]);
only requires the identity conversion sequence, as per 12.4.3.1.4 Reference binding [over.ics.ref] (1):(1) When a parameter of reference type binds directly to an argument expression, the implicit conversion sequence is the identity conversion [...]
void foo(int* a);
requires a conversion sequence consisting of an Array-to-pointer conversion conversion, as per 7.3.2 Array-to-pointer conversion [conv.array] (1):(1) An lvalue or rvalue of type “array of N T” or “array of unknown bound of T” can be converted to a prvalue of type “pointer to T”. [...]
2.2 Which conversion sequence is better?
To determine which conversion sequence is better we need to reference 12.4.3.2 Ranking implicit conversion sequences [over.ics.rank] - in this case mainly paragraph (3) and (4).
(1) This subclause defines a partial ordering of implicit conversion sequences based on the relationships better conversion sequence and better conversion. If an implicit conversion sequence S1 is defined by these rules to be a better conversion sequence than S2, then it is also the case that S2 is a worse conversion sequence than S1. If conversion sequence S1 is neither better than nor worse than conversion sequence S2, S1 and S2 are said to be indistinguishable conversion sequences.
2.3 Is one of the conversion sequences a subsequence of the other?
Note: we'll skip (3.1) because it only applies to list-initialization.
So let's start with the first condition, (3.2.1):
(3.2) Standard conversion sequence S1 is a better conversion sequence than standard conversion sequence S2 if:
- (3.2.1) S1 is a proper subsequence of S2 (comparing the conversion sequences in the canonical form defined by [over.ics.scs], excluding any Lvalue Transformation; the identity conversion sequence is considered to be a subsequence of any non-identity conversion sequence) or, if not that, [...]
Note: Due to questions about this clause in the comments i'll explain this rule in detail.
tl;dr: Neither conversion sequence is a subsequence of the other.
To fully understand this rule we need to first define a few terms:
- sequence (as in standard conversion sequence) refers to a mathematical sequence; in essence a sequence in maths is a set with the additional constraints that the order of elements matters and repetition of elements is allowed.
- proper subsequence (or strict subsequence)
Given SequencesA
andB
, ifA
is a subsequence ofB
, andA
is not equal toB
, thenA
is a proper subsequence ofB
. ()
(see subset / proper subset - it's the same for sequences)
A few examples to illustrate the principle:(A, B)
is a proper subsequence of(A, B, C, D)
(we can remove elements)(B, C)
is a proper subsequence of(A, B, C, D)
(removing is allowed at any position)(A, B, C)
is not a proper subsequence of(A, C, B, D)
(order matters)(A)
is not a proper subsequence of(A)
(if both sequences are equal, neither is a proper subsequence of the other)()
is a proper subsequence of(A, B, C)
(the empty sequence is a proper subsequence of all non-empty sequences)
- identity (as in identity conversion / identity conversion sequence) refers to the mathematical identity element (often shortened to just indentity)
- The terms identity conversion & identity conversion sequence in this case refers to an empty sequence of conversions (
()
) - applying no conversions to a value always results in the original value:value ∘ () = value
- The terms identity conversion & identity conversion sequence in this case refers to an empty sequence of conversions (
So with this we can break down the (3.2.1)
rule:
comparing the conversion sequences in the canonical form defined by [over.ics.scs], excluding any Lvalue Transformation
- [over.ics.scs] describes the way we need to order the conversions (if we have more than one) - because remember ordering does matter for sequences.
- If a conversion sequence contains a Lvalue Transformation we need to remove it before checking for proper subsequences.
the identity conversion sequence is considered to be a subsequence of any non-identity conversion sequence
- This is a roundabout way of saying that an empty conversion sequence is considered a subsequence of any non-empty conversion sequence (one of the rules for proper subsequences).
Standard conversion sequence S1 is a better conversion sequence than standard conversion sequence S2 if:
- S1 is a proper subsequence of S2
- So we need to check if S1 is a proper subsequence of S2, and if it is then S1 is better than S2
So now let's apply this to our specific case:
- We have sequence S1 for
foo(int (&a)[2])
:()
(identity conversion sequence) - and sequence S2 for
foo(int* a);
:("Array-to-pointer conversion")
Now we need to remove Lvalue-conversions.
In 12.4.3.1.1 Standard conversion sequences [over.ics.scs] (3) Array-to-pointer conversion is listed as an Lvalue-conversion, therefore we must remove it from S2.
So S2 = ()
Now we need to check if S1 is a proper subsequence of S2.
It can't be a proper subsequence because S1 = S2, therefore this rule does not apply.
2.4 ranking the conversion sequences
Next we need to check the rank of the conversion sequences as per (3.2.2)
(3.2.2) the rank of S1 is better than the rank of S2, or S1 and S2 have the same rank and are distinguishable by the rules in the paragraph below, or, if not that,
There are three possible ranks for conversions: Exact Match, Promotion or Conversion, as per 12.4.3.1.1 Standard conversion sequences [over.ics.scs] (3):
(3) Each conversion [...] also has an associated rank (Exact Match, Promotion, or Conversion). These are used to rank standard conversion sequences. The rank of a conversion sequence is determined by considering the rank of each conversion in the sequence and the rank of any reference binding. If any of those has Conversion rank, the sequence has Conversion rank; otherwise, if any of those has Promotion rank, the sequence has Promotion rank; otherwise, the sequence has Exact Match rank.
Conversion Category Rank No conversions required Identity Exact Match Lvalue-to-rvalue conversion Lvalue Transformation Exact Match Array-to-pointer conversion Lvalue Transformation Exact Match Function-to-pointer conversion Lvalue Transformation Exact Match Qualification conversions Qualification Adjustment Exact Match Function pointer conversion Qualification Adjustment Exact Match Integral promotions Promotion Promotion Floating-point promotion Promotion Promotion Integral conversions Conversion Conversion Floating-point conversions Conversion Conversion Floating-integral conversions Conversion Conversion Pointer conversions Conversion Conversion Pointer-to-member conversions Conversion Conversion Boolean conversions Conversion Conversion
Array reference binding vs. array-to-pointer conversion with templates
The second overload is more specialized than the first one during partial ordering of function templates.
According to [temp.deduct.partial]/5 the reference on
T &t
of the first overload is ignored during template argument deduction performed for partial ordering. The following paragraphs distinguish based on reference/value category only if both parameters are reference types.Then
T
of the first overload can always deduce against a typeA*
invented from the parameter of the second overload, butT*
of the second overload can't deduce against a typeA
invented from the parameter of the first overload.Therefore the second overload is more specialized and is chosen.
With
T (&t)[4]
argument deduction in both directions will fail because deduction ofT[4]
againstA*
will fail and so will deduction ofT*
againstA[4]
. Array-to-pointer decay of the array type is specified for template argument deduction for a function call but not for template argument deduction for partial ordering. See also active CWG issue 402.So neither template will be more specialized in this case and the partial ordering tiebreaker does not apply.
The array-to-pointer conversion is not relevant. It is not considered any worse than the identity conversion sequence (see [over.ics.rank]/3.2.1 excluding lvalue transformations which array-to-pointer conversions are).
Overload resolution for template operators in namespaces
The
operator+
ofComplex
can be declared asfriend
function inComplex
, which does not pollute the global namespace. Your example should compile after the following change.struct Complex {
Complex(){};
explicit Complex(const DoubleArray<2>& components);
DoubleArray<2> _components;
friend Complex operator+(const Complex& rhs, const Complex& lhs) { return Complex(); }
};According to C++ standard working draft N4140,
When two or more different declarations are specified for a single name in the same scope, that name is said to be overloaded.
In your case, the two
operator+
functions are declared in different namespace and thus are not qualified for overload resolution.When compiler finds the first match
Complex operator+(const Complex& rhs, const Complex& lhs)
,DoubleArray
cannot be implicitly converted toComplex
. Therefore, you got theno match for ‘operator+’
error.Why does pointer decay take priority over a deduced template?
The fundamental reason for this (standard-conforming) ambiguity appears to lie within the cost of conversion: Overload resolution tries to minimize the operations performed to convert an argument to the corresponding parameter. An array is effectively the pointer to its first element though, decorated with some compile-time type information. An array-to-pointer conversion doesn't cost more than e.g. saving the address of the array itself, or initializing a reference to it. From that perspective, the ambiguity seems justified, although conceptually it is unintuitive (and may be subpar). In fact, this argumentation applies to all Lvalue Transformations, as suggested by the quote below. Another example:
void g() {}
void f(void(*)()) {}
void f(void(&)()) {}
int main() {
f(g); // Ambiguous
}The following is obligatory standardese. Functions that are not specializations of some function template are preferred over ones that are if both are otherwise an equally good match (see [over.match.best]/(1.3), (1.6)). In our case, the conversion performed is an array-to-pointer conversion, which is an Lvalue Transformation with Exact Match rank (according to table 12 in [over.ics.user]). [over.ics.rank]/3:
Standard conversion sequence
S1
is a better conversion sequence than standard conversion sequenceS2
if
S1
is a proper subsequence ofS2
(comparing the conversion sequences in the canonical form defined by 13.3.3.1.1, excluding
any Lvalue Transformation; the identity conversion sequence is considered to be a subsequence of any non-identity conversion
sequence) or, if not that,the rank of
S1
is better than the rank ofS2
, orS1
andS2
have the same rank and are distinguishable by the rules in the paragraph below, or, if not that,[..]
The first bullet point excludes our conversion (as it is an Lvalue Transformation). The second one requires a difference in ranks, which isn't present, as both conversions have Exact match rank; The "rules in the paragraph below", i.e. in [over.ics.rank]/4, don't cover array-to-pointer conversions either.
So believe it or not, none of both conversion sequences is better than the other, and thus thechar const*
-overload is picked.Possible workaround: Define the second overload as a function template as well, then partial ordering kicks in and selects the first one.
template <typename T>
auto foo(T s)
-> std::enable_if_t<std::is_convertible<T, char const*>{}>
{
std::cout << "raw, size=" << std::strlen(s) << std::endl;
}Demo.
How does overload resolution work when an argument is an overloaded function?
Let's take the most interesting case,
bar("abc", foo);
The primary question to figure out is, which overload of
bar
to use. As always, we first get a set of overloads by name lookup, then do template type deduction for each function template in the overload set, then do overload resolution.The really interesting part here is the template type deduction for the declaration
template<class T> void bar(T* x, void (*f)(T*)) {}
The Standard has this to say in 14.8.2.1/6:
When
P
is a function type, pointer to function type, or pointer to member function type:
If the argument is an overload set containing one or more function templates, the parameter is treated as a non-deduced context.
If the argument is an overload set (not containing function templates), trial argument deduction is attempted using each of the members of the set. If deduction succeeds for only one of the overload set members, that member is used as the argument value for the deduction. If deduction succeeds for more than one member of the overload set the parameter is treated as a non-deduced context.
(
P
has already been defined as the function template's function parameter type including template parameters, so hereP
isvoid (*)(T*)
.)So since
foo
is an overload set containing a function template,foo
andvoid (*f)(T*)
don't play a role in template type deduction. That leaves parameterT* x
and argument"abc"
with typeconst char[4]
.T*
not being a reference, the array type decays to a pointer typeconst char*
and we find thatT
isconst char
.Now we have overload resolution with these candidates:
void bar(int x, void (*f)(int)) {} // (1)
void bar(double x, void (*f)(double)) {} // (2)
void bar(std::string x, void (*f)(std::string)) {} // (3)
void bar<const char>(const char* x, void (*f)(const char*)) {} // (4)
void bar(A x, void (*f2)(double)) {} // (5)Time to find out which of these are viable functions. (1), (2), and (5) are not viable because there is no conversion from
const char[4]
toint
,double
, orA
. For (3) and (4) we need to figure out iffoo
is a valid second argument. In Standard section 13.4/1-6:A use of an overloaded function name without arguments is resolved in certain contexts to a function, a pointer to function or a pointer to member function for a specific function from the overload set. A function template name is considered to name a set of overloaded functions in such contexts. The function selected is the one whose type is identical to the function type of the target type required in the context. The target can be
- ...
- a parameter of a function (5.2.2),
- ...
... If the name is a function template, template argument deduction is done (14.8.2.2), and if the argument deduction succeeds, the resulting template argument list is used to generate a single function template specialization, which is added to the set of overloaded functions considered. ...
[Note: If
f()
andg()
are both overloaded functions, the cross product of possibilities must be considered to resolvef(&g)
, or the equivalent expressionf(g)
. - end note]For overload (3) of
bar
, we first attempt type deduction fortemplate<class T> void foo(T* ) {}
with target type
void (*)(std::string)
. This fails sincestd::string
cannot matchT*
. But we find one overload offoo
which has the exact typevoid (std::string)
, so it wins for the overload (3) case, and overload (3) is viable.For overload (4) of
bar
, we first attempt type deduction for the same function templatefoo
, this time with target typevoid (*)(const char*)
This time type deduction succeeds, withT
=const char
. None of the other overloads offoo
have the exact typevoid (const char*)
, so the function template specialization is used, and overload (4) is viable.Finally, we compare overloads (3) and (4) by ordinary overload resolution. In both cases, the conversion of argument
foo
to a pointer to function is an Exact Match, so neither implicit conversion sequence is better than the other. But the standard conversion fromconst char[4]
toconst char*
is better than the user-defined conversion sequence fromconst char[4]
tostd::string
. So overload (4) ofbar
is the best viable function (and it usesvoid foo<const char>(const char*)
as its argument).Overload resolution for char*, char array, and string literals using constexpr, SFINAE and/or type_traits
Per [expr.prim.id.unqual]:
[...] The type of the expression is the type of the identifier. The
result is the entity denoted by the identifier. The expression is an
lvalue if the entity is a function, variable, or data member and a
prvalue otherwise; it is a bit-field if the identifier designates a
bit-field ([dcl.struct.bind]).Therefore, given a declaration
const char arr[] = "foo";
The expression
arr
is an lvalue of typeconst char[4]
.Per [lex.string]/8:
Ordinary string literals and UTF-8 string literals are also referred
to as narrow string literals. A narrow string literal has type “array
of nconst char
”, where n is the size of the string as defined
below, and has static storage duration.And per [expr.prim.literal]:
A litera is a primary expression. Its type depends on its form. A
string literal is an lvalue; all other literals are prvalues.Therefore, the expression
"foo"
is an lvalue of typeconst char[4]
.Conclusion: a function is unable to differentiate between a (const) char array and a string literal.
Related Topics
How to Install Tensorflow on Windows
What Are _Mm_Prefetch() Locality Hints
Win32 Setforegroundwindow Unreliable
Conversion from Iplimage* to Cv::Mat
Node Packages Not Building on Windows 8.1 - Missing Microsoft.Cpp.Default.Props
Convert First Letter in String to Uppercase
Symbol Visibility and Namespace
How Does a C/C++ Compiler Find the Definitions of Prototypes in Header Files
Macro to Replace C++ Operator New
How to Create a Thread-Safe Singleton Pattern in Windows
Get Current Working Directory in a Qt Application
Search 25 000 Words Within a Text
Std Linker Error with Apple Llvm 4.1
C++: How to Check If the Cin Buffer Is Empty