反转指向成员的指针(即获取包含结构的地址)

时间:2015-02-26 11:00:18

标签: c++ c++11 pointer-to-member offsetof

我有一个struct(Member),只能在其他一些struct(Container)中用作数据成员。按照惯例,成员的名字总是m。成员是否有可靠的方法来获取包含结构的地址?

template<typename Struct>
struct Member;
{
  const Struct& s = ??;
                    // this - &Struct::m
};

struct Container
{
   Member<Container> m;
};

我希望使用指向成员&Container::m的指针可能有助于从Member对象本身的地址计算回来?

2 个答案:

答案 0 :(得分:5)

不,你不能这样做。您可以在m内确定Container的偏移量,并使用指针算法猜测Container的结果地址,但这将是:

  • 不可靠
  • 容易发生灾难性错误
  • UB(因此可能导致包括时间旅行在内的症状 - no, seriously!

如果您已禁用所有优化,可能在几个平台上始终如一地工作,但是,真的,请,请不要。

Container的指针/引用传递给Member<Container>的构造函数(添加一个之后),或者进一步重新考虑您的设计。为什么成员需要知道封装它的对象?这几乎总是错误的(虽然有一些可用的用例)。

答案 1 :(得分:0)

不确定&#34;可靠&#34;以及它不应该被鼓励的那种黑客,但以下应该给你一个很好的起点:

#include <cassert>
#include <cstddef>
#include <type_traits>

template<typename Struct>
struct Member
{
    Struct const* s = (Struct*)&((char*)this)[-(int)offsetof(Struct, m)];
};

struct Container
{
    int abc;
    int def;

    Member<Container> m;
};



int main(int argc, char* argv[])
{
    assert(std::is_standard_layout<Container>::value);

    Container c;

    Container const *p1 = &c;
    Container const *p2 = c.m.s;

    bool test = p1 == p2;

    return 0;
}

我添加了一些成员,以便m有一个实际的非零偏移用于测试,但它也适用于零偏移。