这不起作用:
struct A {
int x1;
int x2;
};
int main() {
int A::*p1 = &A::x1;
set<int A::*> s;
s.insert( p1 ); // compile error: No operator<
unordered_set<int A::*> us;
us.insert( p1 ); // compile error: No hash function
}
我必须提供比较函数(用于set
)或散列函数(用于unordered_set
)。到目前为止,我想出的唯一方法是检查成员指针底层的原始字节:
struct XLess {
bool operator()( int A::* a, int A::*b ){
return memcmp( &a, &b, sizeof(a) ) < 0;
}
};
set<int A::*, XLess> s; // now appears to work
这是创建套装的可靠方法吗?它取决于相同的指针由相同的字节表示。有更好的解决方案吗?
答案 0 :(得分:1)
您可以展开std::less
和std::hash
运营商,BTW这是完全允许的。同样受到SO answer的启发,我创建了size_t getIndexOf(int A::* x)
进行散列并进行比较,见下文:
#include <set>
#include <unordered_set>
#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;
struct A {
int x1;
int x2;
};
typedef int (A::*x1);
vector<x1> canon;
size_t getIndexOf(int A::* x) {
auto it = find(canon.begin(), canon.end(), x);
if (it != canon.end()) return it - canon.begin();
canon.push_back(x);
return canon.size() - 1;
}
namespace std {
template<> struct less<int A::*> {
bool operator()(int A::* a, int A::*b){ return getIndexOf(a) < getIndexOf(b); }
};
template <> struct hash<int A::*>
{
size_t operator()(int A::* x) const
{
return getIndexOf(x);
}
};
}
int main() {
int A::*p1 = &A::x1;
int A::*p2 = &A::x2;
set<int A::*> s;
s.insert(p1);
s.insert(p2);
for (auto e : s) std::cout << getIndexOf(e) << std::endl;
unordered_set<int A::*> us;
us.insert(p1);
us.insert(p2);
for (auto e : us) std::cout << getIndexOf(e) << std::endl;
return 0;
}
答案 1 :(得分:1)
正式来说,它没有得到保证。在实践中,指向成员的指针 数据很可能只是一个简单的整数类型,而你 应该没问题。对于成员函数的指针,打开 另一方面:这些通常或多或少都很复杂 结构,通常包含填充,其内容为 未定义,所以你的技术不会起作用。
我也注意到,在第一个片段中,您已经使用过
std::unordered_set
,而不是std::set
。 std::unordered_set
不使用排序函数,而是使用等价函数
function(和==
是为指向成员的指针定义的)和
哈希函数。当然,实现哈希函数了
与实施订购相同的问题。
说完这个:为什么你想要这样一套呢?
成员指针(例如int A::*
)只能指向成员
给定类型的(不是给定类型的数组的成员)
类型),你可以编写成千上万的类
成员。最简单的解决方案可能就是使用
std::vector<int A::*>
和线性搜索(std::find
)
确定会员资格它可能比任何一个都快
std::set
,除非你确实有成千上万的成员。
答案 2 :(得分:0)
您的XLess比较器依赖于标准不保证的一个假设:
成员指针的所有位都是重要的,两个具有不同位模式的成员指针指向不同的成员
尽管如此,只要它们没有指向虚函数,它应该可以解决任何平面内存模型的实现:有两种方法可以指向这些:使用vtable,或包含函数地址。 / p>
另外,AFAICT没有更好的方法,因为你需要了解成员指针内部或者实现提供的比较。