Skip to content

Commit 89281b5

Browse files
author
Stefanus Du Toit
committed
N3624 - Pointer comparison vs qualification conversions
In the additions to [expr], terms like T1, C1, where typeset in code font. "pointers to member" was replaced by "pointers to members" in accordance with existing practice in the standard.
1 parent d56faa5 commit 89281b5

File tree

4 files changed

+169
-127
lines changed

4 files changed

+169
-127
lines changed

source/classes.tex

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1161,7 +1161,8 @@
11611161
to inspect the common initial sequence of any of standard-layout struct members;
11621162
see~\ref{class.mem}. \exitnote The size of a union is sufficient to contain the largest
11631163
of its non-static data members. Each non-static data member is allocated
1164-
as if it were the sole member of a struct.
1164+
as if it were the sole member of a struct. All non-static data members of a
1165+
union object have the same address.
11651166

11661167
\pnum
11671168
\indextext{member function!\idxcode{union}}%

source/expressions.tex

Lines changed: 162 additions & 121 deletions
Original file line numberDiff line numberDiff line change
@@ -236,6 +236,82 @@
236236
conversions as described in~\ref{expr.cast},~\ref{expr.static.cast}
237237
and~\ref{expr.ass}.}
238238

239+
\pnum
240+
The \term{cv-combined type} of two types \tcode{T1} and \tcode{T2}
241+
is a type \tcode{T3}
242+
similar to \tcode{T1} whose cv-qualification signature~(\ref{conv.qual}) is:
243+
\begin{itemize}
244+
\item
245+
for every $j > 0$, \cv$_{3,j}$ is the union of
246+
\cv$_{1,j}$ and \cv$_{2,j}$;
247+
248+
\item
249+
if the resulting \cv$_{3,j}$ is different from
250+
\cv$_{1,j}$ or \cv$_{2,j}$, then
251+
\tcode{const} is added to every \cv$_{3,k}$ for $0 < k < j$.
252+
\end{itemize}
253+
254+
\enternote Given similar types \tcode{T1} and \tcode{T2}, this
255+
construction ensures that
256+
both can be converted to \tcode{T3}. \exitnote
257+
The \term{composite pointer type} of
258+
two operands \tcode{p1} and
259+
\tcode{p2} having types \tcode{T1} and \tcode{T2}, respectively, where at least one is a
260+
pointer or pointer to member type or
261+
\tcode{std::nullptr_t}, is:
262+
263+
\begin{itemize}
264+
\item
265+
if both \tcode{p1} and \tcode{p2} are null pointer constants,
266+
\tcode{std::nullptr_t};
267+
268+
\item
269+
if either \tcode{p1} or \tcode{p2} is a null pointer constant, \tcode{T2} or \tcode{T1},
270+
respectively;
271+
272+
\item
273+
if \tcode{T1} or \tcode{T2} is ``pointer to \cvqual{cv1} \tcode{void}'' and the
274+
other type is ``pointer to \cvqual{cv2} T'', ``pointer to \cvqual{cv12}
275+
\tcode{void}'', where \cvqual{cv12} is the union of \cvqual{cv1}
276+
and \cvqual{cv2};
277+
278+
\item
279+
if \tcode{T1} is ``pointer to \cvqual{cv1} \tcode{C1}'' and \tcode{T2} is ``pointer to
280+
\cvqual{cv2} \tcode{C2}'', where \tcode{C1} is reference-related to \tcode{C2} or \tcode{C2} is
281+
reference-related to \tcode{C1}~(\ref{dcl.init.ref}), the cv-combined type
282+
of \tcode{T1} and \tcode{T2} or the cv-combined type of \tcode{T2} and \tcode{T1},
283+
respectively;
284+
285+
\item
286+
if \tcode{T1} is ``pointer to member of \tcode{C1} of type \cvqual{cv1} U1'' and \tcode{T2} is
287+
``pointer to member of \tcode{C2} of type \cvqual{cv2} U2'' where \tcode{C1} is
288+
reference-related to \tcode{C2} or \tcode{C2} is reference-related to
289+
\tcode{C1}~(\ref{dcl.init.ref}), the cv-combined type of \tcode{T2} and \tcode{T1} or the cv-combined type
290+
of \tcode{T1} and \tcode{T2}, respectively;
291+
292+
\item
293+
if \tcode{T1} and \tcode{T2} are similar multi-level mixed pointer and pointer to
294+
member types~(\ref{expr.qual}), the cv-combined type of \tcode{T1} and
295+
\tcode{T2};
296+
297+
\item
298+
otherwise, a program that necessitates the determination of a
299+
composite pointer type is ill-formed.
300+
\end{itemize}
301+
302+
\enterexample
303+
\begin{codeblock}
304+
typedef void *p;
305+
typedef const int *q;
306+
typedef int **pi;
307+
typedef const int **pci;
308+
\end{codeblock}
309+
310+
The composite pointer type of \tcode{p} and \tcode{q} is ``pointer to \tcode{const void}''; the
311+
composite pointer type of \tcode{pi} and \tcode{pci} is ``pointer to \tcode{const} pointer to
312+
\tcode{const int}''.
313+
\exitexample
314+
239315
\rSec1[expr.prim]{Primary expressions}%
240316
\indextext{expression!primary|(}
241317

@@ -3557,102 +3633,49 @@
35573633
relational-expression \terminal{>=} shift-expression
35583634
\end{bnf}
35593635

3560-
The operands shall have arithmetic, enumeration, or pointer type, or type \tcode{std::nullptr_t}. The
3636+
The operands shall have arithmetic, enumeration, or pointer type. The
35613637
operators \tcode{<} (less than), \tcode{>} (greater than), \tcode{<=}
35623638
(less than or equal to), and \tcode{>=} (greater than or equal to) all
35633639
yield \tcode{false} or \tcode{true}. The type of the result is
35643640
\tcode{bool}.
35653641

35663642
\pnum
35673643
The usual arithmetic conversions are performed on operands of arithmetic
3568-
or enumeration type. Pointer conversions~(\ref{conv.ptr}) and
3569-
qualification conversions~(\ref{conv.qual}) are performed on pointer
3570-
operands (or on a pointer operand and a null pointer constant, or on two
3571-
null pointer constants, at least one of which is non-integral) to bring
3572-
them to their \term{composite pointer type}. If one operand is a
3573-
null pointer constant, the composite pointer type is
3574-
\tcode{std::nullptr_t} if the other operand is also a null pointer constant or,
3575-
if the other operand is a pointer,
3576-
the type of the
3577-
other operand. Otherwise, if one of the operands has type ``pointer to
3578-
\cvqual{cv1} \tcode{void},'' then the other has type ``pointer to
3579-
\cvqual{cv2} \term{T}'' and the composite pointer type is ``pointer to
3580-
\cvqual{cv12} \tcode{void},'' where \cvqual{cv12} is the union of
3581-
\cvqual{cv1} and \cvqual{cv2}. Otherwise, the composite pointer type is
3582-
a pointer type similar~(\ref{conv.qual}) to the type of one of the
3583-
operands, with a cv-qualification signature~(\ref{conv.qual}) that is
3584-
the union of the cv-qualification signatures of the operand types.
3585-
\enternote
3586-
\indextext{comparison!void* pointer@\tcode{void*} pointer}%
3587-
this implies
3588-
that any pointer can be compared to a null pointer constant and that any
3589-
object pointer can be compared to a pointer to (possibly cv-qualified)
3590-
\tcode{void}.
3591-
\exitnote
3592-
\enterexample
3644+
or enumeration type. If both operands are pointers, pointer
3645+
conversions~(\ref{conv.ptr}) and qualification conversions~(\ref{conv.qual})
3646+
are performed to bring
3647+
them to their composite pointer type (Clause~\ref{expr}).
3648+
After conversions, the operands shall have the same type.
35933649

3594-
\begin{codeblock}
3595-
void *p;
3596-
const int *q;
3597-
int **pi;
3598-
const int *const *pci;
3599-
void ct() {
3600-
p <= q; // Both converted to \tcode{const void*} before comparison
3601-
pi <= pci; // Both converted to \tcode{const int *const *} before comparison
3602-
}
3603-
\end{codeblock}
3604-
\exitexample
3605-
\indextext{comparison!pointer}%
3606-
\indextext{comparison!pointer~to function}%
3607-
Pointers to objects or functions of the same type (after pointer
3608-
conversions) can be compared, with a result defined as follows:
3650+
\pnum
3651+
Comparing pointers to objects is defined as follows:
36093652

36103653
\begin{itemize}
3611-
\item If two pointers \tcode{p} and \tcode{q} of the same type point to
3612-
the same object or function, or both point one past the end of the same
3613-
array, or are both null, then \tcode{p<=q} and \tcode{p>=q} both yield
3614-
\tcode{true} and \tcode{p<q} and \tcode{p>q} both yield \tcode{false}.
3615-
3616-
\item If two pointers \tcode{p} and \tcode{q} of the same type point to
3617-
different objects that are not members of the same object or elements of
3618-
the same array or to different functions, or if only one of them is
3619-
null, the results of \tcode{p<q}, \tcode{p>q}, \tcode{p<=q}, and
3620-
\tcode{p>=q} are unspecified.
3621-
3622-
\item If two pointers point to non-static data members of the same
3623-
object, or to subobjects or array elements of such members, recursively,
3654+
\item If two pointers point to different elements of the same array, or to
3655+
subobjects thereof, the pointer to the element with the higher subscript
3656+
compares greater.
3657+
3658+
\item If one pointer points to an element of an array, or to a subobject
3659+
thereof, and another pointer points one past the last element of the array, the
3660+
latter pointer compares greater.
3661+
3662+
\item If two pointers point to different non-static data members of the same
3663+
object, or to subobjects of such members, recursively,
36243664
the pointer to the later declared member compares greater provided the
36253665
two members
36263666
have the same access control (Clause~\ref{class.access})
36273667
and provided their class is not a union.
36283668

3629-
\indextext{comparison!undefined pointer}%
3630-
\item If two pointers point to non-static data members of the same
3631-
object
3632-
with different access control (Clause~\ref{class.access})
3633-
the result is unspecified.
3634-
3635-
\item If two pointers point to non-static data members of the same union object,
3636-
they compare equal (after conversion to \tcode{void*}, if necessary). If
3637-
two pointers point to elements of the same array or one beyond the end
3638-
of the array, the pointer to the object with the higher subscript
3639-
compares higher.
3640-
3641-
\indextext{comparison!unspecified pointer}%
3642-
\indextext{comparison!pointer}%
3643-
\item Other pointer comparisons are unspecified.
36443669
\end{itemize}
36453670

36463671
\pnum
3647-
Pointers to \tcode{void} (after pointer conversions) can be compared, with a result
3648-
defined as follows: If both pointers represent the same address or are both the null
3649-
pointer value, the result is \tcode{true} if the operator is \tcode{<=} or \tcode{>=}
3650-
and \tcode{false} otherwise; otherwise the result is unspecified.
3651-
3652-
\pnum
3653-
If two operands of type \tcode{std::nullptr_t} are compared, the result is
3654-
\tcode{true} if the operator is \tcode{<=} or \tcode{>=}, and \tcode{false}
3655-
otherwise.
3672+
If two operands \tcode{p} and \tcode{q} compare equal~(\ref{expr.eq}),
3673+
\tcode{p<=q} and \tcode{p>=q} both yield \tcode{true} and \tcode{p<q} and
3674+
\tcode{p>q} both yield \tcode{false}. Otherwise, if a pointer \tcode{p}
3675+
compares greater than a pointer \tcode{q}, \tcode{p>=q}, \tcode{p>q},
3676+
\tcode{q<=p}, and \tcode{q<p} all yield \tcode{true} and \tcode{p<=q},
3677+
\tcode{p<q}, \tcode{q>=p}, and \tcode{q>p} all yield \tcode{false}.
3678+
Otherwise, the result of each of the operators is unspecified.
36563679

36573680
\pnum
36583681
If both operands (after conversions) are of arithmetic or enumeration type, each
@@ -3673,42 +3696,48 @@
36733696

36743697
\pnum
36753698
The \tcode{==} (equal to) and the \tcode{!=} (not equal to) operators
3676-
have the same semantic restrictions, conversions, and result type as the
3677-
relational operators except for their lower precedence and truth-value
3678-
result.
3679-
\enternote
3680-
\tcode{a<b == c<d} is \tcode{true} whenever \tcode{a<b} and \tcode{c<d}
3681-
have the same truth-value.
3682-
\exitnote
3699+
group left-to-right. The operands shall have arithmetic, enumeration, pointer,
3700+
or pointer to member type, or type \tcode{std::nullptr_t}. The operators
3701+
\tcode{==} and \tcode{!=} both yield \tcode{true} or \tcode{false}, i.e., a
3702+
result of type \tcode{bool}. In each case below, the operands shall have the
3703+
same type after the specified conversions have been applied.
3704+
36833705
\indextext{comparison!pointer}%
36843706
\indextext{comparison!pointer~to function}%
3685-
Pointers of the same type (after pointer
3686-
conversions) can be compared for equality. Two pointers of the same type
3687-
compare equal if and only if they are both null, both point to the same
3707+
\pnum
3708+
If at least one of the operands is a pointer, pointer
3709+
conversions~(\ref{conv.ptr}) and qualification conversions~(\ref{conv.qual})
3710+
are performed on both operands to bring them to their composite pointer type
3711+
(Clause~\ref{expr}). Comparing pointers is defined as follows:
3712+
Two pointers compare equal if they are both null, both point to the same
36883713
\indextext{address}%
3689-
function, or both represent the same address~(\ref{basic.compound}).
3714+
function, or both represent the same address~(\ref{basic.compound}), otherwise
3715+
they compare unequal.
36903716

36913717
\pnum
3692-
In addition, pointers to members can be compared, or a pointer to member
3693-
and a null pointer constant. Pointer to member
3718+
If at least one of the operands is a pointer to member, pointer to member
36943719
conversions~(\ref{conv.mem}) and qualification
3695-
conversions~(\ref{conv.qual}) are performed to bring them to a common
3696-
type. If one operand is a null pointer constant, the common type is the
3697-
type of the other operand. Otherwise, the common type is a pointer to
3698-
member type similar~(\ref{conv.qual}) to the type of one of the
3699-
operands, with a cv-qualification signature~(\ref{conv.qual}) that is
3700-
the union of the cv-qualification signatures of the operand types.
3701-
\enternote
3702-
this implies that any pointer to member can be compared to a null
3703-
pointer constant.
3704-
\exitnote
3705-
If both operands are null, they compare equal. Otherwise if only one is
3706-
null, they compare unequal. Otherwise if either is a pointer to a
3707-
virtual member function, the result is unspecified. Otherwise they
3708-
compare equal if and only if they would refer to the same member of the
3709-
same most derived object~(\ref{intro.object}) or the same subobject if
3720+
conversions~(\ref{conv.qual}) are performed on both operands to bring them to
3721+
their composite pointer type (Clause~\ref{expr}).
3722+
Comparing pointers to members is defined as follows:
3723+
3724+
\begin{itemize}
3725+
\item
3726+
If two pointers to members are both the null member pointer value, they compare
3727+
equal.
3728+
3729+
\item
3730+
If only one of two pointers to members is the null member pointer value, they
3731+
compare unequal.
3732+
3733+
\item
3734+
If either is a pointer to a virtual member function, the result is unspecified.
3735+
3736+
\item
3737+
Two pointers to members compare equal if they would refer to the same member of
3738+
the same most derived object~(\ref{intro.object}) or the same subobject if
37103739
indirection with a hypothetical object of the associated
3711-
class type were performed.
3740+
class type were performed, otherwise they compare unequal.
37123741
\enterexample
37133742

37143743
\begin{codeblock}
@@ -3726,15 +3755,25 @@
37263755
int (D::*pdr)() = pr;
37273756
bool x = (pdl == pdr); // \tcode{false}
37283757
\end{codeblock}
3729-
\exitexample
3758+
\exitexample
3759+
\end{itemize}
3760+
3761+
\pnum
3762+
Two operands of type \tcode{std::nullptr_t} or one operand of type
3763+
\tcode{std::nullptr_t} and the other a null pointer constant compare equal.
37303764

37313765
\pnum
3732-
If two operands of type \tcode{std::nullptr_t} are compared, the result is
3733-
\tcode{true} if the operator is \tcode{==}, and \tcode{false} otherwise.
3766+
If two operands compare equal, the result is \tcode{true} for
3767+
\tcode{operator==} and \tcode{false} for \tcode{operator!=}. If two operands
3768+
compare unequal, the result is \tcode{false} for \tcode{operator==} and
3769+
\tcode{true} for \tcode{operator!=}. Otherwise, the result of each of the
3770+
operators is unspecified.
37343771

37353772
\pnum
3736-
Each of the operators shall yield \tcode{true} if the specified relationship is
3737-
true and \tcode{false} if it is false.
3773+
If both operands are of arithmetic or enumeration type, the usual arithmetic
3774+
conversions are performed on both operands; each of the operators shall yield
3775+
\tcode{true} if the specified relationship is true and \tcode{false} if it is
3776+
false.
37383777

37393778
\rSec1[expr.bit.and]{Bitwise AND operator}%
37403779
\indextext{expression!bitwise~AND}%
@@ -3975,20 +4014,22 @@
39754014
the usual arithmetic conversions are performed to bring them to a common
39764015
type, and the result is of that type.
39774016

3978-
\item The second and third operands have pointer type, or one has
3979-
pointer type and the other is a null pointer constant, or both are
3980-
null pointer constants, at least one of which is non-integral; pointer
4017+
\item One or both of the second and third operands have pointer type; pointer
39814018
conversions~(\ref{conv.ptr}) and qualification
39824019
conversions~(\ref{conv.qual}) are performed to bring them to their
3983-
composite pointer type~(\ref{expr.rel}). The result is of the composite
4020+
composite pointer type (Clause~\ref{expr}). The result is of the composite
39844021
pointer type.
39854022

3986-
\item The second and third operands have pointer to member type, or one
3987-
has pointer to member type and the other is a null pointer constant;
4023+
\item One or both of the second and third operands have pointer to member type;
39884024
pointer to member conversions~(\ref{conv.mem}) and qualification
3989-
conversions~(\ref{conv.qual}) are performed to bring them to a common
3990-
type, whose cv-qualification shall match the cv-qualification of either
3991-
the second or the third operand. The result is of the common type.
4025+
conversions~(\ref{conv.qual}) are performed to bring them to their composite
4026+
pointer type (Clause~\ref{expr}). The result is of the composite pointer type.
4027+
4028+
\item
4029+
Both the second and third operands have type \tcode{std::nullptr_t} or one has
4030+
that type and the other is a null pointer constant. The result is of type
4031+
\tcode{std::nullptr_t}.
4032+
39924033
\end{itemize}
39934034

39944035
\rSec1[expr.ass]{Assignment and compound assignment operators}%

source/overloading.tex

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -3461,8 +3461,8 @@
34613461
\end{codeblock}
34623462

34633463
\pnum
3464-
For every \term{T}, where \term{T} is an enumeration type, a pointer type, or
3465-
\tcode{std::nullptr_t}, there exist candidate operator functions of the form
3464+
For every \term{T}, where \term{T} is an enumeration type or a pointer type,
3465+
there exist candidate operator functions of the form
34663466

34673467
\begin{codeblock}
34683468
bool operator<(@\term{T}@, @\term{T}@);
@@ -3474,8 +3474,8 @@
34743474
\end{codeblock}
34753475

34763476
\pnum
3477-
For every pointer to member type \term{T} there exist candidate operator functions of
3478-
the form
3477+
For every pointer to member type \term{T} or type \tcode{std::nullptr_t} there
3478+
exist candidate operator functions of the form
34793479

34803480
\begin{codeblock}
34813481
bool operator==(@\term{T}@, @\term{T}@);

source/utilities.tex

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5793,7 +5793,7 @@
57935793

57945794
\begin{itemdescr}
57955795
\pnum\returns \tcode{less<V>()(a.get(), b.get())},
5796-
where \tcode{V} is the composite pointer type~(\ref{expr.rel}) of \tcode{T*} and \tcode{U*}.
5796+
where \tcode{V} is the composite pointer type (Clause~\ref{expr}) of \tcode{T*} and \tcode{U*}.
57975797

57985798
\pnum \enternote
57995799
Defining a comparison operator allows \tcode{shared_ptr} objects to be

0 commit comments

Comments
 (0)