Can't use CRTP for inner class - c++

I'm trying to use CRTP for common functionality of several iterators types. As stated here
Using inner class with CRTP it's impossible to use CRTP for inner class, so I move the base iterator class out of the container class and inherit it inside the container for the iterator. But I still got
error: invalid use of incomplete type 'class ConcreteIteratorBase<Node<int>, std::iterator_traits<Node<int>*>, std::iterator<std::forward_iterator_tag, Node<int>, long int, Node<int>*, Node<int>&> >'
error.
Here is the minimal reproducible example:
#include <algorithm>
#include <functional>
#include <iostream>
#include <iterator>
#include <type_traits>
#include <utility>
template <typename T>
class NotEqFromEqMixin : public T
{
public:
bool operator!=(T const & other) const
{
return !(static_cast<T const &>(*this) == other);
}
};
template <typename Iterator, typename Traits, typename StdBase>
class IteratorHelperMixin : public NotEqFromEqMixin<Iterator>, public StdBase
{
public:
using pointer = typename Traits::pointer;
using reference = typename Traits::reference;
pointer operator->()
{
return &**this;
}
};
template <typename NodeT, typename TraitsT, typename StdBaseT>
class ConcreteIteratorBase
: public IteratorHelperMixin<ConcreteIteratorBase<NodeT, TraitsT, StdBaseT>, TraitsT, StdBaseT>
{
public:
using Super = IteratorHelperMixin<ConcreteIteratorBase<NodeT, TraitsT, StdBaseT>, TraitsT, StdBaseT>;
using typename Super::pointer;
using typename Super::reference;
ConcreteIteratorBase(pointer node) : node(node) {}
reference operator*() noexcept { return *node; }
bool operator==(ConcreteIteratorBase const & other) const noexcept { return node == other.node; }
protected:
pointer node;
};
template <typename Value>
class Node
{
public:
~Node() { delete next; }
Node* next = nullptr;
Value value;
};
template <typename Value>
class List
{
public:
using NodeType = Node<Value>;
void push(Value value)
{
NodeType* newNode = new NodeType();
newNode->value = value;
newNode->next = head;
head = newNode;
}
class iterator :
public ConcreteIteratorBase<
Node<Value>,
std::iterator_traits<Node<Value>*>,
std::iterator<std::forward_iterator_tag, Node<Value>>
>
{
using Super = ConcreteIteratorBase<
Node<Value>,
std::iterator_traits<Node<Value>*>,
std::iterator<std::forward_iterator_tag, Node<Value>>
>;
public:
iterator(NodeType* ptr = nullptr) : Super(ptr){}
iterator& operator++()
{
if (this->node)
{
this->node = this->node->next;
}
return *this;
}
Value& operator*()
{
return this->node->value;
}
bool operator==(const iterator& other) const
{
return this->node == other.node;
}
};
iterator begin()
{
return iterator{head};
}
iterator end()
{
return iterator{};
}
NodeType* head = nullptr;
};
int main(int , char**)
{
List<int> list;
for (int i = 0; i < 10; ++i)
{
list.push(i);
}
for(auto & val : list)
{
std::cout << val << " ";
}
std::cout << std::endl;
return 0;
}

Your issue is that you misuse CRTP as you do a circular inheritance:
ConcreteIteratorBase
-> IteratorHelperMixin<ConcreteIteratorBase, ..> -> NotEqFromEqMixin<ConcreteIteratorBase>
-> ConcreteIteratorBase
You should drop the inheritance here
template <typename T>
class NotEqFromEqMixin //: public T
// ^^^^^^^^^^^^
{
public:
bool operator!=(T const & other) const
{
return !(static_cast<T const &>(*this) == other);
}
};
Demo

Related

Out-of-line definition of 'depth' does not match any declaration in 'Tree<E>' (2 declaration errors)

This is a General Trees program, where I am trying to find the depth of the tree (depth of 2) and calculate the size of the directory. The two errors are declaration errors (towards the bottom of Tree.cpp) and can't seem to declare the function properly.
Tree.cpp
#include "Tree.h"
#include <iostream>
using namespace std;
template <typename E>
bool Tree<E>::Position::isRoot() const
{
if (u->parent == NULL)
return true;
else
return false;
}
template <typename E>
bool Tree<E>::Position::isExternal() const
{
return (u->child.empty());
}
template <typename E>
bool Tree<E>::Position::operator==(Tree<E>::Position p)
{
if (u == p.u)
return true;
else
return false;
}
template <typename E>
Tree<E>::Position::Position(TreeNode *v)
{
u = v;
}
template <typename E>
typename Tree<E>::Position Tree<E>::Position::parent()
{
return Tree<E>::Position(u->parent);
}
template <typename E>
typename Tree<E>::PositionList Tree<E>::Position::children()
{
return (u->child);
}
template <typename E>
E Tree<E>::Position::operator*()
{
return u->e;
}
template <typename E>
typename Tree<E>::Position Tree<E>::root()
{
return typename Tree<E>::Position(r);
}
template <typename E>
int Tree<E>::size() const
{
return this->n;
}
template <typename E>
bool Tree<E>::empty() const
{
return size() == 0;
}
template <typename E>
void Tree<E>::insert(E e, Tree<E>::Position p)
{
TreeNode *v = new TreeNode() ;
v->e = e;
if (empty())
v->parent = NULL;
else
v->parent = p.u;
if (!empty() )
{
p.u->child.insertBack(v);
}
else
{
v->parent = NULL;
r = v;
}
++n;
}
template <typename E>
NodeList<typename Tree<E>::Position> Tree<E>::Positions()
{
typename Tree<E>::PositionList list;
preorder(r, list);
return list;
}
template <typename E>
void Tree<E>::preorder(Tree<E>::Position p, Tree<E>::PositionList &pl)
{
pl.insertBack(p);
if (p.u->child.empty()==false)
for(typename Tree<E>::PositionList::Iterator ii = p.u->child.begin(); ii!= p.u->child.end(); ++ii)
preorder(*ii, pl);
}
template <typename E>
int Tree<E>::depth(Tree<E>::TreeNode& u, Tree<E>::Position& p) //ERROR: Out-of-line definition of 'depth' does not match any declaration in 'Tree<E>'
{
if (p.isRoot())
return 0;
else
return 1+depth(u, p.parent());
}
template <typename E>
int Tree<E>::directorySize(Tree<E>::TreeNode& u, Tree<E>::Position& p) //Out-of-line definition of 'directorySize' does not match any declaration in 'Tree<E>'
{
int s = size(p);
if (!p.isExternal())
{
PositionList ch = p.children();
for (typename Tree<E>::PositionList::Iterator q = ch.begin(); q != ch.end(); q++)
s += depth(u, *q);
cout << name(p) << ": " << s << endl;
}
return s;
}
Tree.h
#ifndef TREE_H
#define TREE_H
#include <cstdlib>
#include "NodeList.cpp"
template <typename E>
class Tree {
public:
class TreeNode;
public:
class Position // a node position
{
public:
E operator*(); // get element
Position parent();
NodeList<Position> children();
bool isRoot() const; // root node?
bool isExternal() const; // external node?
bool operator==(Position p);
int depth(const Tree& u, const Position& p); //DECLARED(ERROR) - DEPTH OF TWO FUNCTION
Position(typename Tree<E>::TreeNode *v);
Position(){}
typename Tree<E>::TreeNode *u;
friend class NodeList<Position>;
};
typedef NodeList<typename Tree<E>::Position> PositionList;
public:
class TreeNode
{
E e;
TreeNode *parent;
typename Tree<E>::PositionList child;
friend class Tree;
friend class Tree<E>::Position;
public:
TreeNode(){
parent = NULL;
}
TreeNode(E,Tree<E>::Position*, Tree<E>::PositionList*);
TreeNode& operator=(const TreeNode &t)
{
parent = t.parent;
child = t.child;
e = t.e;
}
};
public: // public functions of Tree
Tree<E>(){
n = 0;
}
int size() const; // number of nodes
bool empty() const; // is tree empty?
int directorySize(const TreeNode& u, const Position& p); //DECLARED(ERROR) - SIZE OF DIRECTORY
Position root();
PositionList Positions();
void insert(E e, Position p);
void preorder(Position p ,PositionList &pre_order);
private:
TreeNode *r;
int n;
friend class Position;
};
#endif
The error is only showing up in the Tree.cpp file.
There are multiple errors here:
The arguments are declared to be const qualified references but the const got dropped in the definitions.
depth() is a member of Tree<E>::Position not of Tree<E>.
The first parameter of depth() is a Tree<E> not a TreeNode.
Note that putting the code into a .cpp file is either confusion (if the intention is to include the file) or it will cause grief when using the template classes from another translation unit. This problem is unrelated to the question, though.

C++: Templated code compiles and runs fine with clang++, but fails with g++

Take a look at this implementation of a linked list:
#include <memory>
#include <type_traits>
#include <iostream>
using namespace std;
template<typename D>
class List {
struct Node {
shared_ptr<D> data;
Node* next;
Node(shared_ptr<D> d, Node* p, Node* n) : data(d), next(n) {}
~Node() {
data.reset();
delete next;
}
};
template <bool isconst = false>
struct iterator : public std::iterator<std::forward_iterator_tag, shared_ptr<D>> {
typedef std::forward_iterator_tag iterator_category;
typedef shared_ptr<D> value_type;
typedef std::ptrdiff_t Distance;
typedef typename conditional<isconst, const value_type&, value_type&>::type
Reference;
typedef typename conditional<isconst, const value_type*, value_type*>::type
Pointer;
typedef typename conditional<isconst, const Node*, Node*>::type
nodeptr;
iterator(nodeptr x = nullptr) : curr_node(x) {}
iterator(const iterator<false>& i) : curr_node(i.curr_node) {}
Reference operator*() const { return curr_node->data; }
Pointer operator->() const { return &(curr_node->data); }
template<bool A>
friend bool operator==(const iterator<A>& a, const iterator<A>& b) {
return a.curr_node == b.curr_node;
}
template<bool A>
friend bool operator!=(const iterator<A>& a, const iterator<A>& b) {
return !(a.curr_node == b.curr_node);
}
friend class List<D>;
iterator& operator++() {
curr_node = curr_node->next;
return *this;
}
private:
nodeptr curr_node;
};
public:
List() {
head = nullptr;
}
int len() const {
int ret = 0;
for (const auto& n : *this) {
ret++;
}
return ret;
}
~List() {
delete head;
}
std::ostream& dump(std::ostream &strm) const {
for (const auto s : *this) {
strm << *s << std::endl;
}
return strm;
}
iterator<false> begin() {
return iterator<false>(head);
}
iterator<false> end() {
return iterator<false>(nullptr);
}
iterator<true> begin() const {
return iterator<true>(head);
}
iterator<true> end() const {
return iterator<true>(nullptr);
}
private:
Node* head;
};
The part giving me problems is the iterator implementation for this list. The iterator template is supposed to provide both mutable and const iterators.
This is a program which uses this implementation:
#include "List.h"
#include <iostream>
int main( int argc, const char *argv[] ) {
List<int> l;
std::cout << l.len() << std::endl;
return 0;
}
The program compiles and runs fine if I use clang++, but the compilation fails for g++ with the following error:
In file included from t.cpp:1:
List.h: In instantiation of ‘struct List<int>::iterator<false>’:
List.h:136:5: required from ‘int List<D>::len() const [with D = int]’
t.cpp:7:24: required from here
List.h:64:21: error: redefinition of ‘template<bool A> bool operator==(const List<int>::iterator<isconst>&, const List<int>::iterator<isconst>&)’
friend bool operator==(const iterator<A>& a, const iterator<A>& b) {
^~~~~~~~
List.h:64:21: note: ‘template<bool A> bool operator==(const List<int>::iterator<isconst>&, const List<int>::iterator<isconst>&)’ previously declared here
List.h:69:21: error: redefinition of ‘template<bool A> bool operator!=(const List<int>::iterator<isconst>&, const List<int>::iterator<isconst>&)’
friend bool operator!=(const iterator<A>& a, const iterator<A>& b) {
^~~~~~~~
List.h:69:21: note: ‘template<bool A> bool operator!=(const List<int>::iterator<isconst>&, const List<int>::iterator<isconst>&)’ previously declared here
What's the cause of this error? How can I fix this?
The problem seems to be here:
template <bool isconst = false>
struct iterator : public std::iterator<std::forward_iterator_tag, shared_ptr<D>> {
template<bool A>
friend bool operator==(const iterator<A>& a, const iterator<A>& b) {
return a.curr_node == b.curr_node;
}
This is saying: For all values of isconst (the outer template parameter), define a template function template<bool A> bool operator==.
So instantiating iterator<true> will define template<bool A> bool operator==, and then instantiating iterator<false> will define template<bool A> bool operator== again, causing a redefinition error.
Solution: Remove the inner template. Have each instantiation of iterator only define its own operator==:
template <bool isconst = false>
struct iterator : public std::iterator<std::forward_iterator_tag, shared_ptr<D>> {
friend bool operator==(const iterator& a, const iterator& b) {
return a.curr_node == b.curr_node;
}
(Here iterator automatically refers to iterator<isconst>, i.e. the current instantiation.)

How to use rebind with custom allocator and custom list

I implemented my custom allocator and custom list container, which supports this allocator. They are defined like so:
template <typename T, size_t num_of_blocks = 16>
class MyAllocator {
public:
template <typename U>
struct rebind {
using other = MyAllocator<U, num_of_blocks>;
}
...dozens of standard methods
}
template <typename T, typename MyAlloc = std::allocator<Node<T>>>
class MyList {
private:
MyAlloc allocator;
...different methods which use allocator member
}
It all works good. So, in my client code, I can do it like:
auto my_list = MyList<int, MyAllocator<Node<int>,10>>{};
It works without errors and I see, that my custom allocator is used. But I do not like the way I use my custom allocator. In fact, I want my client code look like:
auto my_list = MyList<int, MyAllocator<int,10>>{};
My first attempt was this:
template <typename T, typename MyAlloc = std::allocator<T>>
class MyList {
private:
//MyAlloc allocator; // remove this member and rebind allocator to another one
typedef typename MyAlloc::template rebind<Node<T>>::other node_alloc_type;
node_alloc_type allocator; // I expect that my allocator now is of type MyAllocator<Node<T>, num_of_blocks>
... all the rest left unchanged
}
When however I run my new client code:
auto my_list = MyList<int, MyAllocator<int,10>>{};
I get these error messages:
can not convert 'int*' to 'Node*'in assignment
I'm not sure what I'm doing wrong and what I'm missing. So, how can I fix it? And what is the right way to use rebind in custom container?
EDIT
That is how my custom container looks like now:
//MyList.h
#include <memory>
template<typename T>
struct Node
{
Node(): m_next(nullptr){}
Node(T const &t):
m_value(t),
m_next(nullptr)
{}
T m_value;
Node* m_next;
};
template<typename T, typename MyAllocator = std::allocator<Node<T>>>
class MyList
{
private:
Node<T>* m_head = nullptr;
Node<T>* m_tail = nullptr;
MyAllocator my_allocator;
public:
class Iterator
{
private:
Node<T>* m_Node;
public:
Iterator(Node<T>* Node): m_Node(Node) {};
bool operator==(const Iterator& other)
{
return this == &other || m_Node == other.m_Node;
}
bool operator!=(const Iterator& other)
{
return !operator==(other);
}
T operator*()
{
if (m_Node)
{
return m_Node->m_value;
}
return T();
}
Iterator operator++()
{
Iterator i = *this;
if (m_Node)
{
m_Node = m_Node->m_next;
}
return i;
}
};
template<typename... Args>
void emplace(T v)
{
auto new_Node = my_allocator.allocate(1);
my_allocator.construct(new_Node, v);
if (m_head)
{
m_tail->m_next = new_Node;
} else {
m_head = new_Node;
new_Node->m_next = nullptr;
}
m_tail = new_Node;
}
Iterator begin() const
{
return Iterator(m_head);
}
Iterator end() const
{
return Iterator(nullptr);
}
};
At this moment there is no rebinding and I have to define it like
template<typename T, typename MyAllocator = std::allocator<Node<T>>>
class MyList
What I want is to define it like so:
template<typename T, typename MyAllocator = std::allocator<T>>
class MyList
EDIT
Here is a client code with standard allocator:
//main.cpp
#include "MyList.h"
int main()
{
MyList<int, std::allocator<Node<int>>> my_list;
//auto my_list = MyList<int, std::allocator<int>>; // will not work
for (int i = 0; i < 10; ++i)
{
my_list.emplace(i);
}
return 0;
}
These are the requirements for an allocator: http://en.cppreference.com/w/cpp/concept/Allocator
Notice that template rebind is optional.
Here is a list of what a container must have in order to qualify for the concept. http://en.cppreference.com/w/cpp/concept/AllocatorAwareContainer
Yes, gasp. I have searched in vain for a simple, or at least minimalist example. If all you need is a linked list, and you can use C++11 or later, use std::forward_list.
The following works in the example given.
template<typename T, typename MyAllocator = std::allocator<T>>
class MyList
{
private:
using node_alloc_t = typename std::allocator_traits<MyAllocator>::
template rebind_alloc<Node<T>>;
// create an object of type node allocator
node_alloc_t node_alloc;
// etc ....
public:
template<typename T>
void emplace(T v)
{
Node<T>* new_Node = node_alloc.allocate(1);
// Etc...
}
// etc...
};
All together now...
#include <memory>
#include <iostream>
template<typename T>
struct Node
{
Node() : m_next(nullptr) {}
Node(T const &t) :
m_value(t),
m_next(nullptr)
{}
T m_value;
Node<T>* m_next;
};
template<typename T, typename MyAllocator = std::allocator<T>>
class MyList
{
private:
using node_alloc_t = typename std::allocator_traits<MyAllocator>::
template rebind_alloc<Node<T>>;
// create an object of type node allocator
node_alloc_t node_alloc;
public:
class Iterator
{
private:
Node<T>* m_Node;
public:
Iterator(Node<T>* Node) : m_Node(Node) {};
bool operator==(const Iterator& other)
{
return this == &other || m_Node == other.m_Node;
}
bool operator!=(const Iterator& other)
{
return !operator==(other);
}
T operator*()
{
if (m_Node)
{
return m_Node->m_value;
}
return T();
}
Iterator operator++()
{
Iterator i = *this;
if (m_Node)
{
m_Node = m_Node->m_next;
}
return i;
}
};
template<typename T>
void emplace(T v)
{
Node<T>* new_Node = node_alloc.allocate(1);
node_alloc.construct(new_Node, v);
if (m_head)
{
m_tail->m_next = new_Node;
}
else {
m_head = new_Node;
new_Node->m_next = nullptr;
}
m_tail = new_Node;
}
Iterator begin() const
{
return Iterator(m_head);
}
Iterator end() const
{
return Iterator(nullptr);
}
};
int main()
{
MyList<int> my_list;
for (int i = 0; i < 10; ++i)
{
my_list.emplace(i);
}
for (auto i : my_list) {
std::cout << i << std::endl;
}
return 0;
}

How to call the base constructor if your class derives from unique_ptr

How can do I implement the SearchTree constructor with the T type parameter by calling it's superclass ?
template <class T>
class SearchTree: protected unique_ptr<Node<T> >{
public:
SearchTree<T>();
SearchTree<T>(const T &); //How do I implement this ?
}
template <class T>
class Node{
friend class SearchTree<T>;
public:
Node<T>();
Node<T>(const T & sl_):sl(sl_){};
private:
const T sl;
SearchTree<T> left,right;
}
Inheriting from std::unique_ptr is an instant indicator of a design flaw.
Encapsulation is the way to go. Perhaps start with something like this?
#include <memory>
template<class T> struct Node;
template<class T>
void add_node(std::unique_ptr<Node<T>>& next, T t);
template<class T>
struct Node
{
Node(T t) : _value(std::move(t)) {}
void add(T t)
{
if (t < _value) {
add_node(_left, std::move(t));
}
else if(t > _value) {
add_node(_right, std::move(t));
}
else {
// what?
}
}
T _value;
std::unique_ptr<Node<T>> _left, _right;
};
template<class T>
void add_node(std::unique_ptr<Node<T>>& next, T t)
{
if (next) {
next->add(std::move(t));
}
else {
next = std::make_unique<Node<T>>(std::move(t));
}
}
template<class T>
struct SearchTree
{
void add(T t) {
add_node(_root, std::move(t));
}
std::unique_ptr<Node<T>> _root;
};
int main()
{
SearchTree<int> tree;
tree.add(5);
tree.add(3);
tree.add(4);
}

Pointer to class member as template parameter (with type of the following class)

I'm trying to define an internal list as template class that has a type safe container_of member function. For that the template must include the type of the container and the offset where in the container the list can be found (a member pointer). (See below for an example in C).
It should be something like this:
template <class T, List * T::*MEMBER> class List { ... }
But in the <> the type List is not yet defined so it can't be used. My next try was:
template <class T, class L, L * T::*MEMBER> class List { ... };
class Container {
List<Container, List<???>, Container::list> list;
};
But what to put for the "???"? That would have to be the whole <>, including the ???. So you get an endless recursion.
Next I tried to cheat a bit on the type safety:
template <class T, void * T::*M>
class List {
public:
T * container_of() {
return (T *)(intptr_t(this) - intptr_t(&((T *)NULL)->M)); \
}
};
class Container {
public:
List<Container, Container::item1> item1;
};
But that gives me:
error: incomplete type 'Container' used in nested name specifier
List<Container, Container::item1> item1;
^
Using C preprocessor makros what I want looks like this:
#include <unistd.h> // for NULL
#include <stdint.h> // for intptr_t
#include <iostream>
#define LIST(TYPE, MEMBER) \
class List_ ## MEMBER ## _t { \
public: \
TYPE * container_of() { \
return (TYPE *)(intptr_t(this) - intptr_t(&((TYPE *)NULL)->MEMBER)); \
} \
} MEMBER
class Container {
public:
LIST(Container, item1);
LIST(Container, item2);
};
int main() {
Container c;
std::cout << "Container at " << &c << std::endl;
std::cout << "Container of item1 = " << c.item1.container_of() << std::endl;
std::cout << "Container of item2 = " << c.item2.container_of() << std::endl;
}
So can this be expressed with templates at all?
I found a solution. It's not 100% perfect but close.
The idea is to have 3 classes:
class Item;
template <class T, Item T::*M> class Iterator;
template <class T, Item T::*M> class Head;
The Item class contains the next/prev links that form the actual list in memory. This doesn't include the container type and position of the list inside the container and (on its own) is unsafe. But an Item has no method to modify the list. All modifications are done through the Iterator. Even construction is done using a Head to get an Iterator and that to initialize the next/prev pointers.
The Iterator class can be constructed from a container T and has operator ++, --, == and !=, can insert a container into the current position or move the container behind another iterator to its own list. The Iterator also has operator * which returns the current container and operator bool to say if the end of the list has been reached.
The Head class contains a special head and tail Item with prev==NULL and next==NULL respectively. They are special since they aren't inside an instance of container T and mark the begining and end of the list. Other than holding the end markers the Head provides methods to create Iterators pointing at the head, tail, first and last element. This allows iterating the list or inserting at the start or end.
There is a 4th class ConstIterator that is like Iterator but for const access.
Note: This is only minimally tested. The remaining errors are left for the reader to fix.
class Item;
template <class T, Item T::*M> class Iterator;
template <class T, Item T::*M> class ConstIterator;
template <class T, Item T::*M> class Head;
template<class T, Item T::*M>
T * container_of(Item *item) {
return (T *)(intptr_t(item) - intptr_t(&(((T *)NULL)->*M)));
}
template<class T, Item T::*M>
const T * container_of(const Item *item) {
return (const T *)(intptr_t(item) - intptr_t(&(((const T *)NULL)->*M)));
}
class Item {
public:
template <class T, Item T::*M> Item(Head<T, M> *head, T *container) {
assert((container_of<T, M>(this)) == container);
head->tail().insert_before(container);
}
~Item() {
if (next_) next_->prev_ = prev_;
if (prev_) prev_->next_ = next_;
next_ = NULL;
prev_ = NULL;
}
private:
template <class T, Item T::*M> friend class Iterator;
template <class T, Item T::*M> friend class ConstIterator;
template <class T, Item T::*M> friend class Head;
Item(Item *next__, Item *prev__) : next_(next__), prev_(prev__) { }
Item(const Item &) = delete;
Item & operator =(const Item &) = delete;
Item *next_;
Item *prev_;
};
template <class T, Item T::*M>
class Iterator {
public:
Iterator() : item_(NULL) { }
Iterator(T *container) : item_(&(container->*M)) { }
~Iterator() { }
operator bool() const {
assert(item_);
// not head and not tail
return ((item_->next_ != NULL) && (item_->prev_ != NULL));
}
T & operator *() {
assert(item_);
if ((item_->next_ == NULL) || (item_->prev_ == NULL)) {
// head or tail has no container
assert(false);
}
return *container_of<T, M>(item_);
}
T & operator ->() {
assert(item_);
if ((item_->next_ == NULL) || (item_->prev_ == NULL)) {
// head or tail has no container
assert(false);
}
return *container_of<T, M>(item_);
}
Iterator & operator ++() {
assert(item_);
assert(item_->next_);
item_ = item_->next_;
return *this;
}
Iterator & operator --() {
assert(item_);
assert(item_->prev_);
item_ = item_->prev_;
return *this;
}
bool operator ==(const Iterator &other) {
assert(item_);
return (item_ == other.item_);
}
bool operator !=(const Iterator &other) {
assert(item_);
return (item_ != other.item_);
}
void move_before(Iterator &from) {
assert(item_);
assert(from);
assert(item_->prev_);
Item *before = item_->prev_;
Item *after = item_;
Item *item = from.item_;
// remove from old list
item->next_->prev_ = item->prev_;
item->prev_->next_ = item->next_;
// insert into this list
item->next_ = after;
item->prev_ = before;
before->next_ = item;
after->prev_ = item;
}
void insert_before(T *container) {
assert(item_);
assert(item_->prev_);
Item *before = item_->prev_;
Item *after = item_;
Item *item = &(container->*M);
// insert into this list
item->next_ = after;
item->prev_ = before;
before->next_ = item;
after->prev_ = item;
}
private:
Item *item_;
};
template <class T, Item T::*M>
class ConstIterator {
public:
ConstIterator() : item_(NULL) { }
ConstIterator(const T *container) : item_(&(container->*M)) { }
~ConstIterator() { }
operator bool() const {
assert(item_);
// not head and not tail
return ((item_->next_ != NULL) && (item_->prev_ != NULL));
}
const T & operator *() const {
assert(item_);
if ((item_->next_ == NULL) || (item_->prev_ == NULL)) {
// head or tail has no container
assert(false);
}
return *container_of<T, M>(item_);
}
const T & operator ->() const {
assert(item_);
if ((item_->next_ == NULL) || (item_->prev_ == NULL)) {
// head or tail has no container
assert(false);
}
return *container_of<T, M>(item_);
}
ConstIterator & operator ++() {
assert(item_);
assert(item_->next_);
item_ = item_->next_;
return *this;
}
ConstIterator & operator --() {
assert(item_);
assert(item_->prev_);
item_ = item_->prev_;
return *this;
}
bool operator ==(const ConstIterator &other) const {
assert(item_);
return (item_ == other.item_);
}
bool operator !=(const ConstIterator &other) {
assert(item_);
return (item_ != other.item_);
}
private:
const Item *item_;
};
template <class T, Item T::*M>
class Head {
public:
Head() : head_(&tail_, NULL), tail_(NULL, &head_) { }
~Head() { }
Iterator<T, M> head() {
return Iterator<T, M>(container_of<T, M>(&head_));
}
ConstIterator<T, M> head() const {
return ConstIterator<T, M>(container_of<T, M>(&head_));
}
Iterator<T, M> tail() {
return Iterator<T, M>(container_of<T, M>(&tail_));
}
ConstIterator<T, M> tail() const {
return ConstIterator<T, M>(container_of<T, M>(&tail_));
}
Iterator<T, M> first() {
return Iterator<T, M>(container_of<T, M>(head_.next_));
}
ConstIterator<T, M> first() const {
return ConstIterator<T, M>(container_of<T, M>(head_.next_));
}
Iterator<T, M> last() {
return Iterator<T, M>(container_of<T, M>(tail_.prev_));
}
ConstIterator<T, M> last() const {
return ConstIterator<T, M>(container_of<T, M>(tail_.prev_));
}
bool is_empty() const {
return (first() == tail());
}
private:
Head(const Head &) = delete;
Head & operator =(const Head &) = delete;
Item head_;
Item tail_;
};