Felipe Lavratti
Felipe Lavratti

Reputation: 2967

`container_of` macro in C++ with the same signature as C's

I have code that uses the famous container_of macro to implement a macro-only linked list library.

It works perfectly in C. Now I want to support C++ on it, so I need a container_of replacement for C++ that matches the following signature:

container_of(ptr, type, member)

The C implementation is this:

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

Upvotes: 7

Views: 4213

Answers (1)

Felipe Lavratti
Felipe Lavratti

Reputation: 2967

Tailored myself a solution. It would be better without templates:

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)

Because, in C, we commonly use typeof along with container_of to fetch the type of a variable, such as this:

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

We can provide an extra macro to implement the typeof equivalence as well:

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

Upvotes: 7

Related Questions