【发布时间】:2018-10-18 16:31:03
【问题描述】:
我阅读了有关内置比较运算符的信息。我想知道为什么成员指针没有排序运算符(<、<=、>、>=)。比较结构实例化的两个成员的地址是有效的。
http://en.cppreference.com/w/cpp/language/operator_comparison:
3) 如果在一个非联合类类型的对象中,两个指针指向具有相同成员访问权限的不同非静态数据成员,或者指向这些成员的子对象或数组元素,则递归地指向后者的指针声明的成员比较大。换句话说,三种成员访问模式中的每一种中的类成员都是按照声明的顺序在内存中定位的。
使用 adressof 运算符 (&) 和成员指针解引用运算符 (.*) 可以比较地址,但需要一个实例。
我的问题:
为什么没有用于成员指针的内置排序运算符?
如何在没有实例的情况下比较两个成员指针?
我的方法:
#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
};
我考虑过offsetof-macro,但它没有将成员指针作为参数。
【问题讨论】:
-
这是一个有趣的问题,但是比较可以用来做什么呢?
-
@wally 这些“奇怪”比较的重点通常是将它们用作地图(或某些类似数据结构)中的键。
标签: c++ comparison-operators member-pointers