I read about the builtin comparison operators. I wondered why there are no ordering operators(<
, <=
, >
, >=
) for member pointers. It is valid to compare the adresses of two members of an instantiation of a struct.
http://en.cppreference.com/w/cpp/language/operator_comparison:
3) If, within an object of non-union class type, two pointers point to different non-static data members with the same member access, or to subobjects or array elements of such members, recursively, the pointer to the later declared member compares greater. In other words, class members in each of the three member access modes are positioned in memory in order of declaration.
With the use of the adressof operator(&
) and the member pointer dereference operator(.*
) it is possible to compare the adresses, but an instance is needed.
My questions:
Why are there no builtin ordering operators for memberpointers?
How to compare two memberpointers without an instance?
My approach:
#include <iostream>
template<class S, class T>
int cmp_memberptr(T S::* a, T S::* b) {
//S s; // works, but needed instanciation
//S& s = std::declval<S>(); // error
S& s = *(S*)nullptr; // no instanciation, works (on my machine), but undefined behavior because of nullptr dereference (most compilers warn directly)!
// note: the precedence of .*:
return int(&(s.*a) < &(s.*b)) - int(&(s.*a) > &(s.*b));
};
struct Point { int x, y; };
int main(int argc, char const* const* argv) {
Point p;
#define tst(t) std::cout << #t " is " << ((t) ? "true" : "false") << '\n'
tst(&p.x < &p.y);
//tst(&Point::x < &Point::y); // the main problem!
tst(cmp_memberptr(&Point::x, &Point::y) < 0);
#undef tst
};
I considered the offsetof
-macro, but it does not take memberpointers as parameters.