#pragma once
#include<memory>
#include<type_traits>
#include<memory_resource>#include"data_structure/internal/node_handler.hpp"#include"internal/dev_env.hpp"
#include"internal/types.hpp"namespaceuni{template<classValueType,classAllocator=std::allocator<ValueType>>structpersistent_stack{usingvalue_type=ValueType;usingsize_type=internal::size_t;structnode_type;usingnode_handler=node_handlers::cloneable<Allocator>::templatehandler<node_type>;usingallocator_type=typenamenode_handler::allocator_type;usingnode_pointer=typenamenode_handler::node_pointer;structnode_type{value_typevalue;node_pointernext;node_type(node_pointer_next,value_type_value)noexcept(NO_EXCEPT):value(_value),next(_next){}template<class...Args>node_type(node_pointer_next,Args&&...args)noexcept(NO_EXCEPT):value(std::forward<Args>(args)...),next(_next){}};private:size_type_size=0;node_pointer_head;[[no_unique_address]]node_handler_node_handler;public:explicitpersistent_stack(constallocator_type&allocator=allocator_type())noexcept(NO_EXCEPT):_node_handler(allocator){};persistent_stack(constpersistent_stack&source,constallocator_type&allocator)noexcept(NO_EXCEPT):_size(source._size),_head(source._head),_node_handler(allocator){};persistent_stack(persistent_stack&&source,constallocator_type&allocator)noexcept(NO_EXCEPT):_size(source._size),_head(source._head),_node_handler(allocator){};inlineautoclone()constnoexcept(NO_EXCEPT){return*this;}inlineboolempty()constnoexcept(NO_EXCEPT){return!this->_head;}inlinesize_typesize()constnoexcept(NO_EXCEPT){returnthis->_size;}inlinevalue_typetop()constnoexcept(NO_EXCEPT){assert(!this->empty());returnthis->_head->value;}template<std::convertible_to<value_type>T=value_type>requiresstd::is_move_constructible_v<T>inlinevalue_typetop_or(T&&v)constnoexcept(NO_EXCEPT){if(this->empty())returnstatic_cast<value_type>(std::forward<T>(v));elsereturnthis->top();}inlineauto&clear()noexcept(NO_EXCEPT){this->_head.reset();this->_size=0;return*this;}template<std::convertible_to<value_type>T=value_type>inlineauto&push(T&&x)noexcept(NO_EXCEPT){this->_head=this->_node_handler.create(this->_head,std::forward<T>(x));++this->_size;return*this;}template<class...Args>inlineauto&emplace(Args&&...args)noexcept(NO_EXCEPT){this->_head=this->_node_handler.create(this->_head,std::forward<Args>(args)...);++this->_size;returnthis->_head->value;}inlineauto&pop()noexcept(NO_EXCEPT){assert(!this->empty());this->_head=this->_head->next;--this->_size;return*this;}};namespacepmr{template<classT>usingpersistent_stack=uni::persistent_stack<T,std::pmr::polymorphic_allocator<T>>;}// namesapce pmr}// namespace uni