Overload resolution and arrays: which function should be called? Overload resolution and arrays: which function should be called? arrays arrays

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.


I claim that #3 is the function chosen by a conforming compiler.

(1) is better than (2) because "Standard conversion sequence S1 is a better conversion sequence than standard conversion sequence S2 if 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."

(3) is better than both (1) and (2) because it is an identity conversion (the others are exact match conversions) and "Standard conversion sequence S1 is a better conversion sequence than standard conversion sequence S2 if S1 is a proper subsequence of S2 (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)"

Template vs non-template is only considered when neither conversion is better "or, if not that..."

oddly enough though, Comeau prefers (2) over (3). This test case fails to compile:

#include <cstddef>#include <cstdio>// (1) removed because Comeau doesn't support rvalue-references yetchar f(char const* const&) { std::puts("char const* const&"); return 0; } // (2)template <std::size_t N>int f(char const (&)[N])  { std::puts("char const(&)[N]"); return 0; } // (3)int main(){    const char data[] = "a";    switch (0) {       case sizeof(char):           break;       case sizeof(f(data)):           break;    }}


This is a community wiki answer for collecting snippets from the standard (draft 3225).

section 13.3.3 "Best viable function" [over.match.best]

  1. Define ICSi(F) as follows:

    • if F is a static member function, ICS1(F) is defined such that ICS1(F) is neither better nor worse thanICS1(G) for any function G, and, symmetrically, ICS1(G) is neither better nor worse than ICS1(F); otherwise,

    • let ICSi(F) denote the implicit conversion sequence that converts the i-th argument in the list to thetype of the i-th parameter of viable function F. 13.3.3.1 defines the implicit conversion sequences and13.3.3.2 defines what it means for one implicit conversion sequence to be a better conversion sequence or worse conversion sequence than another.

    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

    • for some argument j, ICSj(F1) is a better conversion sequence than ICSj(F2)

    or, if not that,

    • the context is an initialization by user-defined conversion (see 8.5, 13.3.1.5, and 13.3.1.6) and the standard conversion sequence from the return type of F1 to the destination type (i.e., the type of the entity being initialized) is a better conversion sequence than the standard conversion sequence from the return type of F2 to the destination type

    or, if not that,

    • F1 is a non-template function and F2 is a function template specialization

    or, if not that,

    • F1 and F2 are function template specializations, and the function template for F1 is more specializedthan the template for F2 according to the partial ordering rules described in 14.5.6.2.
  2. If there is exactly one viable function that is a better function than all other viable functions, then it is the one selected by overload resolution; otherwise the call is ill-formed.

section 13.3.3.1.4 "Reference binding" [over.ics.ref]

  1. When a parameter of reference type binds directly (8.5.3) to an argument expression, the implicit conversionsequence is the identity conversion, unless the argument expression has a type that is a derived class of theparameter type, in which case the implicit conversion sequence is a derived-to-base conversion (13.3.3.1). If the parameter binds directly to the result of applying a conversion function to theargument expression, the implicit conversion sequence is a user-defined conversion sequence (13.3.3.1.2), with the second standard conversion sequence either an identity conversion or, if the conversion functionreturns an entity of a type that is a derived class of the parameter type, a derived-to-base Conversion.

  2. When a parameter of reference type is not bound directly to an argument expression, the conversion sequenceis the one required to convert the argument expression to the underlying type of the reference accordingto 13.3.3.1. Conceptually, this conversion sequence corresponds to copy-initializing a temporary of theunderlying type with the argument expression. Any difference in top-level cv-qualification is subsumed bythe initialization itself and does not constitute a conversion.

section 13.3.3.2 "Ranking implicit conversion sequences" [over.ics.rank]

  1. 13.3.3.2 defines a partial ordering of implicit conversion sequences based on the relationships better conversionsequence and better conversion. If an implicit conversion sequence S1 is defined by these rules to be a betterconversion sequence than S2, then it is also the case that S2 is a worse conversion sequence than S1. Ifconversion sequence S1 is neither better than nor worse than conversion sequence S2, S1 and S2 are said tobe indistinguishable conversion sequences.

  2. When comparing the basic forms of implicit conversion sequences (as defined in 13.3.3.1)

    • a standard conversion sequence (13.3.3.1.1) is a better conversion sequence than a user-defined conversion sequence or an ellipsis conversion sequence, and

    • a user-defined conversion sequence (13.3.3.1.2) is a better conversion sequence than an ellipsis conversion sequence (13.3.3.1.3).

  3. Two implicit conversion sequences of the same form are indistinguishable conversion sequences unless one ofthe following rules applies:

    • Standard conversion sequence S1 is a better conversion sequence than standard conversion sequence S2 if

      • S1 is a proper subsequence of S2 (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 of S2, or S1 and S2 have the same rank and are distinguishable by the rules in the paragraph below

      or, if not that,

      • S1 and S2 differ only in their qualification conversion and yield similar types T1 and T2 (4.4), respectively, and the cv-qualification signature of type T1 is a proper subset of the cv-qualification signature of type T2.

      or, if not that,

      • S1 and S2 are reference bindings (8.5.3) and neither refers to an implicit object parameter of anon-static member function declared without a ref-qualifier, and S1 binds an rvalue reference toan rvalue and S2 binds an lvalue reference.