开发者

Offset of pointer to member

template<class T, typename U> ptrdiff_t foo(T U::* m)
开发者_JAVA技巧{
    // return offset
}

How I can get the offset of the field 'm' in this context? I would prefer to use am compile-time expression.

Thanks in advance for any help. Best regards


@Michael J

Thanks for your answer. This wasn't exactly what I was looking for, but it gives me the inspiration to doing that:

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


Sounds like you're looking for the offsetof() macro.


You can get the offset, but it's not free:

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

Unfortunately as you can see, this is not a constexpr, and so it can't be used in all scenarios you may want to. It also has a (very small) overhead, but it seems that the compiler just completely optimizes it out: https://godbolt.org/z/jGeox9.

If you are wondering if you can just sprinkle constexpr everywhere yourself and make this work, you can, and your compiler might even compile it and run, but using a cast to size_t is not valid in a constexpr despite the known defect that many compilers allow it.

Credits for this method do not belong to me, but to Daniel Weiler and this excellent gist: https://gist.github.com/graphitemaster/494f21190bb2c63c5516


The simple answer is that you can't. If the type U is a POD, you can use the macro offsetof, but formally, it's undefined behavior if the type isn't a POD: depending on the compiler, you'll get a compile time error, or simply wrong results some of the time. And you can't use it on a pointer to member. You have to invoke it with the name of the class, and the name of the member.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜