Date: Tue, 16 Sep 2025 09:25:30 +0800
I'll reply to this answer to add more details about my question.
On Mon, 15 Sept 2025 at 21:48, David Brown via Std-Discussion
<std-discussion_at_[hidden]> wrote:
>
> On 15/09/2025 14:48, Yongwei Wu via Std-Discussion wrote:
> > As per my understanding of the C++ standard, operators like < should not
> > be used to compare unrelated pointers, but function objects like
> > std::less can. Is there any reason why we cannot make p1 < p2 just
> > behave like std::less<T*>{}(p1, p2)? I really cannot think any.
> >
> > Any insights on this?
> >
>
> First ask yourself, is there any reason why you would want to compare
> unrelated pointers for ordering? If there are no real-world use-cases
> that can't be handled well enough using the existing C++ language, then
> there is no reason to change.
Very simple, it is far too easy to err on the side of UB, as most
(yes, I believe, most) C++ programmers do not know that one should NOT
compare arbitrary pointers with operator<.
> Such comparisons can be helpful for implementations of standard
> functions like memmove(). But those are part of the implementation - a
> standard library implementation can use compiler-specific features or
> implementation-specific knowledge to implement its functions
> efficiently, relying on features that are not part of the C++ standards.
Non-standard-library coders need similar mechanisms, and I certainly
want it to be portable.
> There might be occasions when user-written code can have an interest in
> orderings of pointers, such as for writing specialised memory management
> routines or perhaps holding unrelated pointers in a searchable data
> structure. I would expect that for those situations, you can simple
> cast to uintptr_t and compare those without any overhead. (Use the
> casts just for the comparisons - avoid casting back and forth between
> uintptr_t and pointer types because the compiler might lose useful
> information.) You will probably find that this is what is being the
> std::less implementation in many C++ libraries.
I think of this problem when trying to detect things like the
vector::insert self-reference, and I know of some code that needs to
have similar in-range conditionals.
> As for why comparing unrelated pointers (except for equality) is UB,
> this might be because C and C++ can work on systems with complicated
> address spaces. Modern x86, ARM, and other common "big" processors have
> nice, simple flat address spaces. But some other targets have
> complicated address spaces - the same underlying representation in a
> pointer might refer to different physical addresses depending on its
> type or how the pointer is used. (An example of a currently available
> processor with multiple address spaces and with C++ support is the AVR
> microcontroller family.) On many such systems, it would be possible to
> define a comparison relationship - but why bother, if the results don't
> actually mean anything?
Good to know there are still such systems. I started programming in
the segmented memory model age, but to me it was long gone now. So I
did not see the need to keep such wording now.
Another angle: Can we make operator< on pointers
implementation-defined, as more often than not it has quite
well-defined behaviour? UB is a dangerous thing, and it is better to
have as little UB as possible. (I also hate the fact that sometimes
compilers utilize UB as a crazy licence to kill, and I do not want
anything like that for something as simple as p1 < p2.)
On Mon, 15 Sept 2025 at 21:48, David Brown via Std-Discussion
<std-discussion_at_[hidden]> wrote:
>
> On 15/09/2025 14:48, Yongwei Wu via Std-Discussion wrote:
> > As per my understanding of the C++ standard, operators like < should not
> > be used to compare unrelated pointers, but function objects like
> > std::less can. Is there any reason why we cannot make p1 < p2 just
> > behave like std::less<T*>{}(p1, p2)? I really cannot think any.
> >
> > Any insights on this?
> >
>
> First ask yourself, is there any reason why you would want to compare
> unrelated pointers for ordering? If there are no real-world use-cases
> that can't be handled well enough using the existing C++ language, then
> there is no reason to change.
Very simple, it is far too easy to err on the side of UB, as most
(yes, I believe, most) C++ programmers do not know that one should NOT
compare arbitrary pointers with operator<.
> Such comparisons can be helpful for implementations of standard
> functions like memmove(). But those are part of the implementation - a
> standard library implementation can use compiler-specific features or
> implementation-specific knowledge to implement its functions
> efficiently, relying on features that are not part of the C++ standards.
Non-standard-library coders need similar mechanisms, and I certainly
want it to be portable.
> There might be occasions when user-written code can have an interest in
> orderings of pointers, such as for writing specialised memory management
> routines or perhaps holding unrelated pointers in a searchable data
> structure. I would expect that for those situations, you can simple
> cast to uintptr_t and compare those without any overhead. (Use the
> casts just for the comparisons - avoid casting back and forth between
> uintptr_t and pointer types because the compiler might lose useful
> information.) You will probably find that this is what is being the
> std::less implementation in many C++ libraries.
I think of this problem when trying to detect things like the
vector::insert self-reference, and I know of some code that needs to
have similar in-range conditionals.
> As for why comparing unrelated pointers (except for equality) is UB,
> this might be because C and C++ can work on systems with complicated
> address spaces. Modern x86, ARM, and other common "big" processors have
> nice, simple flat address spaces. But some other targets have
> complicated address spaces - the same underlying representation in a
> pointer might refer to different physical addresses depending on its
> type or how the pointer is used. (An example of a currently available
> processor with multiple address spaces and with C++ support is the AVR
> microcontroller family.) On many such systems, it would be possible to
> define a comparison relationship - but why bother, if the results don't
> actually mean anything?
Good to know there are still such systems. I started programming in
the segmented memory model age, but to me it was long gone now. So I
did not see the need to keep such wording now.
Another angle: Can we make operator< on pointers
implementation-defined, as more often than not it has quite
well-defined behaviour? UB is a dangerous thing, and it is better to
have as little UB as possible. (I also hate the fact that sometimes
compilers utilize UB as a crazy licence to kill, and I do not want
anything like that for something as simple as p1 < p2.)
-- Yongwei Wu URL: http://wyw.dcweb.cn/
Received on 2025-09-16 01:25:48