2011-04-11 65 views
4
template<class T, typename U> ptrdiff_t foo(T U::* m) 
{ 
    // return offset 
} 

如何在此上下文中获得字段'm'的偏移量?我宁愿使用编译时表达式。指向成员的偏移量

在此先感谢您的帮助。此致敬礼

+0

这可能是一个坏主意。为什么不使用指向成员类型的指针? – GManNickG 2011-04-11 06:40:39

+0

嗯,你究竟是什么意思?上面的参数是一个指向成员的指针... – 0xbadf00d 2011-04-12 06:32:01

+0

正确,并且保留它。偏移量太简单,不适用于大多数C++类(非POD)。 – GManNickG 2011-04-12 06:47:22

回答

3

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

+0

使用成员指针调用'offsetof',只有成员名是不合法的。 (在许多实现中它可能工作,但给出了这种事情的模糊程度,它可能会破坏任何编译器更新) – Yakk 2014-03-09 17:00:38

+0

Hi @Yakk。我不太清楚你的意思。如果你点击“offsetof”(上面)这个词,它将把你带到宏的文档。它对我来说看起来很洁净。通过一个“成员指针”来指您是一个指针结构的成员?例如struct s {int i; char * p; }; size_t n = offsetof(struct s,p); – 2014-03-09 18:10:36

4

@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) 
    ); 
} 
+2

你在这里是一个空指针的dereferensing。这是不允许的,除非你正在实现这个库,并在offsetof宏中使用一个特殊的配置。有人打我到-1。 – 2011-04-11 07:16:22

+0

这就是宏的offsetof:(size_t)&reinterpret_cast ((((s *)0) - > m))。有什么不同? – 0xbadf00d 2011-04-11 09:26:09

+2

区别在于offsetof对** particual编译器**是这样做的,只是因为库设计器与编译器编写器做了特殊处理。那么它可能工作。在其他编译器中,offsetof用作特殊的__builtin_offsetof函数。或者其他一些技巧。在库中有一个offsetof的主要原因是你不能轻易地编写它,你需要编译器的特别支持。 – 2011-04-11 11:16:30

0

简单的答案是,你不能。如果类型U是POD, 可以使用宏offsetof,但在形式上,它是未定义的 行为如果类型不是POD:取决于编译器, 您将得到编译时错误,或者完全错误结果一些 的时候。而且你不能在指向成员的指针上使用它。你 必须调用它与类的名称,并且成员的名称 。