我可以/如何将指向字段成员的指针视为指向成员的指针?

Can I / how can I treat a pointer to a field's member as a pointer to member?

我必须在枚举和我的对象的字段之间创建一个映射。

enum E {
   FIRST,
   SECOND,
   THIRD
};

struct A {
   int i;
   int j;
};

我可以使用 get 和 set 函数以及 switch-case 以简单的方式做到这一点,但假设我是个疯子并且为每个枚举值写两行而不是一行让我非常困扰。

所以我创建了一个枚举值映射到指向 A 成员的指针。

static std::map<E, int A::*> m = {
   {FIRST, &A::i},
   {SECOND, &A::j}
};

我对这张地图很满意。我现在可以用两种方式编写简洁的翻译函数,而且性能对我来说并不重要。

但是,悲剧了!高管们已经说过,我们现在将字段映射到 B,而不是 A,这也是一个 int 结构,但是这次,其中一些被分组到子结构中。

struct A {
   int i;
   int j;
};

struct B {
   A a;
   int k;
   int l;
};

仍然创建此类地图的干净且不依赖于未定义行为的方式是什么?

static std::map<E, int B::*> m2 = {
   {FIRST, &B::k},
   {SECOND, &B::l},
   {THIRD, /* somehow access a::i as a B::* */}
};

您可以使用函数指针映射而不是成员指针。

此外,由于您的键是从 0 开始的整数并且结构可能不是动态的,因此更有效的映射是数组。

示例:

using get = int&(B&);
constexpr get* m[] = {
    [](B& b) -> int& { return b.k; },   // FIRST
    [](B& b) -> int& { return b.l; },   // SECOND
    [](B& b) -> int& { return b.a.i; }, // THIRD
};