2014-12-04 56 views
2

我試圖從指向成員變量的指針獲取實際對象的指針。獲取對象的地址從它的指針到成員變量

是的,我知道有offsetof宏,但它需要一個成員變量的名稱,而不是指向成員變量的指針。

它實際上並不難實現,但我不確定它是100%標準的一致性代碼。

template <class T, class M, M T::*Ptr> 
constexpr std::ptrdiff_t offset_to_member() 
{ 
    return static_cast<char*>(static_cast<void*>(&(static_cast<T*>(nullptr)->*Ptr))) 
     - static_cast<char*>(nullptr); 
} 

template <class T, class M, M T::*Ptr> 
constexpr T* object_ptr_from_member(M *__ptr) 
{ 
    // reinterpret_cast is not allowed in constexpr function 
    return static_cast<T*>(static_cast<void*>(
      static_cast<char*>(static_cast<void*>(__ptr)) - offset_to_member<T, M, Ptr>())); 
} 

結果:http://ideone.com/1Z2nIR

鏘++和g ++編譯都沒有任何警告的代碼,但我需要比「似乎工作」等等。

代碼是否在C++ 11標準中有效?

+2

並且* this *如何不需要成員的「名稱」? – 2014-12-04 11:22:36

+1

沒有符合標準的方法來做到這一點。編譯器不會警告你,因爲你告訴他們關閉並編譯(強制轉換)。 – 2014-12-04 11:33:16

+1

@JoachimPileborg你能用'offsetof'實現'object_ptr_from_member'嗎?這是給定的條件。爲什麼我會問這個問題,我是否可以根據需要改變一切? – kukyakya 2014-12-04 11:37:26

回答

2
static_cast<T*>(nullptr)->*Ptr 
根據[expr.mptr.oper]/3,這觸發未定義行爲

相當於(*static_cast<T*>(nullptr)).*Ptr
而且不constexpr(因爲UB的精確) - [expr.const]/2:

條件表達式e芯常量表達式除非的e的 評價,下列規則抽象機 將評估以下表達式之一:

  • 將會有未定義行爲的操作。
+0

我不認爲第一條語句實際上對nullptr進行了解引用。如果它觸發UB,那麼除了編譯器擴展之外,沒有100%符合標準的'offsetof'實現,對吧? – kukyakya 2014-12-04 11:49:33

+0

@kukyakya正是如此。 – Columbo 2014-12-04 11:50:48

+0

@kukyakya:是的,'offsetof'不能在符合標準的代碼中實現。但是不用擔心,實施可以自由地完成任何必要的任務。 – Deduplicator 2014-12-04 11:51:00