reinterpret_cast
so that it may
now cast away constness. For example,
reinterpret_cast<int *>((const void *)0)is ill-formed in C++14 due to the provision in 5.2.10 [expr.reinterpret.cast] paragraph 2 "The
reinterpret_cast
operator shall not cast away constness (5.2.11 expr.const.cast)". The
wording changes below will remove this restriction, thus the example
above will become well-formed. Given the general nature of
reinterpret_cast
, the restriction on casting away
constness appeared as a rather odd constraint.
The following is a verbatim copy of the issue writeup in the core issues list.
Section 4.4 [conv.qual] covers the case of multi-level pointers, but does not appear to cover the case of pointers to arrays of pointers. The effect is that arrays are treated differently from simple scalar values.
Consider for example the following code: (from the thread "Pointer to array conversion question" begun in comp.lang.c++.moderated)
int main() { double *array2D[2][3]; double * (*array2DPtr1)[3] = array2D; // Legal double * const (*array2DPtr2)[3] = array2DPtr1; // Legal double const * const (*array2DPtr3)[3] = array2DPtr2; // Illegal }and compare this code with:-
int main() { double *array[2]; double * *ppd1 = array; // legal double * const *ppd2 = ppd1; // legal double const * const *ppd3 = ppd2; // certainly legal (4.4/4) }
The problem appears to be that the pointed to types in example 1 are unrelated since nothing in the relevant section of the standard covers it - 4.4 [conv.qual] does not mention conversions of the form "cv array of N pointer to T" into "cv array of N pointer to cv T"
It appears that reinterpret_cast
is the only way to
perform the conversion.
Remove 4.4 conv.qual paragraphs 5-7:A conversion can add cv-qualifiers at levels other than the first in multi-level pointers, subject to the following rules: [ Footnote ... ]Twopointertypes T1 and T2 are similar if there exists a type T and integer n > 0 such that:andT1 is cv 1,0 pointer to cv 1,1 pointer to . . . cv 1,n-1 pointer to cv 1,n T
T1 is cv1,0 P0 cv1,1 P1 . . . cv1,n-1 Pn-1 cv1,n Twhere each cvi,j isT2 is cv 2,0 pointer to cv 2,1 pointer to . . . cv 2,n-1 pointer to cv 2,n T
T2 is cv2,0 P0 cv2,1 P1 . . . cv2,n-1 Pn-1 cv2,n Tconst
,volatile
,const volatile
, or nothing and, for each j from 0 ... n-1, Pj Pj+1 ... Pn-1 T is a pointer, pointer to member, or array type. The n-tuple of cv-qualifiers after the first onein a pointer type e.g., cv 1,1 , cv 1,2 , . . . , cv 1,n in the pointer type T1, that is, cvi,1, cvi,2, ... cvi,n for Ti, is called the cv-qualification signature of thepointertype.
AnA prvalue expression of type T1 can be converted to type T2 ifand only ifthe following conditions are satisfied [ Footnote: These rules ensure that const-safety is preserved by the conversion. ]:[ Note: if a program could assign a pointer of type T** to a pointer of type const T** (that is, if line #1 below were allowed), a program could inadvertently modify a const object (as it is done on line #2). For example,
the pointer typesT1 and T2 are similar.forFor every j > 0, ifconst
is in cv1,j thenconst
is incv 2,j , and similarly forvolatile
.ifIf the cv1,j and cv2,j are different, thenconst
is in every cv2,k for 0 < k < j.int main() { const char c = 'c'; char* pc; const char** pcc = &pc; // #1: not allowed *pcc = &c; *pc = 'C'; // #2: modifies a const object }-- end note ]
Move 4.4 conv.qual paragraphs 1-3 after paragraph 4 and turn them into notes:A multi-level pointer to member type, or a multi-level mixed pointer and pointer to member type has the form: ...
Two multi-level pointer to member types or two multi-level mixed pointer and pointer to member types T1 and T2 are similar if ...
For similar multi-level pointer to member types and similar multi-level mixed pointer and pointer to member types, ...
[ Note: A prvalue of type "pointer to cv1 T" can be converted to a prvalue of type "pointer to cv2 T" if "cv2 T" is more cv-qualified than "cv1 T". A prvalue of type "pointer to member of X of type cv1 T" can be converted to a prvalue of type "pointer to member of X of type cv2 T" if "cv2 T" is more cv-qualified than "cv1 T". -- end note ]Change in 5 expr paragraph 13:[ Note: Function types (including those used in pointer to member function types) are never cv-qualified (8.3.5). -- end note ]
Change in 5.2.10 expr.reinterpret.cast paragraph 2:
- ...
- if T1 and T2 are similar
multi-level mixed pointer and pointer to membertypes (4.4 conv.qual), the cv-combined type of T1 and T2;- ...
Delete the footnotes in 5.2.10 expr.reinterpret.cast paragraphs 7 and 10:TheAn expression of integral, enumeration, pointer, or pointer-to-member type can be explicitly converted to its own type; such a cast yields the value of its operand.reinterpret_cast
operator shall not cast away constness (5.2.11 expr.const.cast).
Change in 5.2.11 expr.const.cast paragraph 3:[ Footnote: The types may have different cv-qualifiers, subject to the overall restriction that a reinterpret_cast cannot cast away constness. ]...[ Footnote: T1 and T2 may have different cv-qualifiers, subject to the overall restriction that a reinterpret_cast cannot cast away constness. ]
For twoRemove in 5.2.11 expr.const.cast paragraph 5:pointersimilar types T1 and T2 (4.4 conv.qual)whereT1 is cv 1,0 pointer to cv 1,1 pointer to . . . cv 1,n-1 pointer to cv 1,n TandT2 is cv 2,0 pointer to cv 2,1 pointer to . . . cv 2,n-1 pointer to cv 2,n Twhere T is any object type or the void type and where cv 1,k and cv 2,k may be different cv-qualifications, a prvalue of type T1 may be explicitly converted to the type T2 using aconst_cast
. The result of apointerconst_cast
refers to the originalobjectentity. [ Example:typedef int *A[3]; // array of 3 pointer to int typedef const int *const CA[3]; // array of 3 const pointer to const int CA &&r = A{}; // ok, reference binds to temporary array object after qualification conversion to type CA A &&r = const_cast<A>(CA{}); // error: temporary array decayed to pointer A &&r = const_cast<A&&>(CA{}); // ok-- end example ]
Replace all of 5.2.11 expr.const.cast paragraph 8:For a const_cast involving pointers to data members, multi-level pointers to data members and multi-level mixed pointers and pointers to data members (4.4 conv.qual), the rules for const_cast are the same as those used for pointers; the "member" aspect of a pointer to member is ignored when determining where the cv-qualifiers are added or removed by the const_cast. The result of a pointer to data member const_cast refers to the same member as the original (uncast) pointer to data member.
Remove 5.2.11 expr.const.cast paragraphs 11 and 12:The following rules define the process known as casting away constness. In these rules Tn and Xn represent types. For two pointer types:X1 is T1cv 1,1 * . . . cv 1,N * where T1 is not a pointer type X2 is T2cv 2,1 * . . . cv 2,M * where T2 is not a pointer type K is min(N, M )casting from X1 to X2 casts away constness if, for a non-pointer type T there does not exist an implicit conversion (Clause 4) from:Tcv 1,(N -K+1) * cv 1,(N -K+2) * . . . cv 1,N *toA conversion from a type T1 to a type T2 casts away constness ifTcv 2,(M -K+1) * cv 2,(M -K+2) * . . . cv 2,M *
- T1 and T2 are similar and there is no qualification conversion (4.4 conv.qual) that converts T1 to T2,
- T1 is "pointer to cv1 U1" and T2 is "pointer to cv2 U2" and there is no qualification conversion that converts T1 to the type "pointer to cv2 U1" (see 4.10 conv.ptr), or
- T1 is "pointer to member of class C1 of type cv1 U1" and T2 is "pointer to member of class C2 of type cv2 U2" and there is no qualification conversion that converts T1 to the type "pointer to member of class C1 of type cv2 U1" (see 4.11 conv.mem).
Change 5.4 expr.cast paragraph 4:Casting from a prvalue of type "pointer to data member of X of type T1" to the type "pointer to data member of Y of type T2" casts away constness if a cast from a prvalue of type "pointer to T1" to the type "pointer to T2" casts away constness.
For multi-level pointer to members and multi-level mixed pointers and pointer to members (4.4), the "mem- ber" aspect of a pointer to member level is ignored when determining if a const cv-qualifier has been cast away.
The conversions performed bycan be performed using the cast notation of explicit type conversion. ...
- ...
- a
static_cast
followed by aconst_cast
, or- a
reinterpret_cast
(5.2.10),orareinterpret_cast
followed by a const_cast,