#pragma once
#include<functional>
#include<optional>
#include<cassert>#include"internal/dev_env.hpp"namespaceuni{template<classContainer>structrange_extractor:Container{usingsize_type=typenameContainer::size_type;usingvalue_type=typenameContainer::value_type;protected:usingdefault_func_noarg_type=std::function<value_type(void)>;usingdefault_func_type=std::function<value_type(size_type)>;size_type_begin=0;size_type_end;int_default_type=0;value_type_default_val=value_type();default_func_noarg_type_default_func_noarg;default_func_type_default_func;inlinestaticvalue_type_tmp;inlinevalue_type_get_default(constsize_typekey)constnoexcept(NO_EXCEPT){if(this->_default_type==0)returnthis->_default_val;if(this->_default_type==1)returnthis->_default_func_noarg();if(this->_default_type==2)returnthis->_default_func(key);elseassert(false);}public:template<class...Args>explicitrange_extractor(Args&&...args)noexcept(NO_EXCEPT):Container(std::forward<Args>(args)...){this->_begin=0;this->_end=this->size();}inlineauto&extract(constsize_typebegin,constsize_typeend)noexcept(NO_EXCEPT){assert(begin<=end);this->_begin=begin,this->_end=end;return*this;}inlineauto&set_default(constvalue_type&val)noexcept(NO_EXCEPT){this->_default_val=val;this->_default_type=0;return*this;}inlineauto&set_default(constdefault_func_noarg_typefunc)noexcept(NO_EXCEPT){this->_default_func_noarg=func;this->_default_type=1;return*this;}inlineauto&set_default(constdefault_func_typefunc)noexcept(NO_EXCEPT){this->_default_func=func;this->_default_type=2;return*this;}inlineauto&operator[](constsize_typepos)noexcept(NO_EXCEPT){if(pos<this->_beginorthis->_end<=pos)returnrange_extractor::_tmp=this->_get_default(pos);returnthis->Container::operator[](pos);}inlineconstauto&operator[](constsize_typepos)constnoexcept(NO_EXCEPT){if(pos<this->_beginorthis->_end<=pos)returnrange_extractor::_tmp=this->_get_default(pos);returnthis->Container::operator[](pos);}inlineauto&operator()(constsize_typepos)noexcept(NO_EXCEPT){returnthis->Container::operator[](pos);}inlineconstauto&operator()(constsize_typepos)constnoexcept(NO_EXCEPT){returnthis->Container::operator[](pos);}inlinestd::optional<value_type>get(constsize_typepos)constnoexcept(NO_EXCEPT){if(pos<this->_beginorthis->_end<=pos)return{};returnthis->Container::operator[](pos);}};}