I came across this code recently, in the context of intrusive lists:
template<typename T> struct Node{
T *next;
T *prev;
Node(): next(nullptr), prev(nullptr){}
};
/*
* Intrusive doubly-linked-list
*
* */
template<typename T, Node<T> T::*NODE>
class List{
T *head;
T *tail;
public:
List():head(nullptr), tail(nullptr){}
~List() {clear();}
/*
* Add an element at the head of list
* @param elem item to be inserted
* */
void add_to_front(T *elem){
Node<T> *node = &(elem->*NODE);
assert((node->next) == nullptr);
assert((node->prev) == nullptr);
node->next = head;
if(head != nullptr){
Node<T> *temp = &(head->*NODE);
temp->prev = elem;
}
head = elem;
if(tail == nullptr)
tail = head;
}
//other member functions ,etc.
..
..
};
I see similar code in the boost intrusive list library (member_hook<class T, class Hook, Hook T::* PtrToMember>
).
My question is regarding the template argument Node<T> T::*NODE
. I am not an expert in C++, but I have never come across this particular syntax before, and don't know what to search for to understand it.
What does it mean? What is its purpose, and what should I interpret it as - "NODE is a pointer to a Node, belonging to T"? That doesn't make sense to me, because T isn't known to contain specific members ahead of time, and as far as I know, ::
is used to resolve scope.
As well, if someone could clarify the use of *NODE
in this line, for instance : Node<T> *node = &(elem->*NODE);
, that would help me understand what this is being used for.
It's a member pointer. NODE
is a pointer to a member of T
that has type Node<T>
.
Similarly, foo->*bar
is shorthand for (*foo).*bar
where .*
is the dereference-pointer-to-member operator. elem->*NODE
accesses the member of *elem
pointed to by NODE
.