2016-11-28 92 views
2

我有使用着名的container_of宏來實現僅宏鏈接列表庫的代碼。C++中的container_of宏具有與C相同的簽名

它完全在C.現在我要支持C++就可以了,所以我需要一個container_of替代C++,下面的簽名相匹配:

container_of(ptr, type, member) 

C實現是這樣的:

#define container_of(ptr, type, member) ({ \ 
      const typeof(((type *)0)->member) *__mptr = (ptr); 
      (type *)((char *)__mptr - offsetof(type,member));}) 

回答

0

爲我量身定做了一個解決方案。它沒有模板會更好:

template<class P, class M> 
size_t my_offsetof(const M P::*member) 
{ 
    return (size_t) &(reinterpret_cast<P*>(0)->*member); 
} 

template<class P, class M> 
P* my_container_of_impl(M* ptr, const M P::*member) 
{ 
    return (P*)((char*)ptr - my_offsetof(member)); 
} 

#define my_container_of(ptr, type, member) \ 
    my_container_of_impl (ptr, &type::member) 

因爲,在C,我們通常使用typeofcontainer_of一起去取一個變量的類型,比如這個:

typedef struct _AStruct 
{ 
    int data_field; 
} AStruct; 

AStruct as; 
int * ptr = &as.data_field; 

my_container_of(ptr, AStruct, data_field); 
my_container_of(ptr, typeof(as), data_field); 

我們可以提供一個額外的宏也實現了typeof等價:

#include <type_traits> 
#define my_typeof(___zarg) std::remove_reference<decltype(___zarg)>::type 
+1

也許downvoter可以幫我們一個忙,並解釋他們的批評? –

+0

'offsetof'是一個功能不佳的名稱,因爲它是標準庫中的一個宏。 – aschepler

+1

@aschelper這是一個很好的觀點,在實踐中我不會使用這些常用名稱,但將其留爲教學建議的「默認」。無論如何編輯了答案,在名稱上添加了my_前綴以避免碰撞。 –