2016-11-28 17 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で、私たちは一般的にこのような、変数の型を取得するためにcontainer_ofとともにtypeofを使用し、ので:

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); 

我々は、余分なを提供することができますマクロ

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

を実装することができます。 –

+0

'offsetof'は、標準ライブラリのマクロであるため、関数の名前が貧弱です。 – aschepler

+1

@aschelper実際にはこれらの一般的な名前は使用しませんが、教訓的な提案に対しては「デフォルト」のままにしておくのが良い点です。とにかく答えを編集し、名前に 'my_'という接頭辞を付けて衝突を避けました。 –

関連する問題