cplusplus / draft

C++ standards drafts
http://www.open-std.org/jtc1/sc22/wg21/
5.6k stars 739 forks source link

The permissible types in [over.match.conv] should not be reference types #4761

Open xmh0511 opened 2 years ago

xmh0511 commented 2 years ago

Assuming that “cv T” is the type of the object being initialized, the candidate functions are selected as follows:

  • The permissible types for non-explicit conversion functions are those that can be converted to type T via a standard conversion sequence ([over.ics.scs]).
  • For direct-initialization, the permissible types for explicit conversion functions are those that can be converted to type T with a (possibly trivial) qualification conversion ([conv.qual]); otherwise there are none.

Is that reference to type T considered the permissible type here? It's probably not, if it were, it will be conflicted with [over.match.funcs#general-7]. From the perspective of conversion sequence, an argument of reference type should be first adjusted to the referenced type(T) as per [expr#type-1] prior to any further analysis. Hence, it is arguably said that from T to T satisfies the above requirement. It's unclear here, maybe we should explicitly say that

The permissible types for non-explicit conversion functions are those non-reference types that can be converted to type T via a standard conversion sequence ([over.ics.scs]).

For direct-initialization, the permissible types for explicit conversion functions are those non-reference types that can be converted to type T with a (possibly trivial) qualification conversion ([conv.qual]); otherwise there are none.

It seems that the wording possibly trivial is newly introduced, Is that if we say identity conversion is more clear?

jensmaurer commented 2 years ago

I think the phrasing "convert a type to another type" has a deeper problem. In [conv.general] p1, we say "A standard conversion sequence will be applied to an expression if necessary to convert it to a required destination type."

So, a standard conversion sequence converts an expression to a type. Attempting to convert a type to a type is ill-defined.

jensmaurer commented 2 years ago

http://lists.isocpp.org/core/2021/08/11357.php

opensdh commented 2 years ago

Since we're talking about conversion functions here, one approach is to just say that the expression being converted is a call to the conversion function (so that [expr.call]/14, the "inverse" of decltype, applies). That said, standard conversion sequences don't care much about the value category of the source expression (since the lvalue-to-rvalue conversion always applies when initializing an object), so I bet we can simply say "those object types of which a prvalue can be converted" (and let [over.match.funcs.general]/7 cover the rest, as stated above).

As for "possibly trivial", [conv.qual]/3 doesn't actually require that T1 and T2 differ, but I wanted to be clear about that case since it's not used in forming standard conversion sequences.

xmh0511 commented 2 years ago

I think, from T1 to T2 is just an identity conversion if T1 and T2 are the same. If we say they are the "possibly trivial" qualification conversion, it will result in this problem https://stackoverflow.com/questions/65282778/is-an-identity-conversion-of-pointer-type-be-considered-as-qualification-convers, which means it will influence the rank in overload resolution. Hence, I hope we could distinguish them to be two different kinds of conversion.

opensdh commented 2 years ago

it will result in this problem

It won't: as discussed there, the sequence formation process doesn't use the vacuous qualification conversion because it doesn't need to do so. Here, we explicitly ask whether it's possible to do so, and for the same type it is. If we think it's clearer to exclude that case in [conv.qual] and then say "T and those that can…", we can certainly do so.

Incidentally, the [over.ics.rank]/3.2.5 cited there also discusses converting a type to a type (albeit via a specific kind of conversion).

xmh0511 commented 2 years ago

If we merely according to the definition of the qualification conversion, convert int* to int* itself could be considered as a qualification conversion since it didn't conflict with the definition. However, in some special cases, such as the overload resolution, the qualification conversion is explicitly considered to have the exact match rank as per [over.ics.scs]. But, identity conversion has a higher priority than any other conversion sequence with the same rank(i.e. exact match) as per [over.ics.rank#3.2.1]. I'd prefer to consider the conversion sequence that requires no conversion to be an identity conversion rather than a "trivial" qualification conversion(int => int). And we should use this concept anywhere in the standard to make the meaning be consistent.


It seems not only [over.ics.rank]/3.2.5 but also somewhere in the standard use that possibly wrong utterance.

xmh0511 commented 2 years ago

so I bet we can simply say "those object types of which a prvalue can be converted" (and let [over.match.funcs.general]/7 cover the rest, as stated above).

This should also apply to [over.match.ref]

For direct-initialization, the permissible types for explicit conversion functions are the members of R where T2 can be converted to type T with a (possibly trivial) qualification conversion ([conv.qual]); otherwise there are none.