Universal less<> for pointers in C++ standard

Solution 1:

Two pointers can be compared with using the comparison function objects less, greater etc. Otherwise, using blanket operator< etc, this is only possible if the pointers point to elements of the same array object or one past the end. Otherwise, results are unspecified.

20.3.3/8 in C++03

For templates greater, less, greater_equal, and less_equal, the specializations for any pointer type yield a total order, even if the built-in operators <, >, <=, >= do not.

No need to explicitly specialize and manually casting to size_t: That would lower the portability even, since the mapping of reinterpret_cast from pointers to integers is implementation defined and is not required to yield any order.


Edit: For a more detailed answer, see this one.

Solution 2:

No, it's not available. The standard says that pointers are only comparable with the built-in operators when they point to the same array or other memory block. That is, the block needs to have been allocated all at once, as opposed to two separate allocations that might happen to be adjacent to each other.

This is OK:

int x[2];
bool b = &x[0] < &x[1];

This is undefined:

int x0;
int x1;
bool b = &x0 < &x1;

This is OK:

struct foo {
  int x0;
  int x1;
};
foo f;
bool b = &f.x0 < &f.x1;

Both values are members of the same struct, so they belong to the same block of memory (namely, f's).

Practically speaking, though, there's nothing wrong with your custom-defined comparison.

However, your custom specialization is unnecessary, since the std::less template is defined for pointers, evidently. So this is OK:

int x0;
int x1;
std::less<int*> compare;
bool b = compare(&x0, &x1);

There's still no indication of what the result must be, but you're at least promised to have some result, as opposed to undefined behavior. You get a total order, but you don't know what order until you run it.