Check the viability of a conversion function

Viewed 73

I have the following code:

struct S {
  operator int();       // F1
   operator double();   // F2
};

int main() {
    int res = S();
}

Since neither F1 nor F2 is cv-qualified, the type of the implicit object parameter is S&, and the corresponding argument to be matched against is S().

Now, per [over.match.viable]/4: (emphasis mine)

Third, for F to be a viable function, there shall exist for each argument an implicit conversion sequence that converts that argument to the corresponding parameter of F. If the parameter has reference type, the implicit conversion sequence includes the operation of binding the reference, and the fact that an lvalue reference to non-const cannot bind to an rvalue and that an rvalue reference cannot bind to an lvalue can affect the viability of the function (see [over.ics.ref]).

According to the above quote (bold), I'm expecting that neither F1 nor F2 is viable, because the implicit object parameter for both is of type S& and it cannot bind to an rvalue, S().

But, when I tried to compile the code, I found out both functions are viable candidates. Which is best match is not what I am asking about here.

So, why are both F1 and F2 viable candidates, even though the implicit object parameter (of type S&) cannot bind to class prvalue S()?

1 Answers

The main concern expressed in your question appears to be how a given rvalue argument can bind to an implicitly declared lvalue reference parameter. (I'm not here even attempting to make an adjudication on the extensive discusssion in the comments to your question about whether or not any actual overloads are involved in your code sample.)

This (main) concern is addressed – quite clearly, IMHO – in another part of the [over.match.funcs] section of the C++ Standard you cite (bold emphasis mine):

12.2.2.1       General[over.match.funcs.general]

…
5     During overload resolution, the implied object argument is indistinguishable from other arguments. The implicit object parameter, however, retains its identity since no user-defined conversions can be applied to achieve a type match with it. For implicit object member functions declared without a ref-qualifier, even if the implicit object parameter is not const-qualified, an rvalue can be bound to the parameter as long as in all other respects the argument can be converted to the type of the implicit object parameter.

Without this paragraph, implicit conversion functions would lose a great deal of their usefulness, such as the use-case you have provided in your example.

Related