2011-04-11 64 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:取決於編譯器, 您將得到編譯時錯誤,或者完全錯誤結果一些 的時候。而且你不能在指向成員的指針上使用它。你 必須調用它與類的名稱,並且成員的名稱 。