#include<iostream>
using std::cout;
using std::endl;
using std::string;
// queue implemented as an array
template<class T, int size = 100>
class ArrayQueue {
public:
    ArrayQueue() { 
        first = last = -1; 
    }
    void enqueue(T);
    T dequeue();
    bool isFull()  { 
        return first == 0 && last == size-1 || first == last + 1; 
    }
    bool isEmpty() { 
        return first == -1; 
    }
private:
    int first; // point to the first element that can be take away from the queue.
    int last; // point to the last element that was put into the queue recently.
    T storage[size];
};
template<class T, int size>
void ArrayQueue<T,size>::enqueue(T el) {
   if (!isFull())
        if (last == size-1 || last == -1) {
            storage[0] = el;
            last = 0;
            if (first == -1)
                first = 0;
        }
        else storage[++last] = el;
   else cout << "Full queue.\n";
}
// Please do check "!ifEmpty()" before invoke this API, else a SIGSEGV error will happen.
template<class T, int size>
T ArrayQueue<T,size>::dequeue() {   
    T tmp;
    tmp = storage[first];
    if (first == last)
         last = first = -1;
    else if (first == size-1)
         first = 0;
    else first++;
    return tmp;
}
int main()
{
    ArrayQueue<string, 5> strArray;
    strArray.enqueue("what ");
    strArray.enqueue("is ");
    strArray.enqueue("your ");
    strArray.enqueue("name? ");
    strArray.enqueue("I ");
    strArray.enqueue("am ");
    strArray.enqueue("Frank.");
    while(!strArray.isEmpty()){
        cout << strArray.dequeue();
    }
    cout << endl;
    
    // When queue is empty, dequeue() will cause segmentation fault.
    //cout << strArray.dequeue();
    return 0;
}