2014-12-04 57 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