4

Pointers in C++ do not have a defined total ordering unless they fall within a narrow set of criteria, such as being all parts of the same subobject or array (expr.rel/4, defns.order.ptr).

In fact, to even provide a basic ordering guarantee, you can't use operator< but instead must use std::less with pointers from different subobjects -- otherwise the result is not well defined behavior. From comparisons.general/2:

For templates less, greater, less_­equal, and greater_­equal, the specializations for any pointer type yield a result consistent with the implementation-defined strict total order over pointers (defns.order.ptr).

However, in C++ we also have the (optional) type std::uintptr_t -- which is defined to be an unsigned integer value large enough to store a pointer, with the property that its capable of surviving a round-trip from void* to std::uintptr_t and back to void* without any loss-of-data. unsigned integer types also have a well-defined total-ordering -- which leads me to my question.

Is it at all reasonable to expect that a std::uintptr_t from different sources have a well-defined ordering, within the definition of the C++ Abstract Machine?

I'm not asking whether this would work in practice, but whether this is even feasible to assume that this is well-defined behavior (my assumption is that it is not)


As a concrete example of a potential application of this, I am interested whether something like the following is formally well-defined behavior:

template <typename T>
auto my_typeid() -> std::uintptr_t
{
    // Each 'char' has a unique address since it's static and part of 
    // each unique template instantiation
    static const char s_data = 0;

    // Use this address for an ordering system, and for identity
    return reinterpret_cast<std::uintptr_t>(&s_data);
}
Human-Compiler
  • 11,022
  • 1
  • 32
  • 59
  • 2
    Some good reading [here](https://stackoverflow.com/a/13381081/4342498) for why it might not work. – NathanOliver Mar 18 '21 at 13:10
  • " to assume that this is well-defined behavior" Yes, it is reasonable to assume, but No, it is not well defined to order as things are laid out incrementally n memory. Instead you will get _some_ ordering. Note: 2 pointers with different bit patterns may point ot the same memory and may converted to the same or different `uintptr_t`. Thus `ptr1==ptr2` does not mean `(uintptr_t)ptr1 == (uintptr_t)ptr2`. – chux - Reinstate Monica Mar 18 '21 at 13:32
  • "with the property that its capable of surviving a round-trip from void* to std::uintptr_t and back to void* without any loss-of-data." --> is more like it round trips back to an equivalent pointer, not necessarily the same bit pattern. It would be useful to know your higher level goal. – chux - Reinstate Monica Mar 18 '21 at 13:38
  • @chux-ReinstateMonica I'm not sure how I follow that `ptr1==ptr2` can be true, but the `uintptr_t` version won't be. How can two pointers refer to the same object but have different bit patterns in standard C++? Are you considering the case of segmented architecture where two offsets refer to the same value? At any rate, feel free to throw that into an answer with a reference, and I'll gladly accept -- since this isn't far off from what I was expecting – Human-Compiler Mar 18 '21 at 13:41
  • @chux-ReinstateMonica _2 pointers with different bit patterns may point ot the same memory and may converted to the same or different `uintptr_t`_ Not sure why «different bit patterns» is necessary here. Conversion of 2 pointers with the same bit pattern to `uintptr_t` may produce 2 different integer values. – Language Lawyer Mar 18 '21 at 13:47
  • Good answers take time, short on that now. Yes, seg:offset is one case. An address also may have other bits in it to denote object size, write privilege, parity, ... Common flat addressing is not the only support addressing scheme for the language. – chux - Reinstate Monica Mar 18 '21 at 13:51
  • @LanguageLawyer OP's code "an ordering system, and for identity" hints at comparing integers for identity (equivalence), hence my comments about the equivalence as pointers do not certainly transfer to pointers converted to integers. GTG. – chux - Reinstate Monica Mar 18 '21 at 13:54

0 Answers0