// stack standard header
#ifndef _STACK_
#define _STACK_
#include <deque>

 #if defined(__ghs)
  #pragma ghs start_cxx_lib_header
  #pragma ghs startdata
  #if defined(__ghs_max_pack_value)
   #pragma pack (push, __ghs_max_pack_value)
  #endif /* defined(__ghs_max_pack_value) */
 #endif /* defined(__ghs) */
_STD_BEGIN
		// TEMPLATE CLASS stack
template<class _Ty,
	class _Container = deque<_Ty> >
	class stack
	{	// LIFO queue implemented with a container
public:
	typedef stack<_Ty, _Container> _Myt;
	typedef _Container container_type;
	typedef typename _Container::value_type value_type;
	typedef typename _Container::size_type size_type;
	typedef typename _Container::reference reference;
	typedef typename _Container::const_reference const_reference;

	stack()
		: c()
		{	// construct with empty container
		}

	stack(const _Myt& _Right)
		: c(_Right.c)
		{	// construct by copying _Right
		}

	explicit stack(const _Container& _Cont)
		: c(_Cont)
		{	// construct by copying specified container
		}

	_Myt& operator=(const _Myt& _Right)
		{	// assign by copying _Right
		c = _Right.c;
		return (*this);
		}

 #if _HAS_CPP11

 #if _HAS_NEW_SFINAE
	template<class _Alloc,
		class = enable_if_t<uses_allocator<_Container, _Alloc>::value,
			void> >
		explicit stack(const _Alloc& _Al)
		: c(_Al)
		{	// construct with allocator
		}

	template<class _Alloc,
		class = enable_if_t<uses_allocator<_Container, _Alloc>::value,
			void> >
		stack(const _Myt& _Right, const _Alloc& _Al)
		: c(_Right.c, _Al)
		{	// construct by copying specified container
		}

	template<class _Alloc,
		class = enable_if_t<uses_allocator<_Container, _Alloc>::value,
			void> >
		stack(const _Container& _Cont, const _Alloc& _Al)
		: c(_Cont, _Al)
		{	// construct by copying specified container
		}

 #else /* _HAS_NEW_SFINAE */
	template<class _Alloc>
		explicit stack(const _Alloc& _Al,
			typename enable_if<uses_allocator<_Container, _Alloc>::value,
				void>::type ** = 0)
		: c(_Al)
		{	// construct with allocator
		}

	template<class _Alloc>
		stack(const _Myt& _Right, const _Alloc& _Al,
			typename enable_if<uses_allocator<_Container, _Alloc>::value,
				void>::type ** = 0)
		: c(_Right.c, _Al)
		{	// construct by copying specified container
		}

	template<class _Alloc>
		stack(const _Container& _Cont, const _Alloc& _Al,
			typename enable_if<uses_allocator<_Container, _Alloc>::value,
				void>::type ** = 0)
		: c(_Cont, _Al)
		{	// construct by copying specified container
		}
 #endif /* _HAS_NEW_SFINAE */

 #endif /* _HAS_CPP11 */

 #if _HAS_RVALUE_REFERENCES
	stack(_Myt&& _Right)
		_NOEXCEPT_OP(is_nothrow_move_constructible<_Container>::value)
		: c(_STD move(_Right.c))
		{	// construct by moving _Right
		}

	explicit stack(_Container&& _Cont)
		: c(_STD move(_Cont))
		{	// construct by moving specified container
		}

 #if _HAS_NEW_SFINAE
	template<class _Alloc,
		class = enable_if_t<uses_allocator<_Container, _Alloc>::value,
			void> >
		stack(_Myt&& _Right, const _Alloc& _Al)
		: c(_STD move(_Right.c), _Al)
		{	// construct by moving specified container
		}

	template<class _Alloc,
		class = enable_if_t<uses_allocator<_Container, _Alloc>::value,
			void> >
		stack(_Container&& _Cont, const _Alloc& _Al)
		: c(_STD move(_Cont), _Al)
		{	// construct by moving specified container
		}

 #else /* _HAS_NEW_SFINAE */
	template<class _Alloc>
		stack(_Myt&& _Right, const _Alloc& _Al,
			typename enable_if<uses_allocator<_Container, _Alloc>::value,
				void>::type ** = 0)
		: c(_STD move(_Right.c), _Al)
		{	// construct by moving specified container
		}

	template<class _Alloc>
		stack(_Container&& _Cont, const _Alloc& _Al,
			typename enable_if<uses_allocator<_Container, _Alloc>::value,
				void>::type ** = 0)
		: c(_STD move(_Cont), _Al)
		{	// construct by moving specified container
		}
 #endif /* _HAS_NEW_SFINAE */

	_Myt& operator=(_Myt&& _Right)
		_NOEXCEPT_OP(is_nothrow_move_assignable<_Container>::value)
		{	// assign by moving _Right
		c = _STD move(_Right.c);
		return (*this);
		}

	void push(value_type&& _Val)
		{	// insert element at beginning
		c.push_back(_STD move(_Val));
		}

 #if _HAS_VARIADIC_TEMPLATES
	template<class... _Valty>
#if defined(__ghs) && !_HAS_CPP17
		void emplace(_Valty&&... _Val)
#else
		reference emplace(_Valty&&... _Val)
#endif /* defined(__ghs) && !_HAS_CPP17 */
		{	// insert element at beginning -- return added with C++17
#if !defined(__ghs) || _HAS_CPP17
		return
#endif /* !defined(__ghs) || _HAS_CPP17 */
			(c.emplace_back(_STD forward<_Valty>(_Val)...));
		}

 #else /* _HAS_VARIADIC_TEMPLATES */
#define _STACK_EMPLACE( \
	TEMPLATE_LIST, PADDING_LIST, LIST, C, X1, X2, X3, X4) \
	TEMPLATE_LIST(_CLASS_TYPE) \
		void emplace(LIST(_TYPE_REFREF_ARG)) \
		{	/* insert element at beginning */ \
		c.emplace_back(LIST(_FORWARD_ARG)); \
		}

_VARIADIC_EXPAND_0X(_STACK_EMPLACE, , , , )
#undef _STACK_EMPLACE
 #endif /* _HAS_VARIADIC_TEMPLATES */

 #endif /* _HAS_RVALUE_REFERENCES */

	bool empty() const
		{	// test if stack is empty
		return (c.empty());
		}

	size_type size() const
		{	// test length of stack
		return (c.size());
		}

	reference top()
		{	// return last element of mutable stack
		return (c.back());
		}

	const_reference top() const
		{	// return last element of nonmutable stack
		return (c.back());
		}

	void push(const value_type& _Val)
		{	// insert element at end
		c.push_back(_Val);
		}

	void pop()
		{	// erase last element
		c.pop_back();
		}

	const _Container& _Get_container() const
		{	// get reference to container
		return (c);
		}

	void swap(_Myt& _Right)
		_NOEXCEPT_OP(_NOEXCEPT_OP(_Swap_adl(_Right.c, _Right.c)))
		{	// exchange contents with _Right
		_Swap_adl(c, _Right.c);
		}

protected:
	_Container c;	// the underlying container
	};

#if defined(__ghs) && _HAS_CPP17
// Explicit deduction guides
template<class _Container,
	class = enable_if_t<!_Is_allocator_v<_Container>>>
	stack(_Container) -> stack<typename _Container::value_type, _Container>;

template<class _Container, class _Alloc,
	class = enable_if_t<
		!_Is_allocator_v<_Container> &&
		_Is_allocator_v<_Alloc> &&
		uses_allocator_v<_Container, _Alloc>
	>>
	stack(_Container, _Alloc)
	-> stack<typename _Container::value_type, _Container>;
#endif /* defined(__ghs) && _HAS_CPP17 */

		// stack TEMPLATE FUNCTIONS
 #if _HAS_CPP17
template<class _Ty,
	class _Container,
	class = enable_if_t<is_swappable<_Container>::value,
		void> > inline

 #else /* _HAS_CPP17 */
template<class _Ty,
	class _Container> inline
 #endif /* _HAS_CPP17 */

	void swap(stack<_Ty, _Container>& _Left,
		stack<_Ty, _Container>& _Right)
			_NOEXCEPT_OP(_NOEXCEPT_OP(_Left.swap(_Right)))
	{	// swap _Left and _Right stacks
	_Left.swap(_Right);
	}

 #if defined(__ghs) && _HAS_CPP17
// LWG 2766
template<class _Ty,
	class _Container,
	class _Dummy = void,
	class = enable_if_t<!is_swappable<_Container>::value,
		void> >

	void swap(stack<_Ty, _Container>&,
		stack<_Ty, _Container>&) = delete;
 #endif /* defined(__ghs) && _HAS_CPP17 */

template<class _Ty,
	class _Container> inline
	bool operator==(const stack<_Ty, _Container>& _Left,
		const stack<_Ty, _Container>& _Right)
	{	// test for stack equality
	return (_Left._Get_container() == _Right._Get_container());
	}

template<class _Ty,
	class _Container> inline
	bool operator!=(const stack<_Ty, _Container>& _Left,
		const stack<_Ty, _Container>& _Right)
	{	// test for stack inequality
	return (!(_Left == _Right));
	}

template<class _Ty,
	class _Container> inline
	bool operator<(const stack<_Ty, _Container>& _Left,
		const stack<_Ty, _Container>& _Right)
	{	// test if _Left < _Right for stacks
	return (_Left._Get_container() < _Right._Get_container());
	}

template<class _Ty,
	class _Container> inline
	bool operator>(const stack<_Ty, _Container>& _Left,
		const stack<_Ty, _Container>& _Right)
	{	// test if _Left > _Right for stacks
	return (_Right < _Left);
	}

template<class _Ty,
	class _Container> inline
	bool operator<=(const stack<_Ty, _Container>& _Left,
		const stack<_Ty, _Container>& _Right)
	{	// test if _Left <= _Right for stacks
	return (!(_Right < _Left));
	}

template<class _Ty,
	class _Container> inline
	bool operator>=(const stack<_Ty, _Container>& _Left,
		const stack<_Ty, _Container>& _Right)
	{	// test if _Left >= _Right for stacks
	return (!(_Left < _Right));
	}
_STD_END

 #if _HAS_CPP11
namespace std {
template<class _Ty,
	class _Container,
	class _Alloc>
	struct uses_allocator<stack<_Ty, _Container>, _Alloc>
		: uses_allocator<_Container, _Alloc>
	{	// true_type if container allocator enabled
	};
}	// namespace std
 #endif /* _HAS_CPP11 */

 #if defined(__ghs)
  #if defined(__ghs_max_pack_value)
   #pragma pack(pop)
  #endif /* defined(__ghs_max_pack_value) */
  #pragma ghs enddata
  #pragma ghs end_cxx_lib_header
 #endif /* defined(__ghs) */

#endif /* _STACK_ */

/*
 * Copyright (c) by P.J. Plauger. All rights reserved.
 * Consult your license regarding permissions and restrictions.
V8.03b/17:0063 */
