I need an intrusive, sorted, double-linked list. I do not want to use boost::intrusive, so I'm doing this myself and running into an issue
For a doubly-linked list there are several operations, here is just one of them which will help to illustrate my point:
template<typename LIST, typename NODE>
void insertAfter(LIST *list, NODE *node, NODE *newNode)
{
newNode->prev_ = node;
newNode->next_ = node->next_;
if(nullptr == node->next_)
list->last_ = newNode;
else
node->next_->prev_ = newNode;
node->next_ = newNode;
}
Now suppose I have a set of objects that are in one such list BUT I want their guts private:
struct Object
{
private:
Object *prev_, *next_;
};
Now I create my List (please ignore the fact that when the list is empty there will be a nullptr exception...).
struct List
{
Object *first_, *last_;
void addObject(Object *o)
{
insertAfter(this, last_, o); // not correct when list empty
}
};
This will not compile because prev_ and next_ are private and insertAfter does not have access. It can be solved easily with this:
// Fwd decl
struct List;
struct Object
{
friend void insertAfter<List, Object>(List *, Object *, Object *);
private:
Object *prev_, *next_;
};
struct List
{
Object *first_, *last_;
void addObject(Object *o)
{
insertAfter(this, last_, o);
}
};
But this opens an access hole such that anyone can use insertAfter to affect Object's private members. What I really want is for List to be a friend of Object. I could solve this by not using templates for my linked list operation (use plain macros instead) but this obviously has its downside. What's the right way to go here?