#pragma once
#include<concepts>
#include<utility>#include"internal/dev_env.hpp"namespaceuni{template<classIn,classOut=In>structqueue_by_stack{static_assert(std::same_as<typenameIn::value_type,typenameOut::value_type>);static_assert(std::common_reference_with<typenameIn::size_type,typenameOut::size_type>);usingvalue_type=In::value_type;usingsize_type=std::common_type_t<typenameIn::size_type,typenameOut::size_type>;protected:In_in;Out_out;private:inlinevoid_shift()noexcept(NO_EXCEPT){if(!this->_out.empty())return;while(!this->_in.empty()){this->_out.push(this->_in.top());this->_in.pop();}}public:queue_by_stack()noexcept=default;inlineboolempty()constnoexcept(NO_EXCEPT){returnthis->_in.empty()&&this->_out.empty();}inlineautosize()constnoexcept(NO_EXCEPT){returnthis->_in.size()+this->_out.size();}inlinedecltype(auto)front()noexcept(NO_EXCEPT){this->_shift();assert(!this->_out.empty());returnthis->_out.top();}template<std::convertible_to<value_type>T=value_type>requiresstd::is_move_constructible_v<T>inlinedecltype(auto)front_or(T&&val)constnoexcept(NO_EXCEPT){if(this->empty())returnstatic_cast<value_type>(std::forward<T>(val));elsereturnthis->front();}inlineauto&clear()noexcept(NO_EXCEPT){this->_in.clear(),this->_out.clear();return*this;}template<std::convertible_to<value_type>T=value_type>inlineauto&push(T&&val)noexcept(NO_EXCEPT){this->_in.push(std::forward<T>(val));return*this;}template<class...Args>inlinedecltype(auto)emplace(Args&&...args)noexcept(NO_EXCEPT){returnthis->_in.emplace(std::forward<Args>(args)...);}auto&pop()noexcept(NO_EXCEPT){this->_shift();assert(!this->_out.empty());this->_out.pop();return*this;}};}// namespace uni