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);
    }
};