The change that removed the wording about comparisons on pointers to void was N3624. Reading over the paper, I get the impression that it wasn't meant to change anything about the semantics of previously valid comparisons between pointers to void. If we read the current standard with that in mind, we could say that "unequal pointers to objects" doesn't mean "unequal values of pointer to object type" (which would exclude void*) but rather "unequal values of pointer type, which point to objects". (According to the footnote, for the purposes of this section, we assume that a past-the-end pointer points to an object at index n.) If that's the case, then the comparison in question is well-defined. Perhaps you could open a defect report, noting the implementation divergence.

On Fri, Oct 15, 2021 at 6:53 AM Paul Keir via Std-Discussion <> wrote:
Is the result of comparing pointers to cv void (e.g. void*) using the relational operators unspecified?

GCC, Clang and MSVC++ don't give a warning for code evaluated at runtime; and wouldn't need to. But, as part of a constant expression evaluation (constexpr), a comparison between void pointers, if it does lead to an unspecified result, *would* be expected to produce a compilation error. Currently, GCC and MSVC++ will accept the code below; Clang will reject it.

constexpr bool test()
  int arr[2]{};
  void *p1 = &arr[0];
  void *p2 = &arr[1];

  return p1 < p2;

int main(int argc, char *argv[])
  return test();

Section 7.7 (Constant expressions) [expr.const] states that *where the result is unspecified*, C++ excludes relational (and equality) operators, from the category of "core constant expression":

    An expression E is a core constant expression unless the evaluation of E, following the rules of the abstract machine ([intro.execution]), would evaluate one of the following:
    (5.23) a three-way comparison ([expr.spaceship]), relational ([expr.rel]), or equality ([expr.eq]) operator where the result is unspecified;


Which then leads to the question of whether the result *is* unspecified. Using *equality operators* on void pointers, is specified: Section 7.6.10 (Equality operators) [expr.eq] refers simply to "pointers", and void* is clearly there considered a pointer (see also [dcl.ptr]). Among other things, it then states that if two pointers both represent the same address, they compare equal.

Section 7.6.9 (Relational operators) [expr.rel], however, explains its semantics not in terms of "pointers", but only of "pointers to objects". It explains only how to compare "unequal pointers to objects".

Is void* a pointer to an object? Section 6.8.2 (Compound types) [basic.compound] states that the type of a pointer to cv void is called an "object pointer type", but immediately clarifies that it is *not* a pointer-to-object type.

So it seems that [expr.rel] does not specify the comparison of void pointers.

C++11 [expr.rel] had a clause about comparing void pointers, but this was removed in C++14 and since.

Concretely, should the code example above compile?

Please consider the environment and think before you print.

The University of the West of Scotland is a registered Scottish charity. Charity number SC002520.

This e-mail and any attachment is for authorised use by the intended recipient(s) only. It may contain proprietary material, confidential information and/or be subject to legal privilege. It should not be copied, disclosed to, retained or used by, any other party. If you are not an intended recipient then please promptly delete this e-mail and any attachment and all copies and inform the sender.

Please note that any views or opinions presented in this email are solely those of the author and do not necessarily represent those of the University of the West of Scotland.

As a public body, the University of the West of Scotland may be required to make available emails as well as other written forms of information as a result of a request made under the Freedom of Information (Scotland) Act 2002.
Std-Discussion mailing list

Brian Bi