C++ 指向成员的指针集
这不起作用:C++ 指向成员的指针集,c++,pointer-to-member,C++,Pointer To Member,这不起作用: 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:
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
}
这是创建集合的可靠方法吗?它取决于由相同字节表示的相同指针。有更好的解决方案吗?您可以扩展
std::less
和std::hash
运算符,顺便说一句,这是完全允许的。同样受此启发,我创建了size\u 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;
}
#包括
#包括
#包括
#包括
#包括
使用名称空间std;
结构A{
int-x1;
int-x2;
};
typedef int(A::*x1);
矢量炮;
大小\u t getIndexOf(int A:::*x){
auto it=find(canon.begin(),canon.end(),x);
如果(it!=canon.end())返回它-canon.begin();
佳能。推回(x);
返回佳能.size()-1;
}
名称空间标准{
无模板结构{
bool操作符()(inta::*A,inta::*b){return getIndexOf(A) 对于(自动e:s)std::cout您的无X轴比较器依赖于一个标准不能保证的假设:
一个成员指针的所有位都是有效的,两个具有不同位模式的成员指针指向不同的成员。
尽管如此,只要它们不指向虚拟函数,它应该适用于任何具有平面内存模型的实现:有两种指向虚拟函数的方法:使用vtable或包含函数地址
此外,没有更好的方法,因为您需要了解成员指针的内部结构或实现提供的比较。正式地说,这是不保证的。实际上,指向成员的指针
数据很可能只是一个简单的整数类型,而您
应该没有问题。对于指向成员函数的指针,请参见
另一方面:这些通常或多或少都比较复杂
结构,并且通常将包含填充,其内容为
未定义,所以你的技术不起作用
我还注意到,在第一个片段中,您使用了
std::无序\u集
,而非std::集
std::无序\u集
不使用排序函数,而是等效函数
函数(并且为指向成员的指针定义了=
)和
一个散列函数。当然,实现散列函数
与实现排序相同的问题
话虽如此,你究竟为什么想要这样一套呢。
指向成员的指针(例如,int A::*
)只能指向成员
给定类型的(而不是给定类型的数组的成员)
类型),并且您无法使用数千个
最简单的解决方案可能就是使用
std::vector
,以及线性搜索(std::find
)
确定会员资格。它可能比任何一个
<代码> STD::设置< < /代码>,除非您有数千个成员。假设您想要的成员指针是“代码> SET/CODE >重要,这样<代码>向量<代码>不会切断它吗?@ SP2DANY,这是一个可能的工作。如果没有更好的功能,我会考虑。谢谢,只要指针不属于成员函数。。指向成员函数的指针必须假定它指向的函数可能是虚拟的,也可能不是虚拟的;一种常见的方法是使用与结构{void*ptrNonVirtual;int indexInVTable;}
等效的函数(使用空指针表示虚拟),如果指针大于int
,这可能会导致填充。这看起来不错。效率很低,但这是意料之中的,我不在乎,而且它不是线程安全的,可以轻松修复。谢谢。
#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;
}