New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
[conv.integral,over.best.ics.general,over.ics.user] Ignore cv-qualification differences #4860
base: main
Are you sure you want to change the base?
Conversation
In terms of the opportunity to clarify these concepts, consider this example void fun(int&){} // #1
void fun(int){} // #2
int a = 0;
fun(a); The identity conversion is vague here. Since using a glvalue This issue arises from when we step into [conv#general-1.4]
How should we treat them where whether, from a prvalue of type Back to the definition of identity conversion, the relevant notes and normative rules are
[conv#general-note-1]
[over.best.ics#general-8]
Does it mean, even though an lvalue-to-rvalue conversion applies and the result prvalue with the same type as that of the target, it cannot be considered as identity conversion? Moreover, from a prvalue of type Clarification, I think we should give a terminal condition of implicit conversion(i.e., standard implicit conversion) to avoid the endless conversion that is permitted on concept or definition. int a =0;
int const volatile t = a; // just lvalue-to-rvalue conversion Even though we say a standard conversion sequence can consist of one to three conversions from the other four categories, and a qualification conversion is permitted by the concept. In other words, we should give a condition to avoid it go into [conv#general-1.4] if that condition is satisfied. |
I think the intent is that all conversions described in [conv] are not "empty". This is clear in the formulation of integral and floating-point conversions, where we say "another ... type". Which didn't properly exclude mere differences in cv-qualification (first patch in this pull request). Similarly, [conv.qual] should only allow conversions to a different type, excluding a conversion from T to T (second patch in this pull request). |
Please still consider [conv.qual], give such two example const volatile int v = 0; // #1
const volatile Class obj = Class(); // #2 The target type of |
I think there are situations where the need for a top-level qualification-conversion is significant:
Note also that forming a conversion sequence in overload resolution is different from the actual initialization in [dcl.init]. For the actual initialization, [dcl.init] should (does it?) ignore top-level cv-qualifiers on the target. |
IMO, regardless of the first or second overload, the parameters are all of the reference type, a valid reference type cannot be cv-qualified, in this case, the rank is impacted by [over.ics.rank#3.2.6], that rule explicitly says we talk about the top-level cv-qualifiers of the referenced type. I think the qualification conversion is almost prepared for pointer types and their top-level cv-qualifiers do not have an effect. int* ptr = 0;
int* const ptr1 = ptr // lvalue-to-rvalue conversion is sufficient
int const* ptr2 = ptr // lvalue-to-rvalue conversion followed by a qualification conversion Hence, we can generally say qualification conversion is not necessary to apply to two similar types where their difference only in cv0(i.e. the top-level cv-qualification of that type).
I'm not clear about whether the initialization is or not, however, for overload resolution, the top-level cv-qualifiers are ignored once the function type has formed. In the initialization case, the target type is defined as.
It could arguably say the top-level cv-qualifier is considered in the destination type. |
@@ -780,7 +780,7 @@ | |||
where $\cv{}^j_i$ and $P^j_i$ are the components of | |||
the qualification-decomposition of $\tcode{T}j$. | |||
A prvalue of type \tcode{T1} | |||
can be converted to type \tcode{T2} | |||
can be converted to another type \tcode{T2} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Since we have excluded the identity conversion from qualification conversion, [expr.const.cast] p7 should also have to be changed to adhere this modification
[expr.const.cast] p7 says
A conversion from a type T1 to a type T2 casts away constness if T1 and T2 are different, there is a qualification-decomposition ([conv.qual]) of T1 yielding n such that T2 has a qualification-decomposition of the form
- [...]
and there is no qualification conversion that converts T1 to
- [...] named T3
Consider this example:
int* ptr = 0;
static_cast<void*>(ptr);
In this example, T1
is "pointer to int" while T2
is "pointer to void". When n=1, T3
is pointer to void
, since T2
and T3
are the same types, hence there is no qualification conversion that converts T2
to T3
([conv.qual] p3 excludes identify conversions). This is not the intent of the definition of the cast-away constness.
[expr.const.cast] p7 should be changed to
A conversion from a type T1 to a type T2 casts away constness if T1 and T2 are different, there is a qualification-decomposition ([conv.qual]) of T1 with the form
cv10 P10 cv11 P11 ... cv1n-1 P2n-1 cv1n U1
yielding n such that T2 has a qualification-decomposition of the form
- cv20 P20 cv21 P21 ... cv2n-1 P2n-1 cv2n U2
and such that a type
T3
has a qualification-decomposition of the form
- cv20 P10 cv21 P11 ... cv2n-1 P1n-1 cv2n U1
there is no qualification conversion that converts
T1
toT3
if they are different types
Option 2
Or we just say: The qualification-combined type of T1
and T3
is not T3
.
Fixes #4851