text: #pragma once
  
  #include <deque>
  
  template<typename T>
  class Queue
  {
  public:
  	Queue() = default;
  
  	Queue(const Queue& otherQueue)
  		: m_deque(otherQueue.m_deque)
  	{
  	}
  
  	Queue(Queue&& otherQueue)
  		: m_deque(std::move(otherQueue.m_deque))
  	{
  	}
  
  	Queue& operator =(const Queue& otherQueue)	{ m_deque = otherQueue.m_deque; return *this; }
  	Queue& operator =(Queue&& otherQueue)		{ m_deque = std::move(otherQueue.m_deque); return *this; }
  
  	// Capacity
  	bool IsEmpty() const						{ return m_deque.empty(); }
  	size_t Size() const							{ return m_deque.size(); }
  
  	// Erases all elements from the Queue, but doesn't free its memory
  	void Clear()								{ m_deque.clear(); }
  
  	// Push element to the queue
  	void PushFront(const T& element)			{ m_deque.push_front(element); }
  	void PushFront(T&& element)					{ m_deque.push_front(std::move(element)); }
  	void PushBack(const T& element)				{ m_deque.push_back(element); }
  	void PushBack(T&& element)					{ m_deque.push_back(std::move(element)); }
  
  	template<class... Args>
  	T& EmplaceFront(Args&&... args)				{ return m_deque.emplace_front(std::forward<Args>(args)...); }
  
  	template<class... Args>
  	T& EmplaceBack(Args&&... args)				{ return m_deque.emplace_back(std::forward<Args>(args)...); }
  
  	// Pop element from the queue
  	bool PopFront(T& outElement)
  	{
  		if(!IsEmpty())
  		{
  			outElement = std::move(m_deque.front());
  			m_deque.pop_front();
  			return true;
  		}
  		return false;
  	}
  
  	bool PopBack(T& outElement)
  	{
  		if(!IsEmpty())
  		{
  			outElement = std::move(m_deque.back());
  			m_deque.pop_back();
  			return true;
  		}
  		return false;
  	}
  
  	void Swap(Queue& otherQueue)				{ m_deque.swap(otherQueue.m_deque); }
  
  private:
  	std::deque<T> m_deque;
  };
  