Pointers to class member variables can be compared and the results depend on the declaration sequence. See this in the spec For instance this example in compiler explorer is valid and returns true (1):
struct A {
int a0 = 1;
int a1 = 2;
};
consteval int foo()
{
A a;
int* p1 = &a.a0;
int* p2 = &a.a1;
return p2 > p1;
}
int main()
{
return foo();
}
So one would expect that p2-p1
would return the distance, in int objects, between the pointers. And it does at runtime. compiler explorer
struct A {
int a0 = 1;
int a1 = 2;
};
int foo()
{
A a;
int* p1 = &a.a0;
int* p2 = &a.a1;
return p2 - p1;
}
int main()
{
return foo();
}
But not at compile time. GCC, CLANG, and MSVC all behave differently. GCC compiles and returns the expected value, CLANG complains UB, and MSVC compiles but returns 4, not 1, the distance in bytes! Compiler Explorer
CLANG: note: subtracted pointers are not elements of the same array
Which is correct?
You may not subtract pointers to objects unless they are elements of the same array. It is undefined behavior so you can get different results.
if P and Q point to, respectively, array elements i and j of the same array object x, the expression P - Q has the value i − j.
Otherwise, the behavior is undefined.
http://eel.is/c++draft/expr.add#5.2
clang is correct in labeling it as undefined behavior, gcc and msvc are correct in doing whatever they want because it is undefined behavior. If the function is consteval
then only clang is correct, the others should emit a diagnostic