Ch9.14: Sequential Container Adaptors

Overview

An adaptor is a class that wraps an existing container to provide a restricted interface. fast_io provides three adaptors. We will cover them in more detail in Chapter 10.

1. Adaptor Summary

Adaptor Default Container Access Pattern
::fast_io::stack<T> deque<T> LIFO (last in, first out)
::fast_io::queue<T> deque<T> FIFO (first in, first out)
::fast_io::priority_queue<T> vector<T> Highest-priority element on top

2. Example


#include <fast_io_dsal/stack.h>
#include <fast_io_dsal/queue.h>
#include <fast_io_dsal/priority_queue.h>
#include <fast_io.h>

int main() {
    // Stack: LIFO
    ::fast_io::stack<::std::size_t> stk;
    stk.push(1zu);
    stk.push(2zu);
    stk.push(3zu);
    ::fast_io::io::println("Top: ", stk.top()); // 3
    stk.pop(); // removes 3

    // Queue: FIFO
    ::fast_io::queue<::std::size_t> q;
    q.push(1zu);
    q.push(2zu);
    q.push(3zu);
    ::fast_io::io::println("Front: ", q.front()); // 1
    q.pop(); // removes 1

    // Priority queue: largest on top
    ::fast_io::priority_queue<::std::size_t> pq;
    pq.push(3zu);
    pq.push(1zu);
    pq.push(2zu);
    ::fast_io::io::println("Top: ", pq.top()); // 3
}

All adaptors provide pop_element() — it moves the top element out and pops in one operation, returning the moved value. This is more efficient than calling top() then pop() separately. They also provide get_container() to access the underlying container.

pop_element() example


// Stack: pop_element() moves and returns the top element
::fast_io::stack<::fast_io::string> stk;
stk.push(::fast_io::string{"hello"});
stk.push(::fast_io::string{"world"});

// Move the top element out and pop in one step
::fast_io::string top = stk.pop_element(); // top == "world", stk has 1 element

// Queue: pop_element() moves and returns the front element
::fast_io::queue<::fast_io::string> q;
q.push(::fast_io::string{"first"});
q.push(::fast_io::string{"second"});

::fast_io::string front = q.pop_element(); // front == "first", q has 1 element

// Priority queue: pop_element() moves and returns the highest-priority element
::fast_io::priority_queue<::std::size_t> pq;
pq.push(3zu);
pq.push(1zu);
pq.push(2zu);

::std::size_t highest = pq.pop_element(); // highest == 3, pq has 2 elements

There is also pop_element_unchecked() which skips the empty check for performance-critical code.

get_container() — Accessing the Underlying Container

get_container() returns a reference to the underlying container. This lets you iterate over all elements, query size(), or use any method the container provides:


#include <fast_io_dsal/stack.h>
#include <fast_io_dsal/queue.h>
#include <fast_io.h>

int main() {
    // Stack backed by deque (default)
    ::fast_io::stack<::std::size_t> stk;
    stk.push(10zu);
    stk.push(20zu);
    stk.push(30zu);

    // Query the underlying container
    ::fast_io::io::println("Size: ", stk.get_container().size()); // 3

    // Iterate over all elements in the underlying container
    for (auto const& elem : stk.get_container()) {
        ::fast_io::io::println(elem);
    }
    // Prints: 10, 20, 30 (bottom to top of stack)

    // Queue: iterate over elements in FIFO order
    ::fast_io::queue<::fast_io::string> q;
    q.push(::fast_io::string{"first"});
    q.push(::fast_io::string{"second"});
    q.push(::fast_io::string{"third"});

    for (auto const& elem : q.get_container()) {
        ::fast_io::io::println(elem);
    }
    // Prints: first, second, third (front to back of queue)
}

The non-const overload returns a mutable reference, so you can modify the underlying container directly. Both const and non-const overloads are provided.

Key takeaways