N4861, to which you link, is not the newest working draft. I'm going to assume that you linked to it because it's the closest draft to C++20. The quotations that I'm going to provide below are from C++20 itself, just in case there are any differences.
According to [temp.deduct.conv]/1, we need to consult [dcl.init], [over.match.conv], and [over.match.ref] to determine what is A.
And in fact, [dcl.init] is really where you should have started looking in the first place, since the overload resolution is triggered by the declaration int&& res = s;.
[dcl.init.ref]/5.3 and 5.4 govern the initialization of rvalue references. 5.3 is tried first:
Otherwise, if the initializer expression
- is an rvalue (but not a bit-field) or function lvalue and "cv1
T1" is reference-compatible with "cv2 T2", or
- has a class type (i.e.,
T2 is a class type), where T1 is not reference-related to T2, and can be converted to an rvalue or function lvalue of type "cv3 T3", where "cv1 T1" is reference-compatible with "cv3 T3*" (see [over.match.ref]),
then the value of the initializer expression in the first case and the result of the conversion in the second case is called the converted initializer. If the converted initializer is a prvalue, its type T4 is adjusted to type "cv1 T4" ([conv.qual]) and the temporary materialization conversion ([conv.rval]) is applied. In any case, the reference is bound to the resulting glvalue (or to an appropriate base class subobject).
So we need to consult [over.match.ref] to see if such a cv3 T3 exists (in which case the conversion will be performed, and res will be bound to the result of that conversion). (Note that [over.match.conv] will not be reached in this case; it would be reached if we got to [dcl.init.ref]/5.4, but we will not, because [dcl.init.ref]/5.3 will succeed.)
[over.match.ref] says:
Under the conditions specified in [dcl.init.ref], a reference can be bound directly to the result of applying a conversion function to an initializer expression. Overload resolution is used to select the conversion function to be invoked. Assuming that "reference to cv1 T" is the type of the reference being initialized, and "cv S" is the type of the initializer expression, with S a class type, the candidate functions are selected as follows:
- The conversion functions of S and its base classes are considered. Those non-explicit conversion functions that are not hidden within
S and yield type "lvalue reference to cv2 T2" (when initializing an lvalue
reference or an rvalue reference to function) or "cv2 T2" or "rvalue reference to cv2 T2" (when initializing an rvalue reference or an lvalue reference to function), where "cv1 T" is reference-compatible ([dcl.init.ref]) with "cv2 T2", are candidate functions. For direct-initialization, those explicit conversion functions that are not hidden within S and yield type "lvalue reference to cv2 T2" (when initializing an lvalue reference or an rvalue reference to function) or "rvalue reference to cv2 T2" (when initializing an rvalue reference or an lvalue reference to function), where T2 is the same type as T or can be converted to
type T with a qualification conversion ([conv.qual]), are also candidate functions.
The argument list has one argument, which is the initializer expression.
The only type that int is reference-compatible with is int itself, and we are initializing an rvalue reference, so according to this section, we look for conversion functions of S with type int and int&&.
Only at this point, we are ready to perform template argument deduction under [temp.deduct.conv]/1. We will need to do this twice: once with A = int, and once with A = int&&. The results are then merged, and if there is more than one candidate in the resulting set, then we need to use overload resolution to select the one that gets called.
With A = int, [temp.deduct.conv]/3.3 tells us that the top-level cv-qualifiers of P are ignored. Clearly, this results in T being deduced as int; the candidate is S::operator const int().
With A = int&&, in this case the top-level cv-qualifiers of P are not ignored; P remains const T. [temp.deduct.conv]/4 tells us that A is transformed into the type it refers to, namely int. We do the deduction using the transformed types (P = const T, A = int). This fails; there's no T such that const T is int. So there are no candidates generated in this step.
The result is that S::operator const int() is called, producing a prvalue of type const int, but cv-qualification of prvalues of scalar type is discarded prior to any further analysis. So it is materialized into a temporary object of type int, and res is bound to that temporary.