estd::forward_list
Overview
forward_list<T>
provides a intrusive singly linked list. Intrusive means,
that through inheriting from a common base class. Each node provides the
necessary next pointer already and no wrapper node type with heap allocation is
required.
Usage
The next example shows a simple example of the usage of a forward_list:
Example
/**
* Wrapper for linked list of integers.
*/
class IntNode : public ::estd::forward_list_node<IntNode>
{
int _i;
public:
explicit IntNode(int const i) : _i(i) {}
int getI() const { return _i; }
};
void fillAndPrintList()
{
// Create two example nodes.
IntNode a(1);
IntNode b(2);
// Create list of IntNodes.
estd::forward_list<IntNode> list;
// Add nodes to the list.
list.push_front(a);
list.push_front(b);
// Iterate over list and print values.
estd::forward_list<IntNode>::const_iterator i;
for (i = list.cbegin(); i != list.cend(); ++i)
{
printf("Item = %d\n", i->getI());
}
}
forward_list
is also very useful in embedded systems that cannot use dynamic
memory allocation.
struct ICanFrameListener
{
virtual void frameReceived(uint32_t id, ::estd::slice<uint8_t> payload) = 0;
};
class CanFrameNotifier
{
// Room for at most 10 listeners.
::estd::declare::vector<ICanFrameListener*, 10> _listeners;
public:
bool addListener(ICanFrameListener& listener)
{
// Check if listener can be added.
if (_listeners.full())
{
return false;
}
// Add listener to list.
_listeners.emplace_back().construct(&listener);
return true;
}
};
In contrast to that, consider the example based on forward_list
. The pattern
is, that the interface inherits from forward_list_node
which makes
maintaining lists of that interface easy.
struct ICanFrameListener : public ::estd::forward_list_node<ICanFrameListener>
{
virtual void frameReceived(uint32_t id, ::estd::slice<uint8_t> payload) = 0;
};
class CanFrameNotifier
{
// List of listeners
::estd::forward_list<ICanFrameListener> _listeners;
public:
void addListener(ICanFrameListener& listener)
{
// Add listener to list.
_listeners.push_front(listener);
}
};