Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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

Tags:

c++

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) );})
like image 826
Felipe Lavratti Avatar asked Nov 28 '16 18:11

Felipe Lavratti


People also ask

What is use of Container_of () macro?

As the name says, the container_of macro is used to find the container of the given field of a structure. The macro is defined in include/linux/kernel. h and looks like the following: #define container_of(ptr, type, member) ({ \ const typeof(((type *)0)->member) * __mptr ...

How does container_ of work?

Container_of macro is used to find the container structure address of the given member. In this example, I've declared one structure that contains two members ( mem1 , mem2 ). I'm going to get the structure address by using the member mem2 . Since we know the address of the structure sample1 already.


1 Answers

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 
like image 73
Felipe Lavratti Avatar answered Sep 19 '22 23:09

Felipe Lavratti