【问题标题】:Can I / how can I treat a pointer to a field's member as a pointer to member?我可以/如何将指向字段成员的指针视为指向成员的指针?
【发布时间】:2020-12-16 11:45:06
【问题描述】:

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

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::* */}
};

【问题讨论】:

  • 你可以试着弄乱offsetof,但这确实是一件很奇怪的事情。
  • 唉,维护这段代码的人...大批?您可以使用常量作为索引。
  • “疯子”和“干净”不矛盾吗? Imho clean 将编写一个开关(并放弃编码风格以将每个案例放在一行中;)
  • Here 是另一种映射。它看起来同样可怕但“有效”(直到您开始进行更改并且一切都崩溃了)。
  • 说真的,您要的是干净的解决方案还是黑客?两者都有自己的位置,但通常不在同一个项目中;)

标签: c++ pointer-to-member


【解决方案1】:

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

此外,由于您的键是从 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
};

【讨论】:

    猜你喜欢
    • 2018-03-24
    • 1970-01-01
    • 2013-05-02
    • 2011-12-11
    • 2023-03-12
    • 2021-12-03
    • 1970-01-01
    • 1970-01-01
    • 2014-02-19
    相关资源
    最近更新 更多