专栏文章

C++杂交容器 vector+deque(veque)

科技·工程参与者 10已保存评论 14

文章操作

快速查看文章及其快照的属性,并进行相关操作。

当前评论
14 条
当前快照
1 份
快照标识符
@mio3c71d
此快照首次捕获于
2025/12/02 12:41
3 个月前
此快照最后确认于
2025/12/02 12:41
3 个月前
查看原文
考虑到审核的原因,该文章不一定会实时更新。建议前往 luogu.me 观看。
创作原因(2025/8/26 11:34):
_Kagamine_Rin_: 会慢得跟屎一样,最关键的是我要封装 || AKPC: 用数组手写双端队列 || _Kagamine_Rin_: vector 在首尾添加很慢,deque 随机访问很慢,那能不能把这两个 STL 结合起来??
我认为这个容器需要达到下列要求:
  1. 大部分操作需要不慢于 vectordeque 的对应操作
  2. 所有操作需要比 vectordeque 对应操作中的其中一个快
  3. sizeof(veque) <= 40
  4. 代码长度 10240 Bytes\le 10240 \texttt{ Bytes}
  5. 最低能够在 C++11 (GCC 7) 的编译条件下运行

当前版本 0.9.1-beta

该版本已经达成了前三个目标。
  1. sizeof(veque) == 32
  2. 代码长度缩短至 24k,仍然未达成
  3. 目前至少需要 C++17 (GCC 7),未达成
更新内容:
  1. 移除了原先与很多 STL 不兼容的情况。
  2. 仅对 private 部分的函数或变量进行缩写,不影响使用。
CPP
#ifndef VEQUE_HEADER_GUARD
#define VEQUE_HEADER_GUARD

#include<algorithm>
#include<cstddef>
#include<cstring>
#include<iterator>
#include<limits>
#include<ratio>
#include<string>
#include<type_traits>
#include<stdexcept>
#include<utility>
//
namespace veque{
	struct fast_resize_traits{
		using allocation_before_front=std::ratio<1>;
		using allocation_after_back=std::ratio<1>;
		static constexpr auto resize_from_closest_side=true;
	};
	struct vector_compatible_resize_traits{
		using allocation_before_front=std::ratio<1>;
		using allocation_after_back=std::ratio<1>;
		static constexpr auto resize_from_closest_side=false;
	};
	struct std_vector_traits{
		using allocation_before_front=std::ratio<0>;
		using allocation_after_back=std::ratio<1>;
		static constexpr auto resize_from_closest_side=false;
	};
	struct no_reserve_traits{
		using allocation_before_front=std::ratio<0>;
		using allocation_after_back=std::ratio<0>;
		static constexpr auto resize_from_closest_side=false;
	};
	
	template<typename T,typename RT=fast_resize_traits,typename Alc=std::allocator<T>>
	class veque{
	public:
		using allocator_type=Alc;
		using alloc_traits=std::allocator_traits<allocator_type>;
		using value_type=T;
		using reference=T&;
		using const_reference=const T&;
		using pointer=T*;
		using const_pointer=const T*;
		using iterator=T*;
		using const_iterator=const T*;
		using reverse_iterator=std::reverse_iterator<iterator>;
		using const_reverse_iterator=std::reverse_iterator<const_iterator>;
		using difference_type=std::ptrdiff_t;
		using size_type=std::size_t;
		using ssize_type=std::ptrdiff_t;

		veque()noexcept(noexcept(Alc())):veque(Alc()){}
		explicit veque(const Alc&a)noexcept:_data{0,a}{}
		explicit veque(size_type n,const Alc&a=Alc()):veque(_aut{},n,a){_vcr(begin(),end());}
		veque(size_type n,const T&value,const Alc&a=Alc()):veque(_aut{},n,a){_vcr(begin(),end(),value);}
		template<typename It,typename ItCat=typename std::iterator_traits<It>::iterator_category>veque(It b,It e,const Alc&a=Alc()):veque(b,e,a,ItCat{}){}
		veque(std::initializer_list<T>lst,const Alc&a=Alc()):veque(_aut{},lst.size(),a){_ccr(lst.begin(),lst.end(),begin());}
		veque(const veque&o):veque(_aut{},o.size(),alloc_traits::select_on_container_copy_construction(o._al())){_ccr(o.begin(),o.end(),begin());}
		template<typename ORT>veque(const veque<T,ORT,Alc>&o):veque(_aut{},o.size(),alloc_traits::select_on_container_copy_construction(o._al())){_ccr(o.begin(),o.end(),begin());}
		template<typename ORT>veque(const veque<T,ORT,Alc>&o,const Alc&a):veque(_aut{},o.size(),a){_ccr(o.begin(),o.end(),begin());}
		
		veque(veque&&o)noexcept{_swa(std::move(o));}
		template<typename ORT>veque(veque<T,ORT,Alc>&&o)noexcept{_swa(std::move(o));}
		
		template<typename ORT>veque(veque<T,ORT,Alc>&&o,const Alc&a)noexcept:veque(a){
			if constexpr(!alloc_traits::is_always_equal::value)if(a!=o._al()){
				auto _=veque(_aut{},o.size(),a);
				_nmcr(o.begin(),o.end(),_.begin());
				_swoa(std::move(_));return;
			}_swoa(std::move(o));
		}
		~veque(){_d(begin(),end());}
		veque&operator=(const veque&o){return _ca(o);}
		template<typename ORT>veque&operator=(const veque<T,ORT,Alc>&o){return _ca(o);}
		veque&operator=(veque&&o)noexcept(noexcept(alloc_traits::propagate_on_container_move_assignment::value||alloc_traits::is_always_equal::value)){return _ma(std::move(o));}
		template<typename ORT>veque&operator=(veque<T,ORT,Alc>&&o)noexcept(noexcept(alloc_traits::propagate_on_container_move_assignment::value||alloc_traits::is_always_equal::value)){return _ma(std::move(o));}
		veque&operator=(std::initializer_list<T>lst){_a(lst.begin(),lst.end());return*this;}
		void assign(size_type cnt,const T&value){if(cnt>capacity_full())_swoa(veque(cnt,value,_al()));else _res(cnt,value);}
		template<typename It,typename ItCat=typename std::iterator_traits<It>::iterator_category>void assign(It b,It e){_a(b,e,ItCat{});}
		
		void assign(std::initializer_list<T>lst){_a(lst.begin(),lst.end());}
		allocator_type get_allocator()const{return _al();}
		
		reference at(size_type idx){if(idx>=size()){throw std::out_of_range("veque<T,ResizeTraits,Alloc>::at("+std::to_string(idx)+") out of range");}return(*this)[idx];}
		const_reference at(size_type idx)const{if(idx>=size()){throw std::out_of_range("veque<T,ResizeTraits,Alloc>::at("+std::to_string(idx)+") out of range");}return(*this)[idx];}
		
		reference operator[](size_type idx){return*(begin()+idx);}
		const_reference operator[](size_type idx)const{return*(begin()+idx);}
		reference front(){return(*this)[0];}
		const_reference front()const{return(*this)[0];}
		
		reference back(){return(*this)[size()-1];}
		const_reference back()const{return(*this)[size()-1];}
		T*data()noexcept{return begin();}
		const T*data()const noexcept{return begin();}
		const_iterator cbegin()const noexcept{return _sb()+_offset;}
		iterator begin()noexcept{return _sb()+_offset;}
		const_iterator begin()const noexcept{return cbegin();}
		const_iterator cend()const noexcept{return _sb()+_offset+size();}
		iterator end()noexcept{return _sb()+_offset+size();}
		const_iterator end()const noexcept{return cend();}
		const_reverse_iterator crbegin()const noexcept{return const_reverse_iterator(cend());}
		reverse_iterator rbegin()noexcept{return reverse_iterator(end());}
		const_reverse_iterator rbegin()const noexcept{return crbegin();}
		const_reverse_iterator crend()const noexcept{return const_reverse_iterator(cbegin());}
		reverse_iterator rend()noexcept{return reverse_iterator(begin());}
		const_reverse_iterator rend()const noexcept{return crend();}
		[[nodiscard]]bool empty()const noexcept{return size()==0;}
		size_type size()const noexcept{return _size;}
		ssize_type ssize()const noexcept{return _size;}
		size_type max_size()const noexcept{
			constexpr auto compile_time_limit=std::min(std::numeric_limits<ssize_type>::max()/sizeof(T),std::numeric_limits<size_type>::max()/_full_realloc::num);
			auto runtime_limit=alloc_traits::max_size(_al());
			return std::min(compile_time_limit,runtime_limit);
		}

		void reserve(size_type front,size_type back){
			if(front>capacity_front() || back>capacity_back()){
				auto allocated_before_begin=std::max(capacity_front(),front)-size();
				auto allocated_after_begin=std::max(capacity_back(),back);
				auto new_full_capacity=allocated_before_begin+allocated_after_begin;
				
				if(new_full_capacity>max_size())
					throw std::length_error("veque<T,ResizeTraits,Alloc>::reserve("+std::to_string(front)+","+std::to_string(back)+") exceeds max_size()");
				_re(new_full_capacity,allocated_before_begin);
			}
		}
		void reserve_front(size_type cnt){reserve(cnt,0);}
		void reserve_back(size_type cnt){reserve(0,cnt);}
		void reserve(size_type cnt){reserve(cnt,cnt);}
		size_type capacity_front()const noexcept{return _offset+size();}
		size_type capacity_back()const noexcept{return capacity_full()-_offset;}
		size_type capacity_full()const noexcept{return _data._allocated;}
		size_type capacity()const noexcept{return capacity_back();}
		void shrink_to_fit(){if(size()<capacity_full())_re(size(),0);}

		void clear() noexcept{
			_d(begin(),end());
			_size=0;
			_offset=0;
			if constexpr(std::ratio_greater_v<_unused_realloc,std::ratio<0>>){
				using unused_front_ratio=std::ratio_divide<_front_realloc,_unused_realloc>;
				_offset=capacity_full()*unused_front_ratio::num/unused_front_ratio::den;
			}
		}

		iterator insert(const_iterator it,const T&value){return emplace(it,value);}
		iterator insert(const_iterator it,T&&value){return emplace(it,std::move(value));}
		iterator insert(const_iterator it,size_type cnt,const T&value){auto res=_is(it,cnt);_vcr(res,res+cnt,value);return res;}
		template<typename It,typename ItCat=typename std::iterator_traits<It>::iterator_category>iterator insert(const_iterator it,It b,It e){return _i(it,b,e,ItCat{});}
		iterator insert(const_iterator it,std::initializer_list<T>lst){return insert(it,lst.begin(),lst.end());}
		
		template<typename...Args>
		iterator emplace(const_iterator it,Args&&...args){
			auto res=_is(it,1);
			alloc_traits::construct(_al(),res,std::forward<Args>(args)...);
			return res;
		}
		
		iterator erase(const_iterator it){return erase(it,std::next(it));}
		iterator erase(const_iterator b,const_iterator e){
			auto cnt=std::distance(b,e);
			if constexpr(_rfcs){
				auto elements_before=std::distance(cbegin(),b);
				auto elements_after=std::distance(e,cend());
				if( elements_before<elements_after){
					_shb(begin(),b,cnt);
					_mb(cnt);
					return _mi(e);
				}
			}
			_shf(e,end(),cnt);
			_me(-cnt);
			return _mi(b);
		}
		
		void push_back(const T&value){emplace_back(value);}
		void push_back(T&&value){emplace_back(std::move(value));}
		
		template<typename...Args>reference emplace_back(Args&&...args){
			if(size()==capacity_back())_resab(size()+1);
			alloc_traits::construct(_al(),end(),std::forward<Args>(args)...);
			_me(1);
			return back();
		}
		
		void push_front(const T&value){emplace_front(value);}
		void push_front(T&&value){emplace_front(std::move(value));}
		
		template<typename...Args>reference emplace_front(Args&&...args){
			if(size()==capacity_front())_resaf(size()+1);
			alloc_traits::construct(_al(),begin()-1,std::forward<Args>(args)...);
			_mb(-1);
			return front();
		}
		
		void pop_back(){alloc_traits::destroy(_al(),&back());_me(-1);}
		T pop_back_element(){auto res(_ncm(back()));pop_back();return res;}
		void pop_front(){alloc_traits::destroy(_al(),&front());_mb(1);}
		T pop_front_element(){auto res(_ncm(front()));pop_front();return res;}
		void resize_front(size_type cnt){_rf(cnt);}
		void resize_front(size_type cnt,const T&value){_rf(cnt,value);}
		void resize_back(size_type cnt){_rb(cnt);}
		void resize_back(size_type cnt,const T&value){_rb(cnt,value);}
		void resize(size_type cnt){_rb(cnt);}
		void resize(size_type cnt,const T&value){_rb(cnt,value);}
		
		template<typename ORT>void swap(veque<T,ORT,Alc>&o)noexcept(noexcept(alloc_traits::propagate_on_container_swap::value||alloc_traits::is_always_equal::value)){
			if constexpr(alloc_traits::propagate_on_container_swap::value)_swa(std::move(o));
			else{
				if(_al()==o._al())_swoa(std::move(o));
				else{
					auto new_this=veque(_aut{},o.size(),_al());_nmcr(o.begin(),o.end(),new_this.begin());
					auto new_o=veque(_aut{},size(),o._al());_nmcr(begin(),end(),new_o.begin());
					_swoa(std::move(new_this));o._swoa(std::move(new_o));
				}
			}
		}
		
	private:
		
		using _front_realloc=typename RT::allocation_before_front::type;
		using _back_realloc=typename RT::allocation_after_back::type;
		using _unused_realloc=std::ratio_add<_front_realloc,_back_realloc>;
		using _full_realloc=std::ratio_add<std::ratio<1>,_unused_realloc>;
		
		static constexpr auto _rfcs=RT::resize_from_closest_side;
		
		static_assert(_front_realloc::den>0 );
		static_assert(_back_realloc::den>0 );
		static_assert(std::ratio_greater_equal_v<_front_realloc,std::ratio<0>>,"Reserving negative space is not well-defined");
		static_assert(std::ratio_greater_equal_v<_back_realloc,std::ratio<0>>,"Reserving negative space is not well-defined");
		static_assert(std::ratio_greater_equal_v<_unused_realloc,std::ratio<0>>,"Reserving negative space is not well-defined");
		
		static constexpr auto _cdcd=std::is_same_v<allocator_type,std::allocator<T>>;
		static constexpr auto _cccd=std::is_same_v<allocator_type,std::allocator<T>>;
		static constexpr auto _cdd=std::is_same_v<allocator_type,std::allocator<T>>;
		size_type _size=0;
		size_type _offset=0;
		struct Data:Alc{
			T*_storage=nullptr;
			size_type _allocated=0;
			Data()=default;
			Data(size_type size,const Alc&a):Alc{a},_storage{size?std::allocator_traits<Alc>::allocate(allocator(),size):nullptr},_allocated{size}{}
			Data(const Data&)=delete;
			Data(Data&&o){*this=std::move(o);}
			~Data(){if(_storage)std::allocator_traits<Alc>::deallocate(allocator(),_storage,_allocated);}
			Data&operator=(const Data&)=delete;
			Data&operator=(Data&&o){
				using std::swap;
				if constexpr(!std::is_empty_v<Alc>)swap(allocator(),o.allocator());
				swap(_allocated,o._allocated);
				swap(_storage,o._storage);
				return*this;
			}
			Alc&allocator(){return*this;}
			const Alc&allocator()const{return*this;}
		} _data;
		
		template<typename It>veque(It b,It e,const Alc&a,std::input_iterator_tag):veque{a}{for(;b!=e;++b){push_back(*b);}}
		template<typename It>veque(It b,It e,const Alc&a,std::forward_iterator_tag):veque(_aut{},std::distance(b,e),a){_ccr(b,e,begin());}
		struct _aut{};
		struct _rut{};
		veque(_aut,size_type size,size_type allocated,size_type offset,const Alc&a):_size{size},_offset{offset},_data{allocated,a}{}
		veque(_aut,size_type size,const Alc&a):veque(_aut{},size,size,0,a){}
		veque(_rut,size_type size,const Alc&a):veque(_aut{},size,_cr(size),_co(size),a){}
		static constexpr size_type _cr(size_type size){return size*_full_realloc::num/_full_realloc::den;}
		static constexpr size_type _co(size_type size){return size*_front_realloc::num/_front_realloc::den;}
		Alc&_al()noexcept{return _data.allocator();}
		const Alc&_al()const noexcept{return _data.allocator();}
		
		void _d(const_iterator b,const_iterator e){
			if constexpr(std::is_trivially_destructible_v<T>&&_cdd){(void)b;(void)e;}
			else{
				auto start=_mi(b);
				for(auto i=start;i!=e;++i)alloc_traits::destroy(_al(),i);
			}
		}
		
		template<typename ORT>veque&_ca(const veque<T,ORT,Alc>&o){
			if constexpr(alloc_traits::propagate_on_container_copy_assignment::value)
				if constexpr(!alloc_traits::is_always_equal::value)
					if(o._al()!=_al() || o.size()>capacity_full()){_swa(veque(o,o._al()));return *this;}
			if(o.size()>capacity_full())_swoa(veque(o,_al()));
			else _res(o.begin(),o.end());
			return *this;
		}
		template<typename ORT>veque&_ma(veque<T,ORT,Alc>&&o)noexcept(noexcept(alloc_traits::propagate_on_container_move_assignment::value||alloc_traits::is_always_equal::value)){
			if constexpr(!alloc_traits::is_always_equal::value){
				if(_al()!=o._al()){
					if constexpr(alloc_traits::propagate_on_container_move_assignment::value)_swa(std::move(o));
					else{
						if(o.size()>capacity_full())_swoa(veque(std::move(o),_al()));
						else _res(std::move_iterator(o.begin()),std::move_iterator(o.end()));
					}
					return *this;
				}
			}
			_swoa(std::move(o));
			return *this;
		}
		
		template<typename...Args>void _vcr(const_iterator b,const_iterator e,const Args&...args){
			static_assert(sizeof...(args)<=1,"This is for default-or copy-constructing");
			if constexpr(std::is_trivially_copy_constructible_v<T>&&_cdcd){
				if constexpr(sizeof...(args)==0)std::memset(_mi(b),0,std::distance(b,e)*sizeof(T));
				else std::fill(_mi(b),_mi(e),args...);
			}
			else for(auto dest=_mi(b);dest!=e;++dest) alloc_traits::construct(_al(),dest,args...);
		}
		
		template<typename It>void _ccr(It b,It e,const_iterator dest){
			static_assert(std::is_convertible_v<typename std::iterator_traits<It>::iterator_category,std::forward_iterator_tag>);
			if constexpr(std::is_trivially_copy_constructible_v<T>&&_cccd)std::memcpy(_mi(dest),b,std::distance(b,e)*sizeof(T));
			else for(;b!=e;++dest,++b)alloc_traits::construct(_al(),dest,*b);
		}
		
		template<typename It>void _a(It b,It e){
			static_assert(std::is_convertible_v<typename std::iterator_traits<It>::iterator_category,std::forward_iterator_tag>);
			if(std::distance(b,e)>static_cast<difference_type>(capacity_full()))_swoa(veque(b,e,_al()));
			else _res(b,e);
		}
		
		template<typename It>void _a(It b,It e,std::forward_iterator_tag){_a(b,e);}
		template<typename It>void _a(It b,It e,std::input_iterator_tag){clear();for(;b!=e;++b)push_back(*b);}
		
		template<typename It>iterator _i(const_iterator it,It b,It e){
			static_assert(std::is_convertible_v<typename std::iterator_traits<It>::iterator_category,std::forward_iterator_tag>);
			auto res=_is(it,std::distance(b,e));
			_ccr(b,e,res);
			return res;
		}
		template<typename It>iterator _i(const_iterator it,It b,It e,std::forward_iterator_tag){return _i(it,b,e);}
		template<typename It>iterator _i(const_iterator it,It b,It e,std::input_iterator_tag){auto allocated=veque(b,e);_i(it,allocated.begin(),allocated.end());}
		template<typename ORT>void _swa(veque<T,ORT,Alc>&&o)noexcept{
			std::swap(_size,o._size);
			std::swap(_offset,o._offset);
			std::swap(_data,o._data);
		}
		template<typename ORT>void _swoa(veque<T,ORT,Alc>&&o)noexcept{
			std::swap(_size,o._size);
			std::swap(_offset,o._offset);
			std::swap(_data._allocated,o._data._allocated);
			std::swap(_data._storage,o._data._storage);
		}
		
		template<typename...Args>void _rf(size_type cnt,const Args&...args){
			difference_type delta=cnt-size();
			if(delta>0){
				if(cnt>capacity_front())_resaf(cnt);
				_vcr(begin()-delta,begin(),args...);
			}
			else _d(begin(),begin()-delta);
			_mb(-delta);
		}
		template<typename...Args>void _rb(size_type cnt,const Args&...args){
			difference_type delta=cnt-size();
			if(delta>0){
				if(cnt>capacity_back())_resab(cnt);
				_vcr(end(),end()+delta,args...);
			}
			else _d(end()+delta,end());
			_me(delta);
		}
		void _resab(size_type cnt){
			auto storage_needed=_cr(cnt);
			auto current_capacity=capacity_full();
			auto new_offset=_co(cnt);
			if(storage_needed<=current_capacity){
				auto distance=_offset-new_offset;
				_shf(begin(),end(),distance );
				_mb(-distance);
				_me(-distance);
			}
			else _re(storage_needed,new_offset);
		}
		void _resaf(size_type cnt){
			auto storage_needed=_cr(cnt);
			auto current_capacity=capacity_full();
			auto new_offset=cnt-size()+_co(cnt);
			if(storage_needed<=current_capacity){
				auto distance=new_offset-_offset;
				_shb(begin(),end(),distance);
				_mb(distance);
				_me(distance);
			}
			else _re(storage_needed,new_offset);
		}
		void _re(size_type allocated,size_type offset){
			auto tmp=veque(_aut{},size(),allocated,offset,_al());
			_nmcr(begin(),end(),tmp.begin());
			_swoa(std::move(tmp));
		}
		iterator _is(const_iterator it,size_type cnt){
			auto required_size=size()+cnt;
			auto can_shift_back=capacity_back()>=required_size;
			if constexpr(std::ratio_greater_v<_front_realloc,std::ratio<0>>)
				if(can_shift_back&&it==begin())can_shift_back=false;
			
			if constexpr(_rfcs){
				auto can_shift_front=capacity_front()>=required_size;
				if constexpr(std::ratio_greater_v<_back_realloc,std::ratio<0>>)
					if(can_shift_front&&it==end())can_shift_front=false;
				
				if(can_shift_back&&can_shift_front){
					auto index=std::distance(cbegin(),it);
					if(index<=ssize()/2)can_shift_back=false;
					else can_shift_front=false;
				}
				if(can_shift_front){_shf(begin(),it,cnt);_mb(-cnt);return _mi(it)-cnt;}
			}
			if(can_shift_back){_shb(it,end(),cnt);_me(cnt);return _mi(it);}
			auto tmp=veque(_rut{},required_size,_al());
			auto index=std::distance(cbegin(),it);
			auto insertion_point=begin()+index;
			_nmcr(begin(),insertion_point,tmp.begin());
			_nmcr(insertion_point,end(),tmp.begin()+index+cnt);
			_swa(std::move(tmp));
			return begin()+index;
		}
		void _shf(const_iterator b,const_iterator e,size_type cnt){
			if(e==begin())return;
			auto element_cnt=std::distance(b,e);
			auto start=_mi(b);
			if(element_cnt>0){
				auto dest=start-cnt;
				if constexpr(std::is_trivially_copyable_v<T>&&std::is_trivially_copy_constructible_v<T>&&_cccd)std::memmove(dest,start,element_cnt*sizeof(T));
				else{
					auto src=start;
					auto dest_construct_end=std::min(begin(),_mi(e)-cnt);
					for(;dest<dest_construct_end;++src,++dest)_nmc(dest,src);
					for(;src!=e;++src,++dest)_nma(dest,src);
				}
			}
			_d(std::max(cbegin(),e-cnt),e);
		}
		void _shb(const_iterator b,const_iterator e,size_type cnt){
			auto start=_mi(b); 
			if(b==end())return;
			auto element_cnt=std::distance(b,e);
			if(element_cnt>0){
				if constexpr(std::is_trivially_copyable_v<T>&&std::is_trivially_copy_constructible_v<T>&&_cccd)std::memmove(start+cnt,start,element_cnt*sizeof(T));
				else{
					auto src=_mi(e-1);
					auto dest=src+cnt;
					auto dest_construct_end=std::max(end()-1,dest-element_cnt);
					for(;dest>dest_construct_end;--src,--dest)_nmc(dest,src);
					for(;src!=b-1;--src,--dest)_nma(dest,src);
				}
			}
			_d(b,std::min(cend(),b+cnt));
		}
		template<typename It>void _res(It b,It e){
			static_assert(std::is_convertible_v<typename std::iterator_traits<It>::iterator_category,std::forward_iterator_tag>);
			auto cnt=std::distance(b,e);
			auto size_delta=static_cast<difference_type>(cnt-size());
			auto ib=_sb()+(capacity_full()-cnt)/2;
			if(size()==0)_ccr(b,e,ib);
			else if(size_delta==0){std::copy(b,e,begin());return;}
			else if(size_delta<0){
				ib=std::clamp(ib,begin(),end()-cnt);_d(begin(),ib);
				auto ideal_end=std::copy(b,e,ib);_d(ideal_end,end());
			}
			else{
				ib=std::clamp(ib,end()-cnt,begin());
				auto src=b;
				auto copy_src=src+std::distance(ib,begin());_ccr(src,copy_src,ib);
				std::copy(copy_src,copy_src+ssize(),begin());_ccr(copy_src+ssize(),e,end());
			}
			_mb(std::distance(begin(),ib));
			_me(std::distance(end(),ib+cnt));
		}
		
		void _res(size_type cnt,const T&value){
			auto size_delta=static_cast<difference_type>(cnt-size());
			auto ib=_sb();
			if constexpr(std::ratio_greater_v<_unused_realloc,std::ratio<0>>){
				using ideal_begin_ratio=std::ratio_divide<_front_realloc,_unused_realloc>;
				ib+=(capacity_full()-cnt)*ideal_begin_ratio::num/ideal_begin_ratio::den;
			}
			if(size()==0)_vcr(ib,ib+cnt,value);
			else if(size_delta==0){std::fill(begin(),end(),value);return;}
			else if(size_delta<0){
				ib=std::clamp(ib,begin(),end()-cnt);_d(begin(),ib);
				std::fill(ib,ib+cnt,value);_d(ib+cnt,end());
			}else{
				ib+=_co(capacity_full()-cnt)/2;_vcr(ib,begin(),value);
				std::fill(begin(),end(),value);_vcr(end(),ib+cnt,value);
			}
			_mb(std::distance(begin(),ib));
			_me(std::distance(end(),ib+cnt));
		}
		static decltype(auto)_ncm(T&t){
			if constexpr(std::is_nothrow_move_constructible_v<T>)return std::move(t);
			else return t;
		}
		void _nmc(iterator dest,iterator src){
			if constexpr(std::is_trivially_copy_constructible_v<T>&&_cccd)*dest=*src;
			else alloc_traits::construct(_al(),dest,_ncm(*src));
		}
		void _nmcr(iterator b,iterator e,iterator dest){
			auto size=std::distance(b,e);
			if(size){
				if constexpr(std::is_trivially_copy_constructible_v<T>&&_cccd)std::memcpy(dest,b,size*sizeof(T));
				else for(;b!=e;++dest,++b)_nmc(dest,b);
			}
		}
		
		static void _nma(iterator dest,iterator src){if constexpr(std::is_nothrow_move_assignable_v<T>)*dest=std::move(*src);else*dest=*src;}
		static void _nmar(iterator b,iterator e,iterator src){for(auto dest=b;dest!=e;++dest,++src)_nma(dest,src);}
		void _mb(difference_type cnt)noexcept{_size-=cnt;_offset+=cnt;}
		void _me(difference_type cnt)noexcept{_size+=cnt;}
		iterator _mi(const_iterator i){return begin()+std::distance(cbegin(),i);}
		const_iterator _sb()const noexcept{return _data._storage;}
		iterator _sb()noexcept{return _data._storage;}
	};
#define tp template<typename T,typename LRT,typename LA,typename RRT,typename RA>
#define arg const veque<T,LRT,LA>&lhs,const veque<T,RRT,RA>&rhs
	tp inline bool operator==(arg){return std::equal(lhs.begin(),lhs.end(),rhs.begin(),rhs.end());}
	tp inline bool operator!=(arg){return!(lhs==rhs);}
	tp inline bool operator<(arg){return std::lexicographical_compare(lhs.begin(),lhs.end(),rhs.begin(),rhs.end());}
	tp inline bool operator<=(arg){return!(rhs<lhs);}
	tp inline bool operator>(arg){return(rhs<lhs);}
	tp inline bool operator>=(arg){return!(lhs<rhs);}
#undef tp
#undef arg
	template<typename T,typename RT,typename A>inline void swap(veque<T,RT,A>&lhs,veque<T,RT,A>&rhs)noexcept(noexcept(lhs.swap(rhs))){lhs.swap(rhs);}
	template<typename It,typename A=std::allocator<typename std::iterator_traits<It>::value_type>>veque(It,It,A=A())->veque<typename std::iterator_traits<It>::value_type,fast_resize_traits,A>;
}

namespace std{
	template<typename T,typename RT,typename A>struct hash<veque::veque<T,RT,A>>{
		size_t operator()(const veque::veque<T,RT,A>&v)const{
			size_t hash=0; auto hasher=std::hash<T>();
			for(auto&&val:v) hash^=hasher(val)+0x9e3779b9+(hash<<6)+(hash>>2);
			return hash;
		}
	};
}

#endif
int main(){
	
}

/*
被更改的变量名
InputIt->It
(L/R)Alloc->A
Allocator->Alc
alloc->a
(L/R/Other)ResizeTraits->RT
ideal_begin->ib
count->cnt
_allocate_uninitialized_tag->_aut
_reallocate_uninitialized_tag->_rut
replacement->tmp
Other->O
other->o
_storage_begin->_sb
_mutable_iterator->_mi
_move_end->_me
_move_begin->_mb
_nothrow_move_assign_range->_nmar
_nothrow_move_assign->_nma
_nothrow_move_construct_range->_nmcr
_nothrow_move_construct->_nmc
_nothrow_construct_move->_ncm
_reassign_existing_storage->_res
_shift_back->_shb
_shift_front->_shf
_insert_storage->_is
_reallocate->_re
_reallocate_space_at_front->_resaf
_reallocate_space_at_back->_resab
_resize_back->_rb
_resize_front->_rf
_swap_without_allocator->_swoa
_swap_with_allocator->_swa
_insert->_i
_assign->_a
_copy_construct_range->_ccr
_value_construct_range->_vcr
_move_assignment->_ma
_copy_assignment->_ca
_destroy->_d
_allocator->_al
_calc_offset->_co
_calc_reallocation->_cr
_calls_destructor_directly->_cdd
_calls_copy_constructor_directly->_cccd
_calls_default_constructor_directly->_cdcd
_resize_from_closest_side->_rfcs
*/

评论

14 条评论,欢迎与作者交流。

正在加载评论...