0

I've implemented a simple STL like Queue for practice purpose.

#ifndef QUEUE_H
#define QUEUE_H

#include <iostream>
#include <stdexcept>

template <typename T>
class queue {
public:
    ~queue();
    bool empty() const;
    size_t size() const;
    T const& front() const;
    T& front();
    void push(T const& data);
    void push(T&& data);
    //void emplace (T&&... args);
    // void swap (queue& x);
    void pop();

private:
    size_t elements = 0;
    struct node {
        T data;
        node *next;

        node(T const& data, node* next)
            : data(data)
            , next(next) {
        }

        node(T&& data, node* next)
            : data(std::move(data))
            , next(next) {
        }
    };
    node *head = nullptr;
    node *tail = nullptr;
};

template <typename T>
queue<T>::~queue() {
    node *curr;
    while(head) {
        curr = head;
        head = head->next;
        delete curr;
    }
}

template <typename T>
bool queue<T>::empty() const {
    return elements == 0;
//    return head == nullptr;
}

template <typename T>
size_t queue<T>::size() const {
    return elements;
}

template <typename T>
T const& queue<T>::front() const {
    if(head == nullptr)
        throw std::runtime_error("Invalid Action");
    return head->data;
}

template <typename T>
T& queue<T>::front() {
    if(head == nullptr)
        throw std::runtime_error("Invalid Action");
    return head->data;
}

template <typename T>
void  queue<T>::push(T const& data) {
    node *newNode = new node(data, nullptr);
    if(head == nullptr) head = newNode;
    else tail->next = newNode;
    tail = newNode;
    ++elements;
}
template <typename T>
void  queue<T>::push(T&& data) {
    node *newNode = new node(std::move(data), nullptr);
    if(head == nullptr) head = newNode;
    else tail->next = newNode;
    tail = newNode;
    ++elements;
}

template <typename T>
void  queue<T>::pop() {
    if(head == nullptr)
        throw std::runtime_error("Invalid Action");

    node* remove = head;
    head = head->next;
    delete remove;

    --elements;
}

#endif // QUEUE_H

Everything is okay. Can you give me some insights how I can implement C++11 emplace(Args&&... args) and swap(queue& x) efficiently? Complete Code will be appreciated but some idea will suffice.

Thanks in advance!

Kaidul
  • 15,409
  • 15
  • 81
  • 150

1 Answers1

3

swap(queue&) just has to swap each member of queue :

template <typename T> 
void queue<T>::swap (queue<T>& rhs)
{
    std::swap(elements, rhs.elements);
    std::swap(head, rhs.head);
    std::swap(tail, rhs.tail);
}

For emplace(Args&&... args) you have to add a node constructor to construct T from Args something like:

struct node {
    T data;
    node *next;

    template <typename ... Ts>
    node(node* next, Ts&&...args) :
        data(std::forward<Ts>(args)...),
        next(next)
    {}
};


template <typename T> 
template <typename... Ts>
void queue<T>::emplace(Ts&&... args)
{
    node *newNode = new node(nullptr, std::forward<Ts>(args)...);
    if (head == nullptr) head = newNode;
    else tail->next = newNode;
    tail = newNode;
    ++elements;
}
Jarod42
  • 203,559
  • 14
  • 181
  • 302
  • can you say where we should use `emplace` over `push` ? – Kaidul Aug 21 '14 at 19:33
  • 1
    @KaidulIslam: What is your problem with `swap`. It seems to works [Demo](https://ideone.com/9LSKo0). – Jarod42 Aug 21 '14 at 19:48
  • About [emplace vs push](http://stackoverflow.com/questions/24846781/can-i-use-always-emplace-to-replace-insert-for-single-element-insertion). – Jarod42 Aug 21 '14 at 19:55