指向成员的指针的偏移量

时间:2011-04-11 05:49:57

标签: c++ templates member-pointers

template<class T, typename U> ptrdiff_t foo(T U::* m)
{
    // return offset
}

如何在此上下文中获取字段'm'的偏移量?我更喜欢使用am编译时表达式。

提前感谢您的帮助。最好的问候

4 个答案:

答案 0 :(得分:5)

@Michael J

感谢您的回答。这不是我想要的,但它给了我这样做的灵感:

template<class T, typename U>
std::ptrdiff_t member_offset(U T::* member)
{
    return reinterpret_cast<std::ptrdiff_t>(
        &(reinterpret_cast<T const volatile*>(NULL)->*member)
    );
}

答案 1 :(得分:3)

听起来你正在寻找offsetof()宏。

答案 2 :(得分:0)

简单的答案是,你做不到。如果U型是POD, 你可以使用宏offsetof,但正式来说,它是未定义的 行为如果类型不是POD:取决于编译器, 你会得到一个编译时错误,或者只是错误的结果 时间。而且你不能在指向成员的指针上使用它。您 必须使用类的名称和名称来调用它 会员。

答案 3 :(得分:0)

可以获得偏移量,但它不是免费的:

template <typename T, class C>
size_t memberOffset(T C::*member)
{
    C c {};
    return size_t(&(c.*member)) - size_t(&c);
}

// usage
struct Vector {
    int x;
    int y;
};

size_t off = memberOffset(&Vector::y);

不幸的是,正如您所看到的,这不是 constexpr,因此它不能用于您可能想要的所有场景。它也有(非常小的)开销,但编译器似乎只是完全优化了它:https://godbolt.org/z/jGeox9

如果您想知道是否可以自己将 constexpr 洒在各处并使其工作,您可以,并且您的编译器甚至可能编译并运行它,但是使用强制转换为 size_t 是无效的尽管存在许多编译器允许的已知缺陷,但在 constexpr 中。

此方法的功劳不属于我,而是属于 Daniel Weiler 和这个出色的要点:https://gist.github.com/graphitemaster/494f21190bb2c63c5516