Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/161.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 指向成员的指针集_C++_Pointer To Member - Fatal编程技术网

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;
}