#include <iostream>
#include <queue>
#include <list>
#include <string>
#include <vector>   // only used to demonstrate the underlying container concept; queue defaults to deque

// Helper function: print queue contents (note: this will empty the queue and is only for demonstration)
template <typename T>
void printAndClear(std::queue<T> q) {
    std::cout << "Queue contents (front to back): ";
    while (!q.empty()) {
        std::cout << q.front() << " ";
        q.pop();
    }
    std::cout << std::endl;
}

// Demonstrate basic queue usage
void demoBasicOperations() {
    std::cout << "\n========== 1. Basic operations ==========" << std::endl;
    std::queue<int> q;

    // Insert elements
    q.push(10);
    q.push(20);
    q.push(30);
    std::cout << "After push 10, 20, 30" << std::endl;
    std::cout << "q.front() = " << q.front() << std::endl;  // 10
    std::cout << "q.back()  = " << q.back() << std::endl;   // 30
    std::cout << "q.size()  = " << q.size() << std::endl;   // 3
    std::cout << "q.empty() = " << std::boolalpha << q.empty() << std::endl; // false

    // Pop element
    q.pop();
    std::cout << "\nAfter pop" << std::endl;
    std::cout << "q.front() = " << q.front() << std::endl;  // 20
    std::cout << "q.size()  = " << q.size() << std::endl;   // 2

    // Common way to clear a queue: assign an empty queue or pop repeatedly
    std::queue<int> emptyQ;
    q.swap(emptyQ);  // equivalent to q = emptyQ;
    std::cout << "\nAfter clearing the queue, q.empty() = " << q.empty() << std::endl;
}

// Demonstrate emplace (C++11 onward, construct element in place)
void demoEmplace() {
    std::cout << "\n========== 2. emplace usage ==========" << std::endl;
    std::queue<std::string> q;
    // emplace forwards constructor arguments directly, avoiding temporary copies
    q.emplace("Hello, ");
    q.emplace(3, 'C');   // constructs "CCC"
    q.emplace("queue!");
    std::cout << "After inserting three strings with emplace:" << std::endl;
    printAndClear(q);
}

// Demonstrate swap (member and non-member)
void demoSwap() {
    std::cout << "\n========== 3. swap queue contents ==========" << std::endl;
    std::queue<int> q1, q2;
    q1.push(1); q1.push(2);
    q2.push(100); q2.push(200); q2.push(300);

    std::cout << "Before swap:" << std::endl;
    std::cout << "q1 size = " << q1.size() << " (1,2) | ";
    std::cout << "q2 size = " << q2.size() << " (100,200,300)" << std::endl;

    // member swap
    q1.swap(q2);

    std::cout << "After swap (member swap):" << std::endl;
    std::cout << "q1 size = " << q1.size() << " (100,200,300) | ";
    std::cout << "q2 size = " << q2.size() << " (1,2)" << std::endl;

    // non-member std::swap also works (requires <utility> or <algorithm>, but <iostream> includes it indirectly)
    std::swap(q1, q2);
    std::cout << "After another swap (std::swap):" << std::endl;
    std::cout << "q1 size = " << q1.size() << " (1,2) | ";
    std::cout << "q2 size = " << q2.size() << " (100,200,300)" << std::endl;
}

// Demonstrate using a different underlying container (for example std::list)
void demoDifferentContainer() {
    std::cout << "\n========== 4. Using std::list as underlying container ==========" << std::endl;
    // The second template parameter of queue specifies the underlying container,
    // which must support front(), back(), push_back(), pop_front()
    std::queue<double, std::list<double>> q;
    q.push(3.14);
    q.push(2.718);
    q.push(1.414);
    std::cout << "Queue with list as underlying container:" << std::endl;
    std::cout << "front = " << q.front() << ", back = " << q.back() << std::endl;
    q.pop();
    std::cout << "After pop, new front = " << q.front() << std::endl;
    // Note: you cannot directly iterate over the underlying list,
    // but you can traverse by repeatedly popping elements; printing is omitted here
    while (!q.empty()) q.pop();  // clear
}

// Demonstrate comparison operators (==, !=, <, >, <=, >=)
void demoComparisonOperators() {
    std::cout << "\n========== 5. Comparison operators ==========" << std::endl;
    std::queue<int> a, b, c;
    a.push(1); a.push(2); a.push(3);
    b.push(1); b.push(2); b.push(3);
    c.push(1); c.push(2); c.push(4);

    std::cout << "a: 1,2,3 | b: 1,2,3 | c: 1,2,4" << std::endl;
    std::cout << "a == b : " << (a == b) << std::endl;  // true
    std::cout << "a == c : " << (a == c) << std::endl;  // false
    std::cout << "a < c  : " << (a < c) << std::endl;   // true (element-wise comparison, 3 < 4)
    std::cout << "a > c  : " << (a > c) << std::endl;   // false
}

// Demonstrate practical usage: process a task queue
void demoTaskProcessing() {
    std::cout << "\n========== 6. Practical example: processing a task queue ==========" << std::endl;
    std::queue<std::string> tasks;
    tasks.push("Task A");
    tasks.push("Task B");
    tasks.push("Task C");

    std::cout << "Start processing tasks:" << std::endl;
    while (!tasks.empty()) {
        std::string current = tasks.front();
        tasks.pop();
        std::cout << "Processing: " << current << " (remaining tasks: " << tasks.size() << ")" << std::endl;
        // simulate processing...
    }
    std::cout << "All tasks completed!" << std::endl;
}

int main() {
    std::cout << "========== C++ std::queue Complete Usage Guide ==========" << std::endl;

    demoBasicOperations();
    demoEmplace();
    demoSwap();
    demoDifferentContainer();
    demoComparisonOperators();
    demoTaskProcessing();

    std::cout << "\nDemo complete. All queue usage examples have been demonstrated." << std::endl;
    return 0;
}

results matching ""

    No results matching ""