static_string.hpp 179 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897189818991900190119021903190419051906190719081909191019111912191319141915191619171918191919201921192219231924192519261927192819291930193119321933193419351936193719381939194019411942194319441945194619471948194919501951195219531954195519561957195819591960196119621963196419651966196719681969197019711972197319741975197619771978197919801981198219831984198519861987198819891990199119921993199419951996199719981999200020012002200320042005200620072008200920102011201220132014201520162017201820192020202120222023202420252026202720282029203020312032203320342035203620372038203920402041204220432044204520462047204820492050205120522053205420552056205720582059206020612062206320642065206620672068206920702071207220732074207520762077207820792080208120822083208420852086208720882089209020912092209320942095209620972098209921002101210221032104210521062107210821092110211121122113211421152116211721182119212021212122212321242125212621272128212921302131213221332134213521362137213821392140214121422143214421452146214721482149215021512152215321542155215621572158215921602161216221632164216521662167216821692170217121722173217421752176217721782179218021812182218321842185218621872188218921902191219221932194219521962197219821992200220122022203220422052206220722082209221022112212221322142215221622172218221922202221222222232224222522262227222822292230223122322233223422352236223722382239224022412242224322442245224622472248224922502251225222532254225522562257225822592260226122622263226422652266226722682269227022712272227322742275227622772278227922802281228222832284228522862287228822892290229122922293229422952296229722982299230023012302230323042305230623072308230923102311231223132314231523162317231823192320232123222323232423252326232723282329233023312332233323342335233623372338233923402341234223432344234523462347234823492350235123522353235423552356235723582359236023612362236323642365236623672368236923702371237223732374237523762377237823792380238123822383238423852386238723882389239023912392239323942395239623972398239924002401240224032404240524062407240824092410241124122413241424152416241724182419242024212422242324242425242624272428242924302431243224332434243524362437243824392440244124422443244424452446244724482449245024512452245324542455245624572458245924602461246224632464246524662467246824692470247124722473247424752476247724782479248024812482248324842485248624872488248924902491249224932494249524962497249824992500250125022503250425052506250725082509251025112512251325142515251625172518251925202521252225232524252525262527252825292530253125322533253425352536253725382539254025412542254325442545254625472548254925502551255225532554255525562557255825592560256125622563256425652566256725682569257025712572257325742575257625772578257925802581258225832584258525862587258825892590259125922593259425952596259725982599260026012602260326042605260626072608260926102611261226132614261526162617261826192620262126222623262426252626262726282629263026312632263326342635263626372638263926402641264226432644264526462647264826492650265126522653265426552656265726582659266026612662266326642665266626672668266926702671267226732674267526762677267826792680268126822683268426852686268726882689269026912692269326942695269626972698269927002701270227032704270527062707270827092710271127122713271427152716271727182719272027212722272327242725272627272728272927302731273227332734273527362737273827392740274127422743274427452746274727482749275027512752275327542755275627572758275927602761276227632764276527662767276827692770277127722773277427752776277727782779278027812782278327842785278627872788278927902791279227932794279527962797279827992800280128022803280428052806280728082809281028112812281328142815281628172818281928202821282228232824282528262827282828292830283128322833283428352836283728382839284028412842284328442845284628472848284928502851285228532854285528562857285828592860286128622863286428652866286728682869287028712872287328742875287628772878287928802881288228832884288528862887288828892890289128922893289428952896289728982899290029012902290329042905290629072908290929102911291229132914291529162917291829192920292129222923292429252926292729282929293029312932293329342935293629372938293929402941294229432944294529462947294829492950295129522953295429552956295729582959296029612962296329642965296629672968296929702971297229732974297529762977297829792980298129822983298429852986298729882989299029912992299329942995299629972998299930003001300230033004300530063007300830093010301130123013301430153016301730183019302030213022302330243025302630273028302930303031303230333034303530363037303830393040304130423043304430453046304730483049305030513052305330543055305630573058305930603061306230633064306530663067306830693070307130723073307430753076307730783079308030813082308330843085308630873088308930903091309230933094309530963097309830993100310131023103310431053106310731083109311031113112311331143115311631173118311931203121312231233124312531263127312831293130313131323133313431353136313731383139314031413142314331443145314631473148314931503151315231533154315531563157315831593160316131623163316431653166316731683169317031713172317331743175317631773178317931803181318231833184318531863187318831893190319131923193319431953196319731983199320032013202320332043205320632073208320932103211321232133214321532163217321832193220322132223223322432253226322732283229323032313232323332343235323632373238323932403241324232433244324532463247324832493250325132523253325432553256325732583259326032613262326332643265326632673268326932703271327232733274327532763277327832793280328132823283328432853286328732883289329032913292329332943295329632973298329933003301330233033304330533063307330833093310331133123313331433153316331733183319332033213322332333243325332633273328332933303331333233333334333533363337333833393340334133423343334433453346334733483349335033513352335333543355335633573358335933603361336233633364336533663367336833693370337133723373337433753376337733783379338033813382338333843385338633873388338933903391339233933394339533963397339833993400340134023403340434053406340734083409341034113412341334143415341634173418341934203421342234233424342534263427342834293430343134323433343434353436343734383439344034413442344334443445344634473448344934503451345234533454345534563457345834593460346134623463346434653466346734683469347034713472347334743475347634773478347934803481348234833484348534863487348834893490349134923493349434953496349734983499350035013502350335043505350635073508350935103511351235133514351535163517351835193520352135223523352435253526352735283529353035313532353335343535353635373538353935403541354235433544354535463547354835493550355135523553355435553556355735583559356035613562356335643565356635673568356935703571357235733574357535763577357835793580358135823583358435853586358735883589359035913592359335943595359635973598359936003601360236033604360536063607360836093610361136123613361436153616361736183619362036213622362336243625362636273628362936303631363236333634363536363637363836393640364136423643364436453646364736483649365036513652365336543655365636573658365936603661366236633664366536663667366836693670367136723673367436753676367736783679368036813682368336843685368636873688368936903691369236933694369536963697369836993700370137023703370437053706370737083709371037113712371337143715371637173718371937203721372237233724372537263727372837293730373137323733373437353736373737383739374037413742374337443745374637473748374937503751375237533754375537563757375837593760376137623763376437653766376737683769377037713772377337743775377637773778377937803781378237833784378537863787378837893790379137923793379437953796379737983799380038013802380338043805380638073808380938103811381238133814381538163817381838193820382138223823382438253826382738283829383038313832383338343835383638373838383938403841384238433844384538463847384838493850385138523853385438553856385738583859386038613862386338643865386638673868386938703871387238733874387538763877387838793880388138823883388438853886388738883889389038913892389338943895389638973898389939003901390239033904390539063907390839093910391139123913391439153916391739183919392039213922392339243925392639273928392939303931393239333934393539363937393839393940394139423943394439453946394739483949395039513952395339543955395639573958395939603961396239633964396539663967396839693970397139723973397439753976397739783979398039813982398339843985398639873988398939903991399239933994399539963997399839994000400140024003400440054006400740084009401040114012401340144015401640174018401940204021402240234024402540264027402840294030403140324033403440354036403740384039404040414042404340444045404640474048404940504051405240534054405540564057405840594060406140624063406440654066406740684069407040714072407340744075407640774078407940804081408240834084408540864087408840894090409140924093409440954096409740984099410041014102410341044105410641074108410941104111411241134114411541164117411841194120412141224123412441254126412741284129413041314132413341344135413641374138413941404141414241434144414541464147414841494150415141524153415441554156415741584159416041614162416341644165416641674168416941704171417241734174417541764177417841794180418141824183418441854186418741884189419041914192419341944195419641974198419942004201420242034204420542064207420842094210421142124213421442154216421742184219422042214222422342244225422642274228422942304231423242334234423542364237423842394240424142424243424442454246424742484249425042514252425342544255425642574258425942604261426242634264426542664267426842694270427142724273427442754276427742784279428042814282428342844285428642874288428942904291429242934294429542964297429842994300430143024303430443054306430743084309431043114312431343144315431643174318431943204321432243234324432543264327432843294330433143324333433443354336433743384339434043414342434343444345434643474348434943504351435243534354435543564357435843594360436143624363436443654366436743684369437043714372437343744375437643774378437943804381438243834384438543864387438843894390439143924393439443954396439743984399440044014402440344044405440644074408440944104411441244134414441544164417441844194420442144224423442444254426442744284429443044314432443344344435443644374438443944404441444244434444444544464447444844494450445144524453445444554456445744584459446044614462446344644465446644674468446944704471447244734474447544764477447844794480448144824483448444854486448744884489449044914492449344944495449644974498449945004501450245034504450545064507450845094510451145124513451445154516451745184519452045214522452345244525452645274528452945304531453245334534453545364537453845394540454145424543454445454546454745484549455045514552455345544555455645574558455945604561456245634564456545664567456845694570457145724573457445754576457745784579458045814582458345844585458645874588458945904591459245934594459545964597459845994600460146024603460446054606460746084609461046114612461346144615461646174618461946204621462246234624462546264627462846294630463146324633463446354636463746384639464046414642464346444645464646474648464946504651465246534654465546564657465846594660466146624663466446654666466746684669467046714672467346744675467646774678467946804681468246834684468546864687468846894690469146924693469446954696469746984699470047014702470347044705470647074708470947104711471247134714471547164717471847194720472147224723472447254726472747284729473047314732473347344735473647374738473947404741474247434744474547464747474847494750475147524753475447554756475747584759476047614762476347644765476647674768476947704771477247734774477547764777477847794780478147824783478447854786478747884789479047914792479347944795479647974798479948004801480248034804480548064807480848094810481148124813481448154816481748184819482048214822482348244825482648274828482948304831483248334834483548364837483848394840484148424843484448454846484748484849485048514852485348544855485648574858485948604861486248634864486548664867486848694870487148724873487448754876487748784879488048814882488348844885488648874888488948904891489248934894489548964897489848994900490149024903490449054906490749084909491049114912491349144915491649174918491949204921492249234924492549264927492849294930493149324933493449354936493749384939494049414942494349444945494649474948494949504951495249534954495549564957495849594960496149624963496449654966496749684969497049714972497349744975497649774978497949804981498249834984498549864987498849894990499149924993499449954996499749984999500050015002500350045005500650075008500950105011501250135014501550165017501850195020502150225023502450255026502750285029503050315032503350345035503650375038503950405041504250435044504550465047504850495050505150525053505450555056505750585059506050615062506350645065506650675068506950705071507250735074507550765077507850795080508150825083508450855086508750885089509050915092509350945095509650975098509951005101510251035104510551065107510851095110511151125113511451155116511751185119512051215122512351245125512651275128512951305131513251335134513551365137513851395140514151425143514451455146514751485149515051515152515351545155515651575158515951605161516251635164516551665167516851695170517151725173517451755176517751785179518051815182518351845185518651875188518951905191519251935194519551965197519851995200520152025203520452055206520752085209521052115212521352145215521652175218521952205221522252235224522552265227522852295230523152325233523452355236523752385239524052415242524352445245524652475248524952505251525252535254525552565257525852595260526152625263526452655266526752685269527052715272527352745275527652775278527952805281528252835284528552865287528852895290529152925293529452955296529752985299530053015302530353045305530653075308530953105311531253135314531553165317531853195320532153225323532453255326532753285329533053315332533353345335533653375338533953405341534253435344534553465347534853495350535153525353535453555356535753585359536053615362536353645365536653675368536953705371537253735374537553765377537853795380538153825383538453855386538753885389539053915392539353945395539653975398539954005401540254035404540554065407540854095410541154125413541454155416541754185419542054215422542354245425542654275428542954305431543254335434543554365437543854395440544154425443544454455446544754485449545054515452545354545455545654575458545954605461546254635464546554665467546854695470547154725473547454755476547754785479548054815482548354845485548654875488548954905491549254935494549554965497549854995500550155025503550455055506550755085509551055115512551355145515551655175518551955205521552255235524552555265527552855295530553155325533553455355536553755385539554055415542554355445545554655475548554955505551555255535554555555565557555855595560556155625563556455655566556755685569557055715572557355745575557655775578557955805581558255835584558555865587558855895590559155925593559455955596559755985599560056015602560356045605560656075608560956105611561256135614561556165617561856195620562156225623562456255626562756285629563056315632563356345635563656375638563956405641564256435644564556465647564856495650565156525653565456555656565756585659566056615662566356645665566656675668566956705671567256735674567556765677567856795680568156825683568456855686568756885689569056915692569356945695569656975698569957005701570257035704570557065707570857095710571157125713571457155716571757185719572057215722572357245725572657275728572957305731573257335734573557365737573857395740574157425743574457455746574757485749575057515752575357545755575657575758575957605761576257635764576557665767576857695770577157725773577457755776577757785779578057815782578357845785578657875788578957905791579257935794579557965797579857995800580158025803580458055806580758085809581058115812581358145815581658175818581958205821582258235824582558265827582858295830583158325833583458355836583758385839584058415842584358445845584658475848584958505851585258535854585558565857585858595860586158625863586458655866586758685869587058715872587358745875587658775878587958805881588258835884588558865887588858895890589158925893589458955896589758985899590059015902590359045905590659075908590959105911591259135914591559165917591859195920592159225923592459255926592759285929593059315932593359345935593659375938593959405941594259435944594559465947594859495950595159525953595459555956595759585959596059615962596359645965596659675968596959705971597259735974597559765977597859795980598159825983598459855986598759885989599059915992599359945995599659975998599960006001600260036004600560066007600860096010601160126013601460156016601760186019602060216022602360246025602660276028602960306031603260336034603560366037603860396040604160426043604460456046604760486049605060516052605360546055605660576058605960606061606260636064606560666067606860696070607160726073607460756076607760786079608060816082608360846085608660876088608960906091609260936094609560966097609860996100610161026103610461056106610761086109611061116112611361146115611661176118611961206121612261236124612561266127612861296130613161326133613461356136613761386139614061416142614361446145614661476148614961506151615261536154615561566157615861596160616161626163616461656166616761686169617061716172617361746175617661776178617961806181618261836184618561866187618861896190619161926193619461956196619761986199620062016202620362046205620662076208620962106211621262136214621562166217621862196220622162226223622462256226622762286229623062316232623362346235623662376238623962406241624262436244624562466247624862496250625162526253625462556256625762586259626062616262626362646265626662676268626962706271627262736274627562766277627862796280628162826283628462856286628762886289629062916292629362946295629662976298629963006301630263036304630563066307630863096310631163126313631463156316631763186319632063216322632363246325632663276328632963306331633263336334633563366337633863396340634163426343634463456346634763486349635063516352635363546355635663576358635963606361636263636364636563666367636863696370637163726373637463756376637763786379638063816382638363846385638663876388638963906391639263936394639563966397639863996400640164026403640464056406640764086409641064116412641364146415641664176418641964206421642264236424642564266427642864296430643164326433643464356436643764386439644064416442644364446445644664476448644964506451645264536454645564566457645864596460646164626463646464656466646764686469647064716472647364746475647664776478647964806481648264836484648564866487648864896490649164926493649464956496649764986499650065016502650365046505650665076508650965106511651265136514651565166517651865196520652165226523652465256526652765286529653065316532653365346535653665376538653965406541654265436544654565466547654865496550655165526553655465556556655765586559656065616562656365646565656665676568656965706571657265736574657565766577657865796580658165826583658465856586658765886589659065916592659365946595659665976598659966006601660266036604660566066607660866096610661166126613661466156616661766186619662066216622662366246625662666276628662966306631663266336634663566366637663866396640664166426643664466456646664766486649665066516652665366546655665666576658665966606661666266636664666566666667666866696670667166726673667466756676667766786679668066816682668366846685668666876688668966906691669266936694669566966697669866996700670167026703670467056706670767086709671067116712671367146715671667176718671967206721672267236724672567266727672867296730673167326733673467356736673767386739674067416742674367446745674667476748674967506751675267536754675567566757675867596760676167626763676467656766676767686769677067716772677367746775677667776778677967806781678267836784678567866787678867896790679167926793679467956796679767986799680068016802680368046805680668076808680968106811681268136814681568166817681868196820682168226823682468256826682768286829683068316832683368346835683668376838683968406841684268436844684568466847684868496850685168526853685468556856685768586859686068616862686368646865686668676868686968706871687268736874687568766877687868796880688168826883688468856886688768886889689068916892689368946895689668976898689969006901690269036904690569066907690869096910691169126913691469156916691769186919692069216922692369246925692669276928692969306931693269336934693569366937693869396940694169426943694469456946694769486949695069516952695369546955695669576958695969606961696269636964696569666967696869696970697169726973697469756976697769786979698069816982698369846985698669876988698969906991699269936994699569966997699869997000700170027003
  1. //
  2. // Copyright (c) 2016-2019 Vinnie Falco (vinnie dot falco at gmail dot com)
  3. // Copyright (c) 2019-2020 Krystian Stasiowski (sdkrystian at gmail dot com)
  4. //
  5. // Distributed under the Boost Software License, Version 1.0. (See accompanying
  6. // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
  7. //
  8. // Official repository: https://github.com/boostorg/static_string
  9. //
  10. #ifndef BHO_STATIC_STRING_STATIC_STRING_HPP
  11. #define BHO_STATIC_STRING_STATIC_STRING_HPP
  12. #if defined(__GNUC__) && __GNUC__ >= 8
  13. #pragma GCC diagnostic push
  14. #pragma GCC system_header
  15. // false positives
  16. #pragma GCC diagnostic ignored "-Warray-bounds"
  17. #pragma GCC diagnostic ignored "-Wrestrict"
  18. #pragma GCC diagnostic ignored "-Wstringop-overflow"
  19. #endif
  20. #if defined(__GNUC__) && __GNUC__ >= 7
  21. #pragma GCC diagnostic push
  22. #pragma GCC diagnostic ignored "-Wnoexcept-type"
  23. #endif
  24. // External include guard
  25. #ifndef BHO_STATIC_STRING_CONFIG_HPP
  26. #include <asio2/bho/static_string/config.hpp>
  27. #include <asio2/bho/config/workaround.hpp>
  28. #endif
  29. #include <algorithm>
  30. #include <cstdint>
  31. #include <cstdio>
  32. #include <cwchar>
  33. #include <functional>
  34. #include <initializer_list>
  35. #include <limits>
  36. #include <iosfwd>
  37. #include <type_traits>
  38. namespace bho {
  39. namespace static_strings {
  40. #ifndef BHO_STATIC_STRING_DOCS
  41. template<std::size_t N, typename CharT, typename Traits>
  42. class basic_static_string;
  43. //------------------------------------------------------------------------------
  44. //
  45. // Aliases
  46. //
  47. //------------------------------------------------------------------------------
  48. template<std::size_t N>
  49. using static_string =
  50. basic_static_string<N, char, std::char_traits<char>>;
  51. template<std::size_t N>
  52. using static_wstring =
  53. basic_static_string<N, wchar_t, std::char_traits<wchar_t>>;
  54. template<std::size_t N>
  55. using static_u16string =
  56. basic_static_string<N, char16_t, std::char_traits<char16_t>>;
  57. template<std::size_t N>
  58. using static_u32string =
  59. basic_static_string<N, char32_t, std::char_traits<char32_t>>;
  60. #ifdef __cpp_char8_t
  61. template<std::size_t N>
  62. using static_u8string =
  63. basic_static_string<N, char8_t, std::char_traits<char8_t>>;
  64. #endif
  65. //--------------------------------------------------------------------------
  66. //
  67. // Detail
  68. //
  69. //--------------------------------------------------------------------------
  70. namespace detail {
  71. // Find the smallest width integral type that can hold a value as large as N (Glen Fernandes)
  72. template<std::size_t N>
  73. using smallest_width =
  74. typename std::conditional<(N <= (std::numeric_limits<unsigned char>::max)()), unsigned char,
  75. typename std::conditional<(N <= (std::numeric_limits<unsigned short>::max)()), unsigned short,
  76. typename std::conditional<(N <= (std::numeric_limits<unsigned int>::max)()), unsigned int,
  77. typename std::conditional<(N <= (std::numeric_limits<unsigned long>::max)()), unsigned long,
  78. typename std::conditional<(N <= (std::numeric_limits<unsigned long long>::max)()), unsigned long long,
  79. std::size_t>::type>::type>::type>::type>::type;
  80. // std::is_nothrow_convertible is C++20
  81. template<typename To>
  82. void is_nothrow_convertible_helper(To) noexcept;
  83. // MSVC is unable to parse this as a single expression, so a helper is needed
  84. template<typename From, typename To, typename =
  85. decltype(is_nothrow_convertible_helper<To>(std::declval<From>()))>
  86. struct is_nothrow_convertible_msvc_helper
  87. {
  88. static const bool value =
  89. noexcept(is_nothrow_convertible_helper<To>(std::declval<From>()));
  90. };
  91. template<typename From, typename To, typename = void>
  92. struct is_nothrow_convertible
  93. : std::false_type { };
  94. template<typename From, typename To>
  95. struct is_nothrow_convertible<From, To, typename std::enable_if<
  96. is_nothrow_convertible_msvc_helper<From, To>::value>::type>
  97. : std::true_type { };
  98. // GCC 4.8, 4.9 workaround for void_t to make the defining-type-id dependant
  99. template<typename...>
  100. struct void_t_helper
  101. {
  102. using type = void;
  103. };
  104. // void_t for c++11
  105. template<typename... Ts>
  106. using void_t = typename void_t_helper<Ts...>::type;
  107. template <class T, typename CharT, typename = void>
  108. struct is_string_like : std::false_type {};
  109. template<typename T, typename CharT>
  110. struct is_string_like<
  111. T, CharT,
  112. void_t<
  113. decltype(std::declval<CharT const*&>() = std::declval<T>().data()),
  114. decltype(std::declval<std::size_t&>() = std::declval<T>().size())>>
  115. : std::true_type
  116. {};
  117. // Check if a type can be used for templated
  118. // overloads string_view_type
  119. // This will be used by overloads that accept the string_view types
  120. // directly and other convertible types such as std::string.
  121. // When no string_view type is available, then we check for the
  122. // data and size member functions, and use them directly for assignments.
  123. template<typename T, typename CharT, typename Traits, typename = void>
  124. struct enable_if_viewable { };
  125. template<typename T, typename CharT, typename Traits>
  126. struct enable_if_viewable<T, CharT, Traits,
  127. typename std::enable_if<
  128. #if !defined(BHO_STATIC_STRING_HAS_ANY_STRING_VIEW)
  129. is_string_like<T, CharT>::value
  130. #elif defined(BHO_STATIC_STRING_STANDALONE)
  131. std::is_convertible<const T&, std::basic_string_view<CharT, Traits>>::value &&
  132. !std::is_convertible<const T&, const CharT*>::value
  133. #else
  134. (
  135. std::is_convertible<const T&, basic_string_view<CharT, Traits>>::value ||
  136. std::is_convertible<const T&, core::basic_string_view<CharT>>::value
  137. ) &&
  138. !std::is_convertible<const T&, const CharT*>::value
  139. #endif
  140. >::type>
  141. {
  142. using type = void;
  143. };
  144. template<typename T, typename CharT, typename Traits>
  145. using enable_if_viewable_t = typename enable_if_viewable<T, CharT, Traits>::type;
  146. // The common string_view type used in private operations with enable_if_viewable_t
  147. // - T const& itself when no string_view type is available
  148. // - basic_string_view (bho::string_view or std::string_view) when in
  149. // standalone because core::detail::string_view is unavailable
  150. // - core::detail::basic_string_view otherwise because it's convertible
  151. // to and from most types, including std::string_view
  152. // After converting a parameter to a common_string_view_type reference, we
  153. // can use the data() and size() member functions.
  154. #if !defined(BHO_STATIC_STRING_HAS_ANY_STRING_VIEW)
  155. template<typename T, typename CharT, typename Traits>
  156. using common_string_view_type = T const&;
  157. #elif defined(BHO_STATIC_STRING_STANDALONE)
  158. template<typename T, typename CharT, typename Traits>
  159. using common_string_view_type = basic_string_view<CharT, Traits>;
  160. #else
  161. template <class T, typename CharT, typename Traits, typename = void>
  162. struct common_string_view_type_impl {};
  163. template<typename T, typename CharT, typename Traits>
  164. struct common_string_view_type_impl<
  165. T, CharT, Traits,
  166. typename std::enable_if<
  167. is_string_like<T, CharT>::value &&
  168. !std::is_convertible<const T&, basic_string_view<CharT, Traits>>::value &&
  169. !std::is_convertible<const T&, core::basic_string_view<CharT>>::value>::type>
  170. {
  171. using type = T const&;
  172. };
  173. template<typename T, typename CharT, typename Traits>
  174. struct common_string_view_type_impl<
  175. T, CharT, Traits,
  176. typename std::enable_if<
  177. std::is_convertible<const T&, basic_string_view<CharT, Traits>>::value &&
  178. !std::is_convertible<const T&, core::basic_string_view<CharT>>::value>::type>
  179. {
  180. using type = basic_string_view<CharT, Traits>;
  181. };
  182. template<typename T, typename CharT, typename Traits>
  183. struct common_string_view_type_impl<
  184. T, CharT, Traits,
  185. typename std::enable_if<
  186. std::is_convertible<const T&, core::basic_string_view<CharT>>::value>::type>
  187. {
  188. using type = core::basic_string_view<CharT>;
  189. };
  190. template<typename T, typename CharT, typename Traits>
  191. using common_string_view_type = typename common_string_view_type_impl<T, CharT, Traits>::type;
  192. #endif
  193. // Simplified check for if a type is an iterator
  194. template<typename T, typename = void>
  195. struct is_iterator : std::false_type { };
  196. template<typename T>
  197. struct is_iterator<T,
  198. typename std::enable_if<std::is_class<T>::value,
  199. void_t<typename T::iterator_category>>::type>
  200. : std::true_type { };
  201. template<typename T>
  202. struct is_iterator<T*, void>
  203. : std::true_type { };
  204. template<typename T, typename = void>
  205. struct is_input_iterator : std::false_type { };
  206. template<typename T>
  207. struct is_input_iterator<T, typename std::enable_if<is_iterator<T>::value &&
  208. std::is_convertible<typename std::iterator_traits<T>::iterator_category,
  209. std::input_iterator_tag>::value>::type>
  210. : std::true_type { };
  211. template<typename T, typename = void>
  212. struct is_forward_iterator : std::false_type { };
  213. template<typename T>
  214. struct is_forward_iterator<T, typename std::enable_if<is_iterator<T>::value &&
  215. std::is_convertible<typename std::iterator_traits<T>::iterator_category,
  216. std::forward_iterator_tag>::value>::type>
  217. : std::true_type { };
  218. template<typename T, typename = void>
  219. struct is_subtractable
  220. : std::false_type { };
  221. template<typename T>
  222. struct is_subtractable<T, void_t<decltype(std::declval<T&>() - std::declval<T&>())>>
  223. : std::true_type { };
  224. // constexpr distance for c++14
  225. template<
  226. typename ForwardIt,
  227. typename std::enable_if<!is_subtractable<ForwardIt>::value>::type* = nullptr>
  228. BHO_STATIC_STRING_CPP14_CONSTEXPR
  229. std::size_t
  230. distance(ForwardIt first, ForwardIt last)
  231. {
  232. std::size_t dist = 0;
  233. for (; first != last; ++first, ++dist);
  234. return dist;
  235. }
  236. template<
  237. typename RandomIt,
  238. typename std::enable_if<is_subtractable<RandomIt>::value>::type* = nullptr>
  239. BHO_STATIC_STRING_CPP14_CONSTEXPR
  240. std::size_t
  241. distance(RandomIt first, RandomIt last)
  242. {
  243. return last - first;
  244. }
  245. // Copy using traits, respecting iterator rules
  246. template<typename Traits, typename InputIt, typename CharT>
  247. BHO_STATIC_STRING_CPP14_CONSTEXPR
  248. void
  249. copy_with_traits(
  250. InputIt first,
  251. InputIt last,
  252. CharT* out)
  253. {
  254. for (; first != last; ++first, ++out)
  255. Traits::assign(*out, *first);
  256. }
  257. // Optimization for using the smallest possible type
  258. template<std::size_t N, typename CharT, typename Traits>
  259. class static_string_base
  260. {
  261. private:
  262. using size_type = smallest_width<N>;
  263. using value_type = typename Traits::char_type;
  264. using pointer = value_type*;
  265. using const_pointer = const value_type*;
  266. public:
  267. BHO_STATIC_STRING_CPP11_CONSTEXPR
  268. static_string_base() noexcept { };
  269. BHO_STATIC_STRING_CPP14_CONSTEXPR
  270. pointer
  271. data_impl() noexcept
  272. {
  273. return data_;
  274. }
  275. BHO_STATIC_STRING_CPP14_CONSTEXPR
  276. const_pointer
  277. data_impl() const noexcept
  278. {
  279. return data_;
  280. }
  281. BHO_STATIC_STRING_CPP11_CONSTEXPR
  282. std::size_t
  283. size_impl() const noexcept
  284. {
  285. return size_;
  286. }
  287. BHO_STATIC_STRING_CPP14_CONSTEXPR
  288. std::size_t
  289. set_size(std::size_t n) noexcept
  290. {
  291. // Functions that set size will throw
  292. // if the new size would exceed max_size()
  293. // therefore we can guarantee that this will
  294. // not lose data.
  295. return size_ = size_type(n);
  296. }
  297. BHO_STATIC_STRING_CPP14_CONSTEXPR
  298. void
  299. term_impl() noexcept
  300. {
  301. Traits::assign(data_[size_], value_type());
  302. }
  303. size_type size_ = 0;
  304. value_type data_[N + 1]{};
  305. };
  306. // Optimization for when the size is 0
  307. template<typename CharT, typename Traits>
  308. class static_string_base<0, CharT, Traits>
  309. {
  310. private:
  311. using value_type = typename Traits::char_type;
  312. using pointer = value_type*;
  313. public:
  314. BHO_STATIC_STRING_CPP11_CONSTEXPR
  315. static_string_base() noexcept { }
  316. // Modifying the null terminator is UB
  317. BHO_STATIC_STRING_CPP11_CONSTEXPR
  318. pointer
  319. data_impl() const noexcept
  320. {
  321. return const_cast<pointer>(&null_);
  322. }
  323. BHO_STATIC_STRING_CPP11_CONSTEXPR
  324. std::size_t
  325. size_impl() const noexcept
  326. {
  327. return 0;
  328. }
  329. BHO_STATIC_STRING_CPP11_CONSTEXPR
  330. std::size_t
  331. set_size(std::size_t) const noexcept
  332. {
  333. return 0;
  334. }
  335. BHO_STATIC_STRING_CPP14_CONSTEXPR
  336. void
  337. term_impl() const noexcept { }
  338. private:
  339. static constexpr const value_type null_{};
  340. };
  341. // This is only needed in C++14 and lower.
  342. // see http://eel.is/c++draft/depr.static.constexpr
  343. #ifndef BHO_STATIC_STRING_CPP17
  344. template<typename CharT, typename Traits>
  345. constexpr
  346. const
  347. typename static_string_base<0, CharT, Traits>::value_type
  348. static_string_base<0, CharT, Traits>::
  349. null_;
  350. #endif
  351. template<typename CharT, typename Traits>
  352. BHO_STATIC_STRING_CPP14_CONSTEXPR
  353. inline
  354. int
  355. lexicographical_compare(
  356. const CharT* s1,
  357. std::size_t n1,
  358. const CharT* s2,
  359. std::size_t n2) noexcept
  360. {
  361. if(n1 < n2)
  362. return Traits::compare(
  363. s1, s2, n1) <= 0 ? -1 : 1;
  364. if(n1 > n2)
  365. return Traits::compare(
  366. s1, s2, n2) >= 0 ? 1 : -1;
  367. return Traits::compare(s1, s2, n1);
  368. }
  369. template<typename Traits, typename Integer>
  370. inline
  371. char*
  372. integer_to_string(
  373. char* str_end,
  374. Integer value,
  375. std::true_type) noexcept
  376. {
  377. if (value == 0)
  378. {
  379. Traits::assign(*--str_end, '0');
  380. return str_end;
  381. }
  382. if (value < 0)
  383. {
  384. const bool is_min = value == (std::numeric_limits<Integer>::min)();
  385. // negation of a min value cannot be represented
  386. if (is_min)
  387. value = (std::numeric_limits<Integer>::max)();
  388. else
  389. value = -value;
  390. const auto last_char = str_end - 1;
  391. for (; value > 0; value /= 10)
  392. Traits::assign(*--str_end, "0123456789"[value % 10]);
  393. // minimum values are powers of 2, so it will
  394. // never terminate with a 9.
  395. if (is_min)
  396. Traits::assign(*last_char, Traits::to_char_type(
  397. Traits::to_int_type(*last_char) + 1));
  398. Traits::assign(*--str_end, '-');
  399. return str_end;
  400. }
  401. for (; value > 0; value /= 10)
  402. Traits::assign(*--str_end, "0123456789"[value % 10]);
  403. return str_end;
  404. }
  405. template<typename Traits, typename Integer>
  406. inline
  407. char*
  408. integer_to_string(
  409. char* str_end,
  410. Integer value,
  411. std::false_type) noexcept
  412. {
  413. if (value == 0)
  414. {
  415. Traits::assign(*--str_end, '0');
  416. return str_end;
  417. }
  418. for (; value > 0; value /= 10)
  419. Traits::assign(*--str_end, "0123456789"[value % 10]);
  420. return str_end;
  421. }
  422. template<typename Traits, typename Integer>
  423. inline
  424. wchar_t*
  425. integer_to_wstring(
  426. wchar_t* str_end,
  427. Integer value,
  428. std::true_type) noexcept
  429. {
  430. if (value == 0)
  431. {
  432. Traits::assign(*--str_end, L'0');
  433. return str_end;
  434. }
  435. if (value < 0)
  436. {
  437. const bool is_min = value == (std::numeric_limits<Integer>::min)();
  438. // negation of a min value cannot be represented
  439. if (is_min)
  440. value = (std::numeric_limits<Integer>::max)();
  441. else
  442. value = -value;
  443. const auto last_char = str_end - 1;
  444. for (; value > 0; value /= 10)
  445. Traits::assign(*--str_end, L"0123456789"[value % 10]);
  446. // minimum values are powers of 2, so it will
  447. // never terminate with a 9.
  448. if (is_min)
  449. Traits::assign(*last_char, Traits::to_char_type(
  450. Traits::to_int_type(*last_char) + 1));
  451. Traits::assign(*--str_end, L'-');
  452. return str_end;
  453. }
  454. for (; value > 0; value /= 10)
  455. Traits::assign(*--str_end, L"0123456789"[value % 10]);
  456. return str_end;
  457. }
  458. template<typename Traits, typename Integer>
  459. inline
  460. wchar_t*
  461. integer_to_wstring(
  462. wchar_t* str_end,
  463. Integer value,
  464. std::false_type) noexcept
  465. {
  466. if (value == 0)
  467. {
  468. Traits::assign(*--str_end, L'0');
  469. return str_end;
  470. }
  471. for (; value > 0; value /= 10)
  472. Traits::assign(*--str_end, L"0123456789"[value % 10]);
  473. return str_end;
  474. }
  475. template<std::size_t N, typename Integer>
  476. inline
  477. static_string<N>
  478. to_static_string_int_impl(Integer value) noexcept
  479. {
  480. char buffer[N];
  481. const auto digits_end = std::end(buffer);
  482. const auto digits_begin = integer_to_string<std::char_traits<char>, Integer>(
  483. digits_end, value, std::is_signed<Integer>{});
  484. return static_string<N>(digits_begin, std::distance(digits_begin, digits_end));
  485. }
  486. template<std::size_t N, typename Integer>
  487. inline
  488. static_wstring<N>
  489. to_static_wstring_int_impl(Integer value) noexcept
  490. {
  491. wchar_t buffer[N];
  492. const auto digits_end = std::end(buffer);
  493. const auto digits_begin = integer_to_wstring<std::char_traits<wchar_t>, Integer>(
  494. digits_end, value, std::is_signed<Integer>{});
  495. return static_wstring<N>(digits_begin, std::distance(digits_begin, digits_end));
  496. }
  497. BHO_STATIC_STRING_CPP11_CONSTEXPR
  498. inline
  499. int
  500. count_digits(std::size_t value)
  501. {
  502. return value < 10 ? 1 : count_digits(value / 10) + 1;
  503. }
  504. // Ignore -Wformat-truncation, we know what
  505. // we are doing here. The version check does
  506. // not need to be extremely precise.
  507. #if defined(__GNUC__) && __GNUC__ >= 7
  508. #pragma GCC diagnostic push
  509. #pragma GCC diagnostic ignored "-Wformat-truncation"
  510. #endif
  511. template<std::size_t N>
  512. inline
  513. static_string<N>
  514. to_static_string_float_impl(double value) noexcept
  515. {
  516. // we have to assume here that no reasonable implementation
  517. // will require more than 2^63 chars to represent a float value.
  518. const long long narrow =
  519. static_cast<long long>(N);
  520. // extra one needed for null terminator
  521. char buffer[N + 1];
  522. // we know that a formatting error will not occur, so
  523. // we assume that the result is always positive
  524. if (std::size_t(std::snprintf(buffer, N + 1, "%f", value)) > N)
  525. {
  526. // the + 4 is for the decimal, 'e',
  527. // its sign, and the sign of the integral portion
  528. const int reserved_count =
  529. (std::max)(2, count_digits(
  530. std::numeric_limits<double>::max_exponent10)) + 4;
  531. const int precision = narrow > reserved_count ?
  532. N - reserved_count : 0;
  533. // switch to scientific notation
  534. std::snprintf(buffer, N + 1, "%.*e", precision, value);
  535. }
  536. // this will not throw
  537. return static_string<N>(buffer);
  538. }
  539. template<std::size_t N>
  540. inline
  541. static_string<N>
  542. to_static_string_float_impl(long double value) noexcept
  543. {
  544. // we have to assume here that no reasonable implementation
  545. // will require more than 2^63 chars to represent a float value.
  546. const long long narrow =
  547. static_cast<long long>(N);
  548. // extra one needed for null terminator
  549. char buffer[N + 1];
  550. // snprintf returns the number of characters
  551. // that would have been written
  552. // we know that a formatting error will not occur, so
  553. // we assume that the result is always positive
  554. if (std::size_t(std::snprintf(buffer, N + 1, "%Lf", value)) > N)
  555. {
  556. // the + 4 is for the decimal, 'e',
  557. // its sign, and the sign of the integral portion
  558. const int reserved_count =
  559. (std::max)(2, count_digits(
  560. std::numeric_limits<long double>::max_exponent10)) + 4;
  561. const int precision = narrow > reserved_count ?
  562. N - reserved_count : 0;
  563. // switch to scientific notation
  564. std::snprintf(buffer, N + 1, "%.*Le", precision, value);
  565. }
  566. // this will not throw
  567. return static_string<N>(buffer);
  568. }
  569. template<std::size_t N>
  570. inline
  571. static_wstring<N>
  572. to_static_wstring_float_impl(double value) noexcept
  573. {
  574. // we have to assume here that no reasonable implementation
  575. // will require more than 2^63 chars to represent a float value.
  576. const long long narrow =
  577. static_cast<long long>(N);
  578. // extra one needed for null terminator
  579. wchar_t buffer[N + 1];
  580. // swprintf returns a negative number if it can't
  581. // fit all the characters in the buffer.
  582. // mingw has a non-standard swprintf, so
  583. // this just covers all the bases. short
  584. // circuit evaluation will ensure that the
  585. // second operand is not evaluated on conforming
  586. // implementations.
  587. const long long num_written =
  588. std::swprintf(buffer, N + 1, L"%f", value);
  589. if (num_written < 0 ||
  590. num_written > narrow)
  591. {
  592. // the + 4 is for the decimal, 'e',
  593. // its sign, and the sign of the integral portion
  594. const int reserved_count =
  595. (std::max)(2, count_digits(
  596. std::numeric_limits<double>::max_exponent10)) + 4;
  597. const int precision = narrow > reserved_count ?
  598. N - reserved_count : 0;
  599. // switch to scientific notation
  600. std::swprintf(buffer, N + 1, L"%.*e", precision, value);
  601. }
  602. // this will not throw
  603. return static_wstring<N>(buffer);
  604. }
  605. template<std::size_t N>
  606. inline
  607. static_wstring<N>
  608. to_static_wstring_float_impl(long double value) noexcept
  609. {
  610. // we have to assume here that no reasonable implementation
  611. // will require more than 2^63 chars to represent a float value.
  612. const long long narrow =
  613. static_cast<long long>(N);
  614. // extra one needed for null terminator
  615. wchar_t buffer[N + 1];
  616. // swprintf returns a negative number if it can't
  617. // fit all the characters in the buffer.
  618. // mingw has a non-standard swprintf, so
  619. // this just covers all the bases. short
  620. // circuit evaluation will ensure that the
  621. // second operand is not evaluated on conforming
  622. // implementations.
  623. const long long num_written =
  624. std::swprintf(buffer, N + 1, L"%Lf", value);
  625. if (num_written < 0 ||
  626. num_written > narrow)
  627. {
  628. // the + 4 is for the decimal, 'e',
  629. // its sign, and the sign of the integral portion
  630. const int reserved_count =
  631. (std::max)(2, count_digits(
  632. std::numeric_limits<long double>::max_exponent10)) + 4;
  633. const int precision = narrow > reserved_count ?
  634. N - reserved_count : 0;
  635. // switch to scientific notation
  636. std::swprintf(buffer, N + 1, L"%.*Le", precision, value);
  637. }
  638. // this will not throw
  639. return static_wstring<N>(buffer);
  640. }
  641. #if defined(__GNUC__) && __GNUC__ >= 7
  642. #pragma GCC diagnostic pop
  643. #endif
  644. template<typename Traits, typename CharT, typename ForwardIterator>
  645. BHO_STATIC_STRING_CPP14_CONSTEXPR
  646. inline
  647. ForwardIterator
  648. find_not_of(
  649. ForwardIterator first,
  650. ForwardIterator last,
  651. const CharT* str,
  652. std::size_t n) noexcept
  653. {
  654. for (; first != last; ++first)
  655. if (!Traits::find(str, n, *first))
  656. return first;
  657. return last;
  658. }
  659. // constexpr search for C++14
  660. template<typename ForwardIt1, typename ForwardIt2, typename BinaryPredicate>
  661. BHO_STATIC_STRING_CPP14_CONSTEXPR
  662. inline
  663. ForwardIt1
  664. search(
  665. ForwardIt1 first,
  666. ForwardIt1 last,
  667. ForwardIt2 s_first,
  668. ForwardIt2 s_last,
  669. BinaryPredicate p)
  670. {
  671. for (; ; ++first)
  672. {
  673. ForwardIt1 it = first;
  674. for (ForwardIt2 s_it = s_first; ; ++it, ++s_it)
  675. {
  676. if (s_it == s_last)
  677. return first;
  678. if (it == last)
  679. return last;
  680. if (!p(*it, *s_it))
  681. break;
  682. }
  683. }
  684. }
  685. template<typename InputIt, typename ForwardIt, typename BinaryPredicate>
  686. BHO_STATIC_STRING_CPP14_CONSTEXPR
  687. inline
  688. InputIt
  689. find_first_of(
  690. InputIt first,
  691. InputIt last,
  692. ForwardIt s_first,
  693. ForwardIt s_last,
  694. BinaryPredicate p)
  695. {
  696. for (; first != last; ++first)
  697. for (ForwardIt it = s_first; it != s_last; ++it)
  698. if (p(*first, *it))
  699. return first;
  700. return last;
  701. }
  702. // KRYSTIAN TODO: add a constexpr rotate
  703. // Check if a pointer lies within the range {src_first, src_last)
  704. // without unspecified behavior, allowing it to be used
  705. // in a constant evaluation.
  706. template<typename T>
  707. BHO_STATIC_STRING_CPP14_CONSTEXPR
  708. inline
  709. bool
  710. ptr_in_range(
  711. const T* src_first,
  712. const T* src_last,
  713. const T* ptr)
  714. {
  715. #if defined(BHO_STATIC_STRING_CPP14) && \
  716. defined(BHO_STATIC_STRING_IS_CONST_EVAL)
  717. // Our second best option is to use is_constant_evaluated
  718. // and a loop that checks for equality, since equality for
  719. // pointer to object types is never unspecified in this case.
  720. if (BHO_STATIC_STRING_IS_CONST_EVAL)
  721. {
  722. for (; src_first != src_last; ++src_first)
  723. if (ptr == src_first)
  724. return true;
  725. return false;
  726. }
  727. #endif
  728. // We want to make this usable in constant expressions as much as possible
  729. // while retaining the guarentee that the comparison has a strict total ordering.
  730. // We also want this to be fast. Since different compilers have differing levels
  731. // of conformance, we will settle for the best option that is available.
  732. // We don't care about this in C++11, since this function would have
  733. // no applications in constant expressions.
  734. #if defined(BHO_STATIC_STRING_CPP14) && \
  735. defined(BHO_STATIC_STRING_NO_PTR_COMP_FUNCTIONS)
  736. // If library comparison functions don't work,
  737. // we can use try builtin comparison operators instead.
  738. return ptr >= src_first && ptr < src_last;
  739. #else
  740. // Use the library comparison functions if we can't use
  741. // is_constant_evaluated or if we don't need to.
  742. return std::greater_equal<const T*>()(ptr, src_first) &&
  743. std::less<const T*>()(ptr, src_last);
  744. #endif
  745. }
  746. // This workaround is for gcc 5,
  747. // which prohibits throw expressions in constexpr
  748. // functions, but for some reason permits them in
  749. // constructors.
  750. #ifdef BHO_STATIC_STRING_GCC5_BAD_CONSTEXPR
  751. template<typename Exception>
  752. struct throw_exception
  753. {
  754. BHO_STATIC_STRING_NORETURN
  755. BHO_STATIC_STRING_CPP14_CONSTEXPR
  756. throw_exception(const char* msg)
  757. {
  758. BHO_STATIC_STRING_THROW(Exception(msg));
  759. }
  760. };
  761. #else
  762. template<typename Exception>
  763. BHO_STATIC_STRING_NORETURN
  764. inline
  765. void
  766. throw_exception(const char* msg)
  767. {
  768. BHO_STATIC_STRING_THROW(Exception(msg));
  769. }
  770. #endif
  771. } // detail
  772. #endif
  773. //--------------------------------------------------------------------------
  774. //
  775. // static_string
  776. //
  777. //--------------------------------------------------------------------------
  778. /** A fixed-capacity string.
  779. These objects behave like `std::string` except that the storage
  780. is not dynamically allocated but rather fixed in size, and
  781. stored in the object itself.
  782. These strings offer performance advantages when an algorithm
  783. can execute with a reasonable upper limit on the size of a value.
  784. @par Aliases
  785. The following alias templates are provided for convenience:
  786. @code
  787. template<std::size_t N>
  788. using static_string =
  789. basic_static_string<N, char, std::char_traits<char>>;
  790. @endcode
  791. @code
  792. template<std::size_t N>
  793. using static_wstring =
  794. basic_static_string<N, wchar_t, std::char_traits<wchar_t>>;
  795. @endcode
  796. @code
  797. template<std::size_t N>
  798. using static_u16string =
  799. basic_static_string<N, char16_t, std::char_traits<char16_t>>;
  800. @endcode
  801. @code
  802. template<std::size_t N>
  803. using static_u32string =
  804. basic_static_string<N, char32_t, std::char_traits<char32_t>>;
  805. @endcode
  806. Addtionally, the alias template `static_u8string` is provided in C++20
  807. @code
  808. template<std::size_t N>
  809. using static_u8string =
  810. basic_static_string<N, char8_t, std::char_traits<char8_t>>;
  811. @endcode
  812. @see to_static_string
  813. */
  814. template<std::size_t N, typename CharT,
  815. typename Traits = std::char_traits<CharT>>
  816. class basic_static_string
  817. #ifndef BHO_STATIC_STRING_DOCS
  818. : private detail::static_string_base<N, CharT, Traits>
  819. #endif
  820. {
  821. private:
  822. template<std::size_t, class, class>
  823. friend class basic_static_string;
  824. public:
  825. //--------------------------------------------------------------------------
  826. //
  827. // Member types
  828. //
  829. //--------------------------------------------------------------------------
  830. /// The traits type.
  831. using traits_type = Traits;
  832. /// The character type.
  833. using value_type = typename traits_type::char_type;
  834. /// The size type.
  835. using size_type = std::size_t;
  836. /// The difference type.
  837. using difference_type = std::ptrdiff_t;
  838. /// The pointer type.
  839. using pointer = value_type*;
  840. /// The reference type.
  841. using reference = value_type&;
  842. /// The constant pointer type.
  843. using const_pointer = const value_type*;
  844. /// The constant reference type.
  845. using const_reference = const value_type&;
  846. /// The iterator type.
  847. using iterator = value_type*;
  848. /// The constant iterator type.
  849. using const_iterator = const value_type*;
  850. /// The reverse iterator type.
  851. using reverse_iterator =
  852. std::reverse_iterator<iterator>;
  853. /// The constant reverse iterator type.
  854. using const_reverse_iterator =
  855. std::reverse_iterator<const_iterator>;
  856. #ifdef BHO_STATIC_STRING_HAS_ANY_STRING_VIEW
  857. /// The string view type.
  858. using string_view_type =
  859. basic_string_view<value_type, traits_type>;
  860. #endif
  861. //--------------------------------------------------------------------------
  862. //
  863. // Constants
  864. //
  865. //--------------------------------------------------------------------------
  866. /// Maximum size of the string excluding any null terminator
  867. static constexpr size_type static_capacity = N;
  868. /// A special index
  869. static constexpr size_type npos = size_type(-1);
  870. //--------------------------------------------------------------------------
  871. //
  872. // Construction
  873. //
  874. //--------------------------------------------------------------------------
  875. /** Constructor.
  876. Construct an empty string
  877. */
  878. BHO_STATIC_STRING_CPP11_CONSTEXPR
  879. basic_static_string() noexcept
  880. {
  881. #ifdef BHO_STATIC_STRING_CPP20
  882. term();
  883. #endif
  884. }
  885. /** Constructor.
  886. Construct the string with `count` copies of character `ch`.
  887. The behavior is undefined if `count >= npos`
  888. */
  889. BHO_STATIC_STRING_CPP14_CONSTEXPR
  890. basic_static_string(
  891. size_type count,
  892. value_type ch)
  893. {
  894. assign(count, ch);
  895. }
  896. /** Constructor.
  897. Construct with a substring (pos, other.size()) of `other`.
  898. */
  899. template<std::size_t M>
  900. BHO_STATIC_STRING_CPP14_CONSTEXPR
  901. basic_static_string(
  902. const basic_static_string<M, CharT, Traits>& other,
  903. size_type pos)
  904. {
  905. assign(other, pos);
  906. }
  907. /** Constructor.
  908. Construct with a substring (pos, count) of `other`.
  909. */
  910. template<std::size_t M>
  911. BHO_STATIC_STRING_CPP14_CONSTEXPR
  912. basic_static_string(
  913. const basic_static_string<M, CharT, Traits>& other,
  914. size_type pos,
  915. size_type count)
  916. {
  917. assign(other, pos, count);
  918. }
  919. /** Constructor.
  920. Construct with the first `count` characters of `s`, including nulls.
  921. */
  922. BHO_STATIC_STRING_CPP14_CONSTEXPR
  923. basic_static_string(
  924. const_pointer s,
  925. size_type count)
  926. {
  927. assign(s, count);
  928. }
  929. /** Constructor.
  930. Construct from a null terminated string.
  931. */
  932. BHO_STATIC_STRING_CPP14_CONSTEXPR
  933. basic_static_string(const_pointer s)
  934. {
  935. assign(s);
  936. }
  937. /** Constructor.
  938. Construct from a range of characters
  939. */
  940. template<typename InputIterator
  941. #ifndef BHO_STATIC_STRING_DOCS
  942. , typename std::enable_if<
  943. detail::is_input_iterator<InputIterator>
  944. ::value>::type* = nullptr
  945. #endif
  946. >
  947. BHO_STATIC_STRING_CPP14_CONSTEXPR
  948. basic_static_string(
  949. InputIterator first,
  950. InputIterator last)
  951. {
  952. // KRYSTIAN TODO: we can use a better algorithm if this is a forward iterator
  953. assign(first, last);
  954. }
  955. /** Constructor.
  956. Copy constructor.
  957. */
  958. BHO_STATIC_STRING_CPP14_CONSTEXPR
  959. basic_static_string(const basic_static_string& other) noexcept
  960. {
  961. assign(other);
  962. }
  963. /** Constructor.
  964. Copy constructor.
  965. */
  966. template<std::size_t M>
  967. BHO_STATIC_STRING_CPP14_CONSTEXPR
  968. basic_static_string(
  969. const basic_static_string<M, CharT, Traits>& other)
  970. {
  971. assign(other);
  972. }
  973. /** Constructor.
  974. Construct from an initializer list
  975. */
  976. BHO_STATIC_STRING_CPP14_CONSTEXPR
  977. basic_static_string(std::initializer_list<value_type> init)
  978. {
  979. assign(init.begin(), init.size());
  980. }
  981. /** Constructor.
  982. Construct from a object convertible to `string_view_type`
  983. */
  984. template<typename T
  985. #ifndef BHO_STATIC_STRING_DOCS
  986. , typename = detail::enable_if_viewable_t<T, CharT, Traits>
  987. #endif
  988. >
  989. explicit
  990. BHO_STATIC_STRING_CPP14_CONSTEXPR
  991. basic_static_string(const T& t)
  992. {
  993. assign(t);
  994. }
  995. /** Constructor.
  996. Construct from any object convertible to `string_view_type`.
  997. The range (pos, n) is extracted from the value
  998. obtained by converting `t` to `string_view_type`,
  999. and used to construct the string.
  1000. */
  1001. template<typename T
  1002. #ifndef BHO_STATIC_STRING_DOCS
  1003. , typename = detail::enable_if_viewable_t<T, CharT, Traits>
  1004. #endif
  1005. >
  1006. BHO_STATIC_STRING_CPP14_CONSTEXPR
  1007. basic_static_string(
  1008. const T& t,
  1009. size_type pos,
  1010. size_type n)
  1011. {
  1012. assign(t, pos, n);
  1013. }
  1014. //--------------------------------------------------------------------------
  1015. //
  1016. // Assignment
  1017. //
  1018. //--------------------------------------------------------------------------
  1019. /** Assign to the string.
  1020. Replaces the contents with those of
  1021. the string `s`.
  1022. @par Complexity
  1023. Linear in `s.size()`.
  1024. @par Exception Safety
  1025. Strong guarantee.
  1026. @return `*this`
  1027. @param s The string to replace
  1028. the contents with.
  1029. @throw std::length_error `s.size() > max_size()`.
  1030. */
  1031. BHO_STATIC_STRING_CPP14_CONSTEXPR
  1032. basic_static_string&
  1033. operator=(const basic_static_string& s)
  1034. {
  1035. return assign(s);
  1036. }
  1037. /** Assign to the string.
  1038. Replaces the contents with those of
  1039. the string `s`.
  1040. @par Complexity
  1041. Linear in `s.size()`.
  1042. @par Exception Safety
  1043. Strong guarantee.
  1044. @tparam M The size of the other string.
  1045. @return `*this`
  1046. @param s The string to replace
  1047. the contents with.
  1048. @throw std::length_error `s.size() > max_size()`.
  1049. */
  1050. template<std::size_t M>
  1051. BHO_STATIC_STRING_CPP14_CONSTEXPR
  1052. basic_static_string&
  1053. operator=(const basic_static_string<M, CharT, Traits>& s)
  1054. {
  1055. return assign(s);
  1056. }
  1057. /** Assign to the string.
  1058. Replaces the contents with those of
  1059. `{s, s + traits_type::length(s))`.
  1060. @par Complexity
  1061. Linear in `count`.
  1062. @par Exception Safety
  1063. Strong guarantee.
  1064. @return `*this`
  1065. @param s A pointer to the string to copy from.
  1066. @throw std::length_error `traits_type::length(s) > max_size()`.
  1067. */
  1068. BHO_STATIC_STRING_CPP14_CONSTEXPR
  1069. basic_static_string&
  1070. operator=(const_pointer s)
  1071. {
  1072. return assign(s);
  1073. }
  1074. /** Assign to the string.
  1075. Replaces the contents with a single copy of
  1076. the character `ch`.
  1077. @par Complexity
  1078. Constant.
  1079. @par Exception Safety
  1080. Strong guarantee.
  1081. @return `*this`
  1082. @param ch The character to assign to.
  1083. @throw std::length_error `count > max_size()`.
  1084. */
  1085. BHO_STATIC_STRING_CPP14_CONSTEXPR
  1086. basic_static_string&
  1087. operator=(value_type ch)
  1088. {
  1089. return assign_char(ch,
  1090. std::integral_constant<bool, (N > 0)>{});
  1091. }
  1092. /** Assign to the string.
  1093. Replaces the contents with those of the
  1094. initializer list `ilist`.
  1095. @par Complexity
  1096. Linear in `init.size()`.
  1097. @par Exception Safety
  1098. Strong guarantee.
  1099. @return `*this`
  1100. @param ilist The initializer list to copy from.
  1101. @throw std::length_error `ilist.size() > max_size()`.
  1102. */
  1103. BHO_STATIC_STRING_CPP14_CONSTEXPR
  1104. basic_static_string&
  1105. operator=(std::initializer_list<value_type> ilist)
  1106. {
  1107. return assign(ilist);
  1108. }
  1109. /** Assign to the string.
  1110. Replaces the contents with those of
  1111. `sv`, where `sv` is `string_view_type(t)`.
  1112. @par Complexity
  1113. Linear in `sv.size()`.
  1114. @par Exception Safety
  1115. Strong guarantee.
  1116. @note
  1117. The view can contain null characters.
  1118. @tparam T A type convertible to `string_view_type`.
  1119. @par Constraints
  1120. @code
  1121. std::is_convertible<const T&, string_view>::value &&
  1122. !std::is_convertible<const T&, const CharT*>::value
  1123. @endcode
  1124. @return `*this`
  1125. @param t The object to assign from.
  1126. @throw std::length_error `sv.size() > max_size()`.
  1127. */
  1128. template<typename T
  1129. #ifndef BHO_STATIC_STRING_DOCS
  1130. , typename = detail::enable_if_viewable_t<T, CharT, Traits>
  1131. #endif
  1132. >
  1133. BHO_STATIC_STRING_CPP14_CONSTEXPR
  1134. basic_static_string&
  1135. operator=(const T& t)
  1136. {
  1137. return assign(t);
  1138. }
  1139. /** Assign to the string.
  1140. Replaces the contents with `count` copies of
  1141. character `ch`.
  1142. @par Complexity
  1143. Linear in `count`.
  1144. @par Exception Safety
  1145. Strong guarantee.
  1146. @return `*this`
  1147. @param count The size of the resulting string.
  1148. @param ch The value to initialize characters
  1149. of the string with.
  1150. @throw std::length_error `count > max_size()`.
  1151. */
  1152. BHO_STATIC_STRING_CPP14_CONSTEXPR
  1153. basic_static_string&
  1154. assign(
  1155. size_type count,
  1156. value_type ch);
  1157. /** Assign to the string.
  1158. Replaces the contents with those of
  1159. the string `s`.
  1160. @par Complexity
  1161. Linear in `s.size()`.
  1162. @par Exception Safety
  1163. Strong guarantee.
  1164. @tparam M The size of the other string.
  1165. @return `*this`
  1166. @param s The string to replace
  1167. the contents with.
  1168. @throw std::length_error `s.size() > max_size()`.
  1169. */
  1170. template<std::size_t M
  1171. #ifndef BHO_STATIC_STRING_DOCS
  1172. , typename std::enable_if<(M < N)>::type* = nullptr
  1173. #endif
  1174. >
  1175. BHO_STATIC_STRING_CPP14_CONSTEXPR
  1176. basic_static_string&
  1177. assign(const basic_static_string<M, CharT, Traits>& s)
  1178. {
  1179. return assign_unchecked(s.data(), s.size());
  1180. }
  1181. #ifndef BHO_STATIC_STRING_DOCS
  1182. BHO_STATIC_STRING_CPP14_CONSTEXPR
  1183. basic_static_string&
  1184. assign(const basic_static_string& s) noexcept
  1185. {
  1186. if (data() == s.data())
  1187. return *this;
  1188. return assign_unchecked(s.data(), s.size());
  1189. }
  1190. template<std::size_t M,
  1191. typename std::enable_if<(M > N)>::type* = nullptr>
  1192. BHO_STATIC_STRING_CPP14_CONSTEXPR
  1193. basic_static_string&
  1194. assign(const basic_static_string<M, CharT, Traits>& s)
  1195. {
  1196. return assign(s.data(), s.size());
  1197. }
  1198. #endif
  1199. /** Assign to the string.
  1200. Replaces the contents with those of the string `sub`,
  1201. where `sub` is `s.substr(pos, count)`.
  1202. @par Complexity
  1203. Linear in `sub.size()`.
  1204. @par Exception Safety
  1205. Strong guarantee.
  1206. @tparam M The capacity of the other string.
  1207. @return `*this`
  1208. @param s The string to replace
  1209. the contents with.
  1210. @param pos The index at which to begin the substring.
  1211. @param count The size of the substring. The default
  1212. argument for this parameter is @ref npos.
  1213. @throw std::length_error `sub.size() > max_size()`.
  1214. */
  1215. template<std::size_t M>
  1216. BHO_STATIC_STRING_CPP14_CONSTEXPR
  1217. basic_static_string&
  1218. assign(
  1219. const basic_static_string<M, CharT, Traits>& s,
  1220. size_type pos,
  1221. size_type count = npos)
  1222. {
  1223. return assign(s.data() + pos, s.capped_length(pos, count));
  1224. }
  1225. /** Assign to the string.
  1226. Replaces the contents with those of `{s, s + count)`.
  1227. @par Complexity
  1228. Linear in `count`.
  1229. @par Exception Safety
  1230. Strong guarantee.
  1231. @note
  1232. The range can contain null characters.
  1233. @return `*this`
  1234. @param count The number of characters to copy.
  1235. @param s A pointer to the string to copy from.
  1236. @throw std::length_error `count > max_size()`.
  1237. */
  1238. BHO_STATIC_STRING_CPP14_CONSTEXPR
  1239. basic_static_string&
  1240. assign(
  1241. const_pointer s,
  1242. size_type count);
  1243. /** Assign to the string.
  1244. Replaces the contents with those of
  1245. `{s, s + traits_type::length(s))`.
  1246. @par Complexity
  1247. Linear in `count`.
  1248. @par Exception Safety
  1249. Strong guarantee.
  1250. @return `*this`
  1251. @param s A pointer to the string to copy from.
  1252. @throw std::length_error `traits_type::length(s) > max_size()`.
  1253. */
  1254. BHO_STATIC_STRING_CPP14_CONSTEXPR
  1255. basic_static_string&
  1256. assign(const_pointer s)
  1257. {
  1258. return assign(s, traits_type::length(s));
  1259. }
  1260. /** Assign to the string.
  1261. Replaces the contents with the characters
  1262. in the range `{first, last)`.
  1263. @par Complexity
  1264. Linear in `std::distance(first, last)`.
  1265. @par Exception Safety
  1266. Strong guarantee.
  1267. @tparam InputIterator The type of the iterators.
  1268. @par Constraints
  1269. `InputIterator` satisfies __InputIterator__.
  1270. @return `*this`
  1271. @param first An iterator referring to the
  1272. first character to assign.
  1273. @param last An iterator past the end
  1274. of the range to assign from.
  1275. @throw std::length_error `std::distance(first, last) > max_size()`.
  1276. */
  1277. template<typename InputIterator>
  1278. BHO_STATIC_STRING_CPP14_CONSTEXPR
  1279. #ifdef BHO_STATIC_STRING_DOCS
  1280. basic_static_string&
  1281. #else
  1282. typename std::enable_if<
  1283. detail::is_input_iterator<InputIterator>::value,
  1284. basic_static_string&>::type
  1285. #endif
  1286. assign(
  1287. InputIterator first,
  1288. InputIterator last);
  1289. /** Assign to the string.
  1290. Replaces the contents with those of the
  1291. initializer list `ilist`.
  1292. @par Complexity
  1293. Linear in `init.size()`.
  1294. @par Exception Safety
  1295. Strong guarantee.
  1296. @return `*this`
  1297. @param ilist The initializer list to copy from.
  1298. @throw std::length_error `ilist.size() > max_size()`.
  1299. */
  1300. BHO_STATIC_STRING_CPP14_CONSTEXPR
  1301. basic_static_string&
  1302. assign(
  1303. std::initializer_list<value_type> ilist)
  1304. {
  1305. return assign(ilist.begin(), ilist.end());
  1306. }
  1307. /** Assign to the string.
  1308. Replaces the contents with those of
  1309. `sv`, where `sv` is `string_view_type(t)`.
  1310. @par Complexity
  1311. Linear in `sv.size()`.
  1312. @par Exception Safety
  1313. Strong guarantee.
  1314. @note
  1315. The view can contain null characters.
  1316. @tparam T A type convertible to `string_view_type`.
  1317. @par Constraints
  1318. @code
  1319. std::is_convertible<const T&, string_view>::value &&
  1320. !std::is_convertible<const T&, const CharT*>::value
  1321. @endcode
  1322. @return `*this`
  1323. @param t The object to assign from.
  1324. @throw std::length_error `sv.size() > max_size()`.
  1325. */
  1326. template<typename T
  1327. #ifndef BHO_STATIC_STRING_DOCS
  1328. , typename = detail::enable_if_viewable_t<T, CharT, Traits>
  1329. #endif
  1330. >
  1331. BHO_STATIC_STRING_CPP14_CONSTEXPR
  1332. basic_static_string&
  1333. assign(const T& t)
  1334. {
  1335. detail::common_string_view_type<T, CharT, Traits> sv = t;
  1336. return assign(sv.data(), sv.size());
  1337. }
  1338. /** Assign to the string.
  1339. Replaces the contents with those of the substring `sv`,
  1340. where `sv` is `string_view_type(t).substr(pos, count)`.
  1341. @par Complexity
  1342. Linear in `sv.size()`.
  1343. @par Exception Safety
  1344. Strong guarantee.
  1345. @note
  1346. The view can contain null characters.
  1347. @tparam T A type convertible to `string_view_type`.
  1348. @par Constraints
  1349. @code
  1350. std::is_convertible<const T&, string_view>::value &&
  1351. !std::is_convertible<const T&, const CharT*>::value
  1352. @endcode
  1353. @return `*this`
  1354. @param t The object to assign from.
  1355. @param pos The index at which to begin the substring.
  1356. @param count The size of the substring. The default
  1357. argument for this parameter is @ref npos.
  1358. @throw std::length_error `sv.size() > max_size()`.
  1359. */
  1360. template<typename T
  1361. #ifndef BHO_STATIC_STRING_DOCS
  1362. , typename = detail::enable_if_viewable_t<T, CharT, Traits>
  1363. #endif
  1364. >
  1365. basic_static_string&
  1366. assign(
  1367. const T& t,
  1368. size_type pos,
  1369. size_type count = npos)
  1370. {
  1371. detail::common_string_view_type<T, CharT, Traits> sv = t;
  1372. if( pos > sv.size() )
  1373. detail::throw_exception<std::out_of_range>(
  1374. "pos >= t.size()");
  1375. std::size_t rlen = (std::min)( count, sv.size() - pos );
  1376. return assign(sv.data() + pos, rlen);
  1377. }
  1378. //--------------------------------------------------------------------------
  1379. //
  1380. // Element access
  1381. //
  1382. //--------------------------------------------------------------------------
  1383. /** Access a character with bounds checking.
  1384. Returns a reference to the character at
  1385. index `pos`.
  1386. @par Complexity
  1387. Constant.
  1388. @par Exception Safety
  1389. Strong guarantee.
  1390. @param pos The index to access.
  1391. @throw std::out_of_range `pos >= size()`
  1392. */
  1393. BHO_STATIC_STRING_CPP14_CONSTEXPR
  1394. reference
  1395. at(size_type pos)
  1396. {
  1397. if (pos >= size())
  1398. detail::throw_exception<std::out_of_range>(
  1399. "pos >= size()");
  1400. return data()[pos];
  1401. }
  1402. /** Access a character with bounds checking.
  1403. Returns a reference to the character at
  1404. index `pos`.
  1405. @par Complexity
  1406. Constant.
  1407. @par Exception Safety
  1408. Strong guarantee.
  1409. @param pos The index to access.
  1410. @throw std::out_of_range `pos >= size()`
  1411. */
  1412. BHO_STATIC_STRING_CPP14_CONSTEXPR
  1413. const_reference
  1414. at(size_type pos) const
  1415. {
  1416. if (pos >= size())
  1417. detail::throw_exception<std::out_of_range>(
  1418. "pos >= size()");
  1419. return data()[pos];
  1420. }
  1421. /** Access a character.
  1422. Returns a reference to the character at
  1423. index `pos`.
  1424. @par Complexity
  1425. Constant.
  1426. @par Precondition
  1427. `pos >= size`
  1428. @param pos The index to access.
  1429. */
  1430. BHO_STATIC_STRING_CPP14_CONSTEXPR
  1431. reference
  1432. operator[](size_type pos) noexcept
  1433. {
  1434. return data()[pos];
  1435. }
  1436. /** Access a character.
  1437. Returns a reference to the character at
  1438. index `pos`.
  1439. @par Complexity
  1440. Constant.
  1441. @par Precondition
  1442. `pos >= size`
  1443. @param pos The index to access.
  1444. */
  1445. BHO_STATIC_STRING_CPP14_CONSTEXPR
  1446. const_reference
  1447. operator[](size_type pos) const noexcept
  1448. {
  1449. return data()[pos];
  1450. }
  1451. /** Return the first character.
  1452. Returns a reference to the first character.
  1453. @par Complexity
  1454. Constant.
  1455. @par Precondition
  1456. `not empty()`
  1457. */
  1458. BHO_STATIC_STRING_CPP14_CONSTEXPR
  1459. reference
  1460. front() noexcept
  1461. {
  1462. return data()[0];
  1463. }
  1464. /** Return the first character.
  1465. Returns a reference to the first character.
  1466. @par Complexity
  1467. Constant.
  1468. @par Precondition
  1469. `not empty()`
  1470. */
  1471. BHO_STATIC_STRING_CPP14_CONSTEXPR
  1472. const_reference
  1473. front() const noexcept
  1474. {
  1475. return data()[0];
  1476. }
  1477. /** Return the last character.
  1478. Returns a reference to the last character.
  1479. @par Complexity
  1480. Constant.
  1481. @par Precondition
  1482. `not empty()`
  1483. */
  1484. BHO_STATIC_STRING_CPP14_CONSTEXPR
  1485. reference
  1486. back() noexcept
  1487. {
  1488. return data()[size() - 1];
  1489. }
  1490. /** Return the last character.
  1491. Returns a reference to the last character.
  1492. @par Complexity
  1493. Constant.
  1494. @par Precondition
  1495. `not empty()`
  1496. */
  1497. BHO_STATIC_STRING_CPP14_CONSTEXPR
  1498. const_reference
  1499. back() const noexcept
  1500. {
  1501. return data()[size() - 1];
  1502. }
  1503. /** Return a pointer to the string.
  1504. Returns a pointer to the underlying array
  1505. serving as storage. The value returned is such that
  1506. the range `{data(), data() + size())` is always a
  1507. valid range, even if the container is empty.
  1508. @par Complexity
  1509. Constant.
  1510. @note The value returned from this function
  1511. is never never a null pointer value.
  1512. */
  1513. BHO_STATIC_STRING_CPP14_CONSTEXPR
  1514. pointer
  1515. data() noexcept
  1516. {
  1517. return this->data_impl();
  1518. }
  1519. /** Return a pointer to the string.
  1520. Returns a pointer to the underlying array
  1521. serving as storage. The value returned is such that
  1522. the range `{data(), data() + size())` is always a
  1523. valid range, even if the container is empty.
  1524. @par Complexity
  1525. Constant.
  1526. @note The value returned from this function
  1527. is never never a null pointer value.
  1528. */
  1529. BHO_STATIC_STRING_CPP14_CONSTEXPR
  1530. const_pointer
  1531. data() const noexcept
  1532. {
  1533. return this->data_impl();
  1534. }
  1535. /** Return a pointer to the string.
  1536. Returns a pointer to the underlying array
  1537. serving as storage. The value returned is such that
  1538. the range `{c_str(), c_str() + size())` is always a
  1539. valid range, even if the container is empty.
  1540. @par Complexity
  1541. Constant.
  1542. @note The value returned from this function
  1543. is never never a null pointer value.
  1544. */
  1545. BHO_STATIC_STRING_CPP14_CONSTEXPR
  1546. const_pointer
  1547. c_str() const noexcept
  1548. {
  1549. return data();
  1550. }
  1551. #ifdef BHO_STATIC_STRING_DOCS
  1552. /** Convert to a string view referring to the string.
  1553. Returns a string view referring to the
  1554. underlying character string.
  1555. @par Complexity
  1556. Constant.
  1557. */
  1558. BHO_STATIC_STRING_CPP11_CONSTEXPR
  1559. operator string_view_type() const noexcept
  1560. {
  1561. return string_view_type(data(), size());
  1562. }
  1563. #else
  1564. #ifdef BHO_STATIC_STRING_HAS_STD_STRING_VIEW
  1565. BHO_STATIC_STRING_CPP11_CONSTEXPR
  1566. operator std::basic_string_view<CharT, Traits>() const noexcept
  1567. {
  1568. return std::basic_string_view<CharT, Traits>(data(), size());
  1569. }
  1570. #endif
  1571. #ifndef BHO_STATIC_STRING_STANDALONE
  1572. BHO_STATIC_STRING_CPP11_CONSTEXPR
  1573. operator ::bho::basic_string_view<CharT, Traits>() const noexcept
  1574. {
  1575. return ::bho::basic_string_view<CharT, Traits>(data(), size());
  1576. }
  1577. BHO_STATIC_STRING_CPP11_CONSTEXPR
  1578. operator ::bho::core::basic_string_view<CharT>() const noexcept
  1579. {
  1580. return ::bho::core::basic_string_view<CharT>(data(), size());
  1581. }
  1582. #endif
  1583. #endif
  1584. //--------------------------------------------------------------------------
  1585. //
  1586. // Iterators
  1587. //
  1588. //--------------------------------------------------------------------------
  1589. /// Return an iterator to the beginning.
  1590. BHO_STATIC_STRING_CPP14_CONSTEXPR
  1591. iterator
  1592. begin() noexcept
  1593. {
  1594. return data();
  1595. }
  1596. /// Return an iterator to the beginning.
  1597. BHO_STATIC_STRING_CPP14_CONSTEXPR
  1598. const_iterator
  1599. begin() const noexcept
  1600. {
  1601. return data();
  1602. }
  1603. /// Return an iterator to the beginning.
  1604. BHO_STATIC_STRING_CPP14_CONSTEXPR
  1605. const_iterator
  1606. cbegin() const noexcept
  1607. {
  1608. return data();
  1609. }
  1610. /// Return an iterator to the end.
  1611. BHO_STATIC_STRING_CPP14_CONSTEXPR
  1612. iterator
  1613. end() noexcept
  1614. {
  1615. return data() + size();
  1616. }
  1617. /// Return an iterator to the end.
  1618. BHO_STATIC_STRING_CPP14_CONSTEXPR
  1619. const_iterator
  1620. end() const noexcept
  1621. {
  1622. return data() + size();
  1623. }
  1624. /// Return an iterator to the end.
  1625. BHO_STATIC_STRING_CPP14_CONSTEXPR
  1626. const_iterator
  1627. cend() const noexcept
  1628. {
  1629. return data() + size();
  1630. }
  1631. /// Return a reverse iterator to the beginning.
  1632. BHO_STATIC_STRING_CPP17_CONSTEXPR
  1633. reverse_iterator
  1634. rbegin() noexcept
  1635. {
  1636. return reverse_iterator{end()};
  1637. }
  1638. /// Return a reverse iterator to the beginning.
  1639. BHO_STATIC_STRING_CPP17_CONSTEXPR
  1640. const_reverse_iterator
  1641. rbegin() const noexcept
  1642. {
  1643. return const_reverse_iterator{cend()};
  1644. }
  1645. /// Return a reverse iterator to the beginning.
  1646. BHO_STATIC_STRING_CPP17_CONSTEXPR
  1647. const_reverse_iterator
  1648. crbegin() const noexcept
  1649. {
  1650. return const_reverse_iterator{cend()};
  1651. }
  1652. /// Return a reverse iterator to the end.
  1653. BHO_STATIC_STRING_CPP17_CONSTEXPR
  1654. reverse_iterator
  1655. rend() noexcept
  1656. {
  1657. return reverse_iterator{begin()};
  1658. }
  1659. /// Return a reverse iterator to the end.
  1660. BHO_STATIC_STRING_CPP17_CONSTEXPR
  1661. const_reverse_iterator
  1662. rend() const noexcept
  1663. {
  1664. return const_reverse_iterator{cbegin()};
  1665. }
  1666. /// Return a reverse iterator to the end.
  1667. BHO_STATIC_STRING_CPP17_CONSTEXPR
  1668. const_reverse_iterator
  1669. crend() const noexcept
  1670. {
  1671. return const_reverse_iterator{cbegin()};
  1672. }
  1673. //--------------------------------------------------------------------------
  1674. //
  1675. // Capacity
  1676. //
  1677. //--------------------------------------------------------------------------
  1678. /** Return if the string is empty.
  1679. Returns whether the string contains no characters.
  1680. @par Complexity
  1681. Constant.
  1682. @return `size() == 0`
  1683. */
  1684. BHO_STATIC_STRING_NODISCARD
  1685. BHO_STATIC_STRING_CPP11_CONSTEXPR
  1686. bool
  1687. empty() const noexcept
  1688. {
  1689. return size() == 0;
  1690. }
  1691. /** Return the size of the string.
  1692. Returns the number of characters stored in the
  1693. string, excluding the null terminator.
  1694. @par Complexity
  1695. Constant.
  1696. */
  1697. BHO_STATIC_STRING_CPP11_CONSTEXPR
  1698. size_type
  1699. size() const noexcept
  1700. {
  1701. return this->size_impl();
  1702. }
  1703. /** Return the size of the string.
  1704. Returns the number of characters stored in the
  1705. string, excluding the null terminator.
  1706. @par Complexity
  1707. Constant.
  1708. */
  1709. BHO_STATIC_STRING_CPP11_CONSTEXPR
  1710. size_type
  1711. length() const noexcept
  1712. {
  1713. return size();
  1714. }
  1715. /** Return the number of characters that can be stored.
  1716. Returns the maximum size of the string, excluding the
  1717. null terminator. The returned value is always `N`.
  1718. @par Complexity
  1719. Constant.
  1720. */
  1721. BHO_STATIC_STRING_CPP11_CONSTEXPR
  1722. size_type
  1723. max_size() const noexcept
  1724. {
  1725. return N;
  1726. }
  1727. /** Increase the capacity.
  1728. This function has no effect.
  1729. @throw std::length_error `n > max_size()`
  1730. */
  1731. BHO_STATIC_STRING_CPP14_CONSTEXPR
  1732. void
  1733. reserve(size_type n)
  1734. {
  1735. if (n > max_size())
  1736. detail::throw_exception<std::length_error>(
  1737. "n > max_size()");
  1738. }
  1739. /** Return the number of characters that can be stored.
  1740. Returns the maximum size of the string, excluding the
  1741. null terminator. The returned value is always `N`.
  1742. @par Complexity
  1743. Constant.
  1744. */
  1745. BHO_STATIC_STRING_CPP11_CONSTEXPR
  1746. size_type
  1747. capacity() const noexcept
  1748. {
  1749. return max_size();
  1750. }
  1751. /** Request the removal of unused capacity.
  1752. This function has no effect.
  1753. */
  1754. BHO_STATIC_STRING_CPP14_CONSTEXPR
  1755. void
  1756. shrink_to_fit() noexcept { }
  1757. //--------------------------------------------------------------------------
  1758. //
  1759. // Operations
  1760. //
  1761. //--------------------------------------------------------------------------
  1762. /** Clear the contents.
  1763. Erases all characters from the string. After this
  1764. call, @ref size() returns zero.
  1765. @par Complexity
  1766. Linear in @ref size().
  1767. @note All references, pointers, or iterators
  1768. referring to contained elements are invalidated. Any
  1769. past-the-end iterators are also invalidated.
  1770. */
  1771. BHO_STATIC_STRING_CPP14_CONSTEXPR
  1772. void
  1773. clear() noexcept
  1774. {
  1775. this->set_size(0);
  1776. term();
  1777. }
  1778. /** Insert into the string.
  1779. Inserts `count` copies of `ch` at the position `index`.
  1780. @par Exception Safety
  1781. Strong guarantee.
  1782. @note All references, pointers, or iterators
  1783. referring to contained elements are invalidated. Any
  1784. past-the-end iterators are also invalidated.
  1785. @return `*this`
  1786. @param index The index to insert at.
  1787. @param count The number of characters to insert.
  1788. @param ch The character to insert.
  1789. @throw std::length_error `size() + count > max_size()`
  1790. @throw std::out_of_range `index > size()`
  1791. */
  1792. BHO_STATIC_STRING_CPP14_CONSTEXPR
  1793. basic_static_string&
  1794. insert(
  1795. size_type index,
  1796. size_type count,
  1797. value_type ch)
  1798. {
  1799. if (index > size())
  1800. detail::throw_exception<std::out_of_range>(
  1801. "index > size()");
  1802. insert(begin() + index, count, ch);
  1803. return *this;
  1804. }
  1805. /** Insert into the string.
  1806. Inserts the null-terminated character string pointed to by `s`
  1807. of length `count` at the position `index` where `count`
  1808. is `traits_type::length(s)`.
  1809. @par Exception Safety
  1810. Strong guarantee.
  1811. @note All references, pointers, or iterators
  1812. referring to contained elements are invalidated. Any
  1813. past-the-end iterators are also invalidated.
  1814. @return `*this`
  1815. @param index The index to insert at.
  1816. @param s The string to insert.
  1817. @throw std::length_error `size() + count > max_size()`
  1818. @throw std::out_of_range `index > size()`
  1819. */
  1820. BHO_STATIC_STRING_CPP14_CONSTEXPR
  1821. basic_static_string&
  1822. insert(
  1823. size_type index,
  1824. const_pointer s)
  1825. {
  1826. return insert(index, s, traits_type::length(s));
  1827. }
  1828. /** Insert into the string.
  1829. Inserts `count` characters of the string pointed to by `s`
  1830. at the position `index`.
  1831. @par Exception Safety
  1832. Strong guarantee.
  1833. @note All references, pointers, or iterators
  1834. referring to contained elements are invalidated. Any
  1835. past-the-end iterators are also invalidated.
  1836. @return `*this`
  1837. @param index The index to insert at.
  1838. @param s The string to insert.
  1839. @param count The length of the string to insert.
  1840. @throw std::length_error `size() + count > max_size()`
  1841. @throw std::out_of_range `index > size()`
  1842. */
  1843. BHO_STATIC_STRING_CPP14_CONSTEXPR
  1844. basic_static_string&
  1845. insert(
  1846. size_type index,
  1847. const_pointer s,
  1848. size_type count)
  1849. {
  1850. if (index > size())
  1851. detail::throw_exception<std::out_of_range>(
  1852. "index > size()");
  1853. insert(data() + index, s, s + count);
  1854. return *this;
  1855. }
  1856. /** Insert into the string.
  1857. Inserts the string `str`
  1858. at the position `index`.
  1859. @par Exception Safety
  1860. Strong guarantee.
  1861. @note The insertion is done unchecked when
  1862. the capacity of `str` differs from that of the
  1863. string the function is called on.
  1864. @note All references, pointers, or iterators
  1865. referring to contained elements are invalidated. Any
  1866. past-the-end iterators are also invalidated.
  1867. @tparam M The size of the input string.
  1868. @return `*this`
  1869. @param index The index to insert at.
  1870. @param str The string to insert.
  1871. @throw std::length_error `size() + str.size() > max_size()`
  1872. @throw std::out_of_range `index > size()`
  1873. */
  1874. template<std::size_t M>
  1875. BHO_STATIC_STRING_CPP14_CONSTEXPR
  1876. basic_static_string&
  1877. insert(
  1878. size_type index,
  1879. const basic_static_string<M, CharT, Traits>& str)
  1880. {
  1881. return insert_unchecked(index, str.data(), str.size());
  1882. }
  1883. #ifndef BHO_STATIC_STRING_DOCS
  1884. BHO_STATIC_STRING_CPP14_CONSTEXPR
  1885. basic_static_string&
  1886. insert(
  1887. size_type index,
  1888. const basic_static_string& str)
  1889. {
  1890. return insert(index, str.data(), str.size());
  1891. }
  1892. #endif
  1893. /** Insert into the string.
  1894. Inserts a string, obtained by `str.substr(index_str, count)`
  1895. at the position `index`.
  1896. @par Exception Safety
  1897. Strong guarantee.
  1898. @note The insertion is done unchecked when
  1899. the capacity of `str` differs from that of the
  1900. string the function is called on.
  1901. @note All references, pointers, or iterators
  1902. referring to contained elements are invalidated. Any
  1903. past-the-end iterators are also invalidated.
  1904. @tparam M The size of the input string.
  1905. @return `*this`
  1906. @param index The index to insert at.
  1907. @param str The string from which to insert.
  1908. @param index_str The index in `str` to start inserting from.
  1909. @param count The number of characters to insert.
  1910. The default argument for this parameter is @ref npos.
  1911. @throw std::length_error `size() + str.substr(index_str, count).size() > max_size()`
  1912. @throw std::out_of_range `index > size()`
  1913. @throw std::out_of_range `index_str > str.size()`
  1914. */
  1915. template<std::size_t M>
  1916. BHO_STATIC_STRING_CPP14_CONSTEXPR
  1917. basic_static_string&
  1918. insert(
  1919. size_type index,
  1920. const basic_static_string<M, CharT, Traits>& str,
  1921. size_type index_str,
  1922. size_type count = npos)
  1923. {
  1924. return insert_unchecked(index, str.data() + index_str, str.capped_length(index_str, count));
  1925. }
  1926. #ifndef BHO_STATIC_STRING_DOCS
  1927. BHO_STATIC_STRING_CPP14_CONSTEXPR
  1928. basic_static_string&
  1929. insert(
  1930. size_type index,
  1931. const basic_static_string& str,
  1932. size_type index_str,
  1933. size_type count = npos)
  1934. {
  1935. return insert(index, str.data() + index_str, str.capped_length(index_str, count));
  1936. }
  1937. #endif
  1938. /** Insert into the string.
  1939. Inserts the character `ch` before the character pointed by `pos`.
  1940. @par Precondition
  1941. `pos` shall be vaild within `{data(), data() + size()}`
  1942. @par Exception Safety
  1943. Strong guarantee.
  1944. @note All references, pointers, or iterators
  1945. referring to contained elements are invalidated. Any
  1946. past-the-end iterators are also invalidated.
  1947. @return An iterator which refers to the first inserted character
  1948. or `pos` if no characters were inserted
  1949. @param pos The index to insert at.
  1950. @param ch The character to insert.
  1951. @throw std::length_error `size() + 1 > max_size()`
  1952. */
  1953. BHO_STATIC_STRING_CPP14_CONSTEXPR
  1954. iterator
  1955. insert(
  1956. const_iterator pos,
  1957. value_type ch)
  1958. {
  1959. return insert(pos, 1, ch);
  1960. }
  1961. /** Insert into the string.
  1962. Inserts `count` copies of `ch` before the character pointed by `pos`.
  1963. @par Precondition
  1964. `pos` shall be valid within `{data(), data() + size()}`
  1965. @par Exception Safety
  1966. Strong guarantee.
  1967. @note All references, pointers, or iterators
  1968. referring to contained elements are invalidated. Any
  1969. past-the-end iterators are also invalidated.
  1970. @return An iterator which refers to the first inserted character
  1971. or `pos` if no characters were inserted
  1972. @param pos The position to insert at.
  1973. @param count The number of characters to insert.
  1974. @param ch The character to insert.
  1975. @throw std::length_error `size() + count > max_size()`
  1976. */
  1977. BHO_STATIC_STRING_CPP14_CONSTEXPR
  1978. iterator
  1979. insert(
  1980. const_iterator pos,
  1981. size_type count,
  1982. value_type ch);
  1983. /** Insert into the string.
  1984. Inserts characters from the range `{first, last)` before the
  1985. character pointed to by `pos`.
  1986. @par Precondition
  1987. `pos` shall be valid within `{data(), data() + size()}`,
  1988. `{first, last)` shall be a valid range
  1989. @par Exception Safety
  1990. Strong guarantee.
  1991. @note All references, pointers, or iterators
  1992. referring to contained elements are invalidated. Any
  1993. past-the-end iterators are also invalidated.
  1994. @tparam InputIterator The type of the iterators.
  1995. @par Constraints
  1996. `InputIterator` satisfies __InputIterator__ and does not
  1997. satisfy __ForwardIterator__.
  1998. @return An iterator which refers to the first inserted character
  1999. or `pos` if no characters were inserted
  2000. @param pos The position to insert at.
  2001. @param first An iterator representing the first character to insert.
  2002. @param last An iterator representing one past the last character to insert.
  2003. @throw std::length_error `size() + insert_count > max_size()`
  2004. */
  2005. template<typename InputIterator>
  2006. BHO_STATIC_STRING_CPP14_CONSTEXPR
  2007. #ifdef BHO_STATIC_STRING_DOCS
  2008. iterator
  2009. #else
  2010. typename std::enable_if<
  2011. detail::is_input_iterator<
  2012. InputIterator>::value &&
  2013. !detail::is_forward_iterator<
  2014. InputIterator>::value, iterator>::type
  2015. #endif
  2016. insert(
  2017. const_iterator pos,
  2018. InputIterator first,
  2019. InputIterator last);
  2020. #ifndef BHO_STATIC_STRING_DOCS
  2021. template<typename ForwardIterator>
  2022. BHO_STATIC_STRING_CPP14_CONSTEXPR
  2023. typename std::enable_if<
  2024. detail::is_forward_iterator<
  2025. ForwardIterator>::value,
  2026. iterator>::type
  2027. insert(
  2028. const_iterator pos,
  2029. ForwardIterator first,
  2030. ForwardIterator last);
  2031. #endif
  2032. /** Insert into the string.
  2033. Inserts characters from `ilist` before `pos`.
  2034. @par Precondition
  2035. `pos` shall be valid within `{data(), data() + size()}`
  2036. @par Exception Safety
  2037. Strong guarantee.
  2038. @note All references, pointers, or iterators
  2039. referring to contained elements are invalidated. Any
  2040. past-the-end iterators are also invalidated.
  2041. @return An iterator which refers to the first inserted character
  2042. or `pos` if no characters were inserted
  2043. @param pos The position to insert at.
  2044. @param ilist The initializer list from which to insert.
  2045. @throw std::length_error `size() + ilist.size() > max_size()`
  2046. */
  2047. BHO_STATIC_STRING_CPP14_CONSTEXPR
  2048. iterator
  2049. insert(
  2050. const_iterator pos,
  2051. std::initializer_list<value_type> ilist)
  2052. {
  2053. return insert_unchecked(pos, ilist.begin(), ilist.size());
  2054. }
  2055. /** Insert into the string.
  2056. Constructs a temporary `string_view_type` object `sv` from `t` and
  2057. inserts `{sv.begin(), sv.end())` at `index`.
  2058. @par Precondition
  2059. `index` shall be valid within `{data(), data() + size()}`
  2060. @par Exception Safety
  2061. Strong guarantee.
  2062. @note All references, pointers, or iterators
  2063. referring to contained elements are invalidated. Any
  2064. past-the-end iterators are also invalidated.
  2065. @return `*this`
  2066. @tparam T The type of the object to convert.
  2067. @par Constraints
  2068. `std::is_convertible<const T&, string_view>::value &&
  2069. !std::is_convertible<const T&, const CharT*>::value`.
  2070. @param index The index to insert at.
  2071. @param t The string to insert from.
  2072. @throw std::length_error `size() + sv.size() > max_size()`
  2073. @throw std::out_of_range `index > size()`
  2074. */
  2075. template<typename T
  2076. #ifndef BHO_STATIC_STRING_DOCS
  2077. , typename = detail::enable_if_viewable_t<T, CharT, Traits>
  2078. #endif
  2079. >
  2080. BHO_STATIC_STRING_CPP14_CONSTEXPR
  2081. basic_static_string&
  2082. insert(
  2083. size_type index,
  2084. const T& t)
  2085. {
  2086. detail::common_string_view_type<T, CharT, Traits> sv = t;
  2087. return insert(index, sv.data(), sv.size());
  2088. }
  2089. /** Insert into the string.
  2090. Constructs a temporary `string_view_type` object `sv` from `t`
  2091. and inserts `sv.substr(index_str, count)` at `index`.
  2092. @par Exception Safety
  2093. Strong guarantee.
  2094. @note All references, pointers, or iterators
  2095. referring to contained elements are invalidated. Any
  2096. past-the-end iterators are also invalidated.
  2097. @tparam T The type of the object to convert.
  2098. @par Constraints
  2099. `std::is_convertible<const T&, string_view>::value &&
  2100. !std::is_convertible<const T&, const_pointer>::value`.
  2101. @return `*this`
  2102. @param index The index to insert at.
  2103. @param t The string to insert from.
  2104. @param index_str The index in the temporary `string_view_type` object
  2105. to start the substring from.
  2106. @param count The number of characters to insert.
  2107. @throw std::length_error `size() + sv.size() > max_size()`
  2108. @throw std::out_of_range `index > size()`
  2109. @throw std::out_of_range `index_str > sv.size()`
  2110. */
  2111. template<typename T
  2112. #ifndef BHO_STATIC_STRING_DOCS
  2113. , typename = detail::enable_if_viewable_t<T, CharT, Traits>
  2114. #endif
  2115. >
  2116. BHO_STATIC_STRING_CPP14_CONSTEXPR
  2117. basic_static_string&
  2118. insert(
  2119. size_type index,
  2120. const T& t,
  2121. size_type index_str,
  2122. size_type count = npos)
  2123. {
  2124. detail::common_string_view_type<T, CharT, Traits> sv(t);
  2125. if ( index_str > sv.size() )
  2126. detail::throw_exception<std::out_of_range>("index_str > t.size()");
  2127. return insert(index, sv.data() + index_str, (std::min)(sv.size() - index_str, count));
  2128. }
  2129. /** Erase from the string.
  2130. Erases `num` characters from the string, starting at `index`.
  2131. `num` is determined as the smaller of `count` and `size() - index`.
  2132. @par Exception Safety
  2133. Strong guarantee.
  2134. @note All references, pointers, or iterators
  2135. referring to contained elements are invalidated. Any
  2136. past-the-end iterators are also invalidated.
  2137. @return `*this`
  2138. @param index The index to erase at.
  2139. The default argument for this parameter is `0`.
  2140. @param count The number of characters to erase.
  2141. The default argument for this parameter is @ref npos.
  2142. @throw std::out_of_range `index > size()`
  2143. */
  2144. BHO_STATIC_STRING_CPP14_CONSTEXPR
  2145. basic_static_string&
  2146. erase(
  2147. size_type index = 0,
  2148. size_type count = npos)
  2149. {
  2150. erase(data() + index, data() + index + capped_length(index, count));
  2151. return *this;
  2152. }
  2153. /** Erase from the string.
  2154. Erases the character at `pos`.
  2155. @par Preconditions
  2156. `pos` shall be valid within `{data(), data() + size()}`
  2157. @par Exception Safety
  2158. Strong guarantee.
  2159. @note All references, pointers, or iterators
  2160. referring to contained elements are invalidated. Any
  2161. past-the-end iterators are also invalidated.
  2162. @return An iterator referring to character immediately following
  2163. the erased character, or @ref end() if one does not exist.
  2164. @param pos An iterator referring to the character to erase.
  2165. */
  2166. BHO_STATIC_STRING_CPP14_CONSTEXPR
  2167. iterator
  2168. erase(const_iterator pos)
  2169. {
  2170. BHO_STATIC_STRING_ASSERT(!empty());
  2171. return erase(pos, pos + 1);
  2172. }
  2173. /** Erase from the string.
  2174. Erases the characters in the range `{first, last)`.
  2175. @par Precondition
  2176. `{first, last}` shall be valid within `{data(), data() + size()}`
  2177. @par Exception Safety
  2178. Strong guarantee.
  2179. @note All references, pointers, or iterators
  2180. referring to contained elements are invalidated. Any
  2181. past-the-end iterators are also invalidated.
  2182. @return An iterator referring to the character `last`
  2183. previously referred to, or @ref end() if one does not exist.
  2184. @param first An iterator referring to the first character to erase.
  2185. @param last An iterator past the last character to erase.
  2186. */
  2187. BHO_STATIC_STRING_CPP14_CONSTEXPR
  2188. iterator
  2189. erase(
  2190. const_iterator first,
  2191. const_iterator last);
  2192. /** Append a character.
  2193. Appends a character to the end of the string.
  2194. @par Exception Safety
  2195. Strong guarantee.
  2196. @param ch The character to append.
  2197. @throw std::length_error `size() >= max_size()`
  2198. */
  2199. BHO_STATIC_STRING_CPP14_CONSTEXPR
  2200. void
  2201. push_back(value_type ch);
  2202. /** Remove the last character.
  2203. Removes a character from the end of the string.
  2204. @par Precondition
  2205. `not empty()`
  2206. */
  2207. BHO_STATIC_STRING_CPP14_CONSTEXPR
  2208. void
  2209. pop_back() noexcept
  2210. {
  2211. BHO_STATIC_STRING_ASSERT(!empty());
  2212. this->set_size(size() - 1);
  2213. term();
  2214. }
  2215. /** Append to the string.
  2216. Appends `count` copies of `ch` to the end of the string.
  2217. @par Exception Safety
  2218. Strong guarantee.
  2219. @return `*this`
  2220. @param count The number of characters to append.
  2221. @param ch The character to append.
  2222. @throw std::length_error `size() + count > max_size()`
  2223. */
  2224. BHO_STATIC_STRING_CPP14_CONSTEXPR
  2225. basic_static_string&
  2226. append(
  2227. size_type count,
  2228. value_type ch);
  2229. /** Append to the string.
  2230. Appends `s` to the end of the string.
  2231. @par Exception Safety
  2232. Strong guarantee.
  2233. @tparam M The size of the string to append.
  2234. @return `*this`
  2235. @param s The string to append.
  2236. @throw std::length_error `size() + s.size() > max_size()`
  2237. */
  2238. template<std::size_t M>
  2239. BHO_STATIC_STRING_CPP14_CONSTEXPR
  2240. basic_static_string&
  2241. append(
  2242. const basic_static_string<M, CharT, Traits>& s)
  2243. {
  2244. return append(s.data(), s.size());
  2245. }
  2246. /** Append to the string.
  2247. Appends the substring `sub` to the end of the string,
  2248. where `sub` is `s.substr(pos, count)`.
  2249. @par Exception Safety
  2250. Strong guarantee.
  2251. @tparam M The size of the string to append.
  2252. @return `*this`
  2253. @param s The string to append.
  2254. @param pos The index at which to begin the substring.
  2255. @param count The size of the substring. The default
  2256. argument for this parameter is @ref npos.
  2257. @throw std::length_error `size() + sub.size() > max_size()`
  2258. @throw std::out_of_range `pos > s.size()`
  2259. */
  2260. template<std::size_t M>
  2261. BHO_STATIC_STRING_CPP14_CONSTEXPR
  2262. basic_static_string&
  2263. append(
  2264. const basic_static_string<M, CharT, Traits>& s,
  2265. size_type pos,
  2266. size_type count = npos)
  2267. {
  2268. return append(s.data() + pos, s.capped_length(pos, count));
  2269. }
  2270. /** Append to the string.
  2271. Appends `count` characters from the string pointed
  2272. to by `s` to the end of the string.
  2273. @par Exception Safety
  2274. Strong guarantee.
  2275. @note The string can contain null characters.
  2276. @return `*this`
  2277. @param s The string to append.
  2278. @param count The number of characters to append.
  2279. @throw std::length_error `size() + count > max_size()`
  2280. */
  2281. BHO_STATIC_STRING_CPP14_CONSTEXPR
  2282. basic_static_string&
  2283. append(
  2284. const_pointer s,
  2285. size_type count);
  2286. /** Append to the string.
  2287. Appends `count` characters from the string pointed
  2288. to by `s` to the end of the string, where `count`
  2289. is `traits_type::length(s)`.
  2290. @par Exception Safety
  2291. Strong guarantee.
  2292. @return `*this`
  2293. @param s The string to append.
  2294. @throw std::length_error `size() + count > max_size()`
  2295. */
  2296. BHO_STATIC_STRING_CPP14_CONSTEXPR
  2297. basic_static_string&
  2298. append(const_pointer s)
  2299. {
  2300. return append(s, traits_type::length(s));
  2301. }
  2302. // KRYSTIAN TODO: change exception safety
  2303. /** Append to the string.
  2304. Appends characters from the range `{first, last)`
  2305. to the end of the string.
  2306. @par Precondition
  2307. `{first, last)` shall be a valid range
  2308. @par Exception Safety
  2309. Strong guarantee.
  2310. @tparam InputIterator The type of the iterators.
  2311. @par Constraints
  2312. `InputIterator` satisfies __InputIterator__.
  2313. @return `*this`
  2314. @param first An iterator referring to the
  2315. first character to append.
  2316. @param last An iterator past the end of
  2317. last character to append.
  2318. @throw std::length_error `size() + std::distance(first, last) > max_size()`
  2319. */
  2320. template<typename InputIterator>
  2321. BHO_STATIC_STRING_CPP14_CONSTEXPR
  2322. #ifdef BHO_STATIC_STRING_DOCS
  2323. basic_static_string&
  2324. #else
  2325. typename std::enable_if<
  2326. detail::is_input_iterator<InputIterator>::value,
  2327. basic_static_string&>::type
  2328. #endif
  2329. append(
  2330. InputIterator first,
  2331. InputIterator last)
  2332. {
  2333. this->set_size(size() + read_back(true, first, last));
  2334. return term();
  2335. }
  2336. /** Append to the string.
  2337. Appends the characters from `ilist` to the
  2338. end of the string.
  2339. @par Exception Safety
  2340. Strong guarantee.
  2341. @return `*this`
  2342. @param ilist The initializer list to append.
  2343. @throw std::length_error `size() + ilist.size() > max_size()`
  2344. */
  2345. BHO_STATIC_STRING_CPP14_CONSTEXPR
  2346. basic_static_string&
  2347. append(
  2348. std::initializer_list<value_type> ilist)
  2349. {
  2350. return append(ilist.begin(), ilist.size());
  2351. }
  2352. /** Append to the string.
  2353. Appends `sv` to the end of the string,
  2354. where `sv` is `string_view_type(t)`.
  2355. @par Exception Safety
  2356. Strong guarantee.
  2357. @tparam T The type of the object to convert.
  2358. @par Constraints
  2359. @code
  2360. std::is_convertible<T const&, string_view>::value &&
  2361. !std::is_convertible<T const&, char const*>::value
  2362. @endcode
  2363. @return `*this`
  2364. @param t The string to append.
  2365. @throw std::length_error `size() + sv.size() > max_size()`
  2366. */
  2367. template<typename T
  2368. #ifndef BHO_STATIC_STRING_DOCS
  2369. , typename = detail::enable_if_viewable_t<T, CharT, Traits>
  2370. #endif
  2371. >
  2372. BHO_STATIC_STRING_CPP14_CONSTEXPR
  2373. basic_static_string&
  2374. append(const T& t)
  2375. {
  2376. detail::common_string_view_type<T, CharT, Traits> sv = t;
  2377. return append(sv.data(), sv.size());
  2378. }
  2379. /** Append to the string.
  2380. Appends the substring `sv` to the end of the string,
  2381. where `sv` is `string_view_type(t).substr(pos, count)`.
  2382. @par Exception Safety
  2383. Strong guarantee.
  2384. @tparam T The type of the object to convert.
  2385. @par Constraints
  2386. @code
  2387. std::is_convertible<T const&, string_view>::value &&
  2388. !std::is_convertible<T const&, char const*>::value
  2389. @endcode
  2390. @return `*this`
  2391. @param t The object to append.
  2392. @param pos The index at which to begin the substring.
  2393. @param count The size of the substring. The default
  2394. argument for this parameter is @ref npos.
  2395. @throw std::length_error `size() + sv.size() > max_size()`
  2396. */
  2397. template<typename T
  2398. #ifndef BHO_STATIC_STRING_DOCS
  2399. , typename = detail::enable_if_viewable_t<T, CharT, Traits>
  2400. #endif
  2401. >
  2402. BHO_STATIC_STRING_CPP14_CONSTEXPR
  2403. basic_static_string&
  2404. append(
  2405. const T& t,
  2406. size_type pos,
  2407. size_type count = npos)
  2408. {
  2409. detail::common_string_view_type<T, CharT, Traits> sv = t;
  2410. if ( pos > sv.size() )
  2411. detail::throw_exception<std::out_of_range>("pos > t.size()");
  2412. return append(sv.data() + pos, (std::min)(sv.size() - pos, count));
  2413. }
  2414. /** Append to the string.
  2415. Appends `s` to the end of the string.
  2416. @par Exception Safety
  2417. Strong guarantee.
  2418. @tparam M The size of the string to append.
  2419. @return `*this`
  2420. @param s The string to append.
  2421. @throw std::length_error `size() + s.size() > max_size()`
  2422. */
  2423. template<std::size_t M>
  2424. BHO_STATIC_STRING_CPP14_CONSTEXPR
  2425. basic_static_string&
  2426. operator+=(
  2427. const basic_static_string<M, CharT, Traits>& s)
  2428. {
  2429. return append(s);
  2430. }
  2431. /** Append to the string.
  2432. Appends a character to the end of the string.
  2433. @par Exception Safety
  2434. Strong guarantee.
  2435. @param ch The character to append.
  2436. @throw std::length_error `size() >= max_size()`
  2437. */
  2438. BHO_STATIC_STRING_CPP14_CONSTEXPR
  2439. basic_static_string&
  2440. operator+=(value_type ch)
  2441. {
  2442. push_back(ch);
  2443. return *this;
  2444. }
  2445. /** Append to the string.
  2446. Appends `count` characters from the string pointed
  2447. to by `s` to the end of the string, where `count`
  2448. is `traits_type::length(s)`.
  2449. @par Exception Safety
  2450. Strong guarantee.
  2451. @return `*this`
  2452. @param s The string to append.
  2453. @throw std::length_error `size() + count > max_size()`
  2454. */
  2455. BHO_STATIC_STRING_CPP14_CONSTEXPR
  2456. basic_static_string&
  2457. operator+=(const_pointer s)
  2458. {
  2459. return append(s);
  2460. }
  2461. /** Append to the string.
  2462. Appends the characters from `ilist` to the
  2463. end of the string.
  2464. @par Exception Safety
  2465. Strong guarantee.
  2466. @return `*this`
  2467. @param ilist The initializer list to append.
  2468. @throw std::length_error `size() + ilist.size() > max_size()`
  2469. */
  2470. BHO_STATIC_STRING_CPP14_CONSTEXPR
  2471. basic_static_string&
  2472. operator+=(
  2473. std::initializer_list<value_type> ilist)
  2474. {
  2475. return append(ilist);
  2476. }
  2477. /** Append to the string.
  2478. Appends `sv` to the end of the string,
  2479. where `sv` is `string_view_type(t)`.
  2480. @par Exception Safety
  2481. Strong guarantee.
  2482. @tparam T The type of the object to convert.
  2483. @par Constraints
  2484. @code
  2485. std::is_convertible<T const&, string_view>::value &&
  2486. !std::is_convertible<T const&, char const*>::value
  2487. @endcode
  2488. @return `*this`
  2489. @param t The string to append.
  2490. @throw std::length_error `size() + sv.size() > max_size()`
  2491. */
  2492. template<typename T
  2493. #ifndef BHO_STATIC_STRING_DOCS
  2494. , typename = detail::enable_if_viewable_t<T, CharT, Traits>
  2495. #endif
  2496. >
  2497. BHO_STATIC_STRING_CPP14_CONSTEXPR
  2498. basic_static_string&
  2499. operator+=(const T& t)
  2500. {
  2501. return append(t);
  2502. }
  2503. /** Compare a string with the string.
  2504. Let `comp` be `traits_type::compare(data(), s.data(), std::min(size(), s.size())`.
  2505. If `comp != 0`, then the result is `comp`. Otherwise, the result is
  2506. `0` if `size() == s.size()`, `-1` if `size() < s.size()`, and `1`
  2507. otherwise.
  2508. @par Complexity
  2509. Linear.
  2510. @return The result of lexicographically comparing `s` and the string.
  2511. @tparam M The size of the string to compare with.
  2512. @param s The string to compare.
  2513. */
  2514. template<std::size_t M>
  2515. BHO_STATIC_STRING_CPP14_CONSTEXPR
  2516. int
  2517. compare(
  2518. const basic_static_string<M, CharT, Traits>& s) const noexcept
  2519. {
  2520. return detail::lexicographical_compare<CharT, Traits>(
  2521. data(), size(), s.data(), s.size());
  2522. }
  2523. /** Compare a string with the string.
  2524. Let `sub` be `substr(pos1, count1)` and `comp` be
  2525. `traits_type::compare(sub.data(), s.data(), std::min(sub.size(), s.size())`.
  2526. If `comp != 0`, then the result is `comp`. Otherwise, the result is
  2527. `0` if `sub.size() == s.size()`, `-1` if `sub.size() < s.size()`, and `1`
  2528. otherwise.
  2529. @par Complexity
  2530. Linear.
  2531. @par Exception Safety
  2532. Strong guarantee.
  2533. @return The result of lexicographically comparing `sub` and `s`.
  2534. @tparam M The size of the string to compare with.
  2535. @param pos1 The index at which to begin the substring.
  2536. @param count1 The size of the substring.
  2537. @param s The string to compare.
  2538. @throw std::out_of_range `pos1 > size()`
  2539. */
  2540. template<std::size_t M>
  2541. BHO_STATIC_STRING_CPP14_CONSTEXPR
  2542. int
  2543. compare(
  2544. size_type pos1,
  2545. size_type count1,
  2546. const basic_static_string<M, CharT, Traits>& s) const
  2547. {
  2548. return detail::lexicographical_compare<CharT, Traits>(
  2549. data() + pos1, capped_length(pos1, count1), s.data(), s.size());
  2550. }
  2551. /** Compare a string with the string.
  2552. Let `sub1` be `substr(pos1, count1)`, `sub2` be
  2553. `s.substr(pos2, count2)`, and `comp` be
  2554. `traits_type::compare(sub1.data(), sub2.data(), std::min(sub1.size(), sub2.size())`.
  2555. If `comp != 0`, then the result is `comp`. Otherwise, the result is
  2556. `0` if `sub1.size() == sub2.size()`, `-1` if `sub1.size() < sub2.size()`, and `1`
  2557. otherwise.
  2558. @par Complexity
  2559. Linear.
  2560. @par Exception Safety
  2561. Strong guarantee.
  2562. @return The result of lexicographically comparing `sub1` and `sub2`.
  2563. @param pos1 The index at which to begin the substring.
  2564. @param count1 The size of the substring.
  2565. @param s The string to compare.
  2566. @param pos2 The index at which to begin the substring to compare.
  2567. @param count2 The size of the substring to compare.
  2568. @throw std::out_of_range `pos1 > size()`
  2569. @throw std::out_of_range `pos2 > s.size()`
  2570. */
  2571. template<std::size_t M>
  2572. BHO_STATIC_STRING_CPP14_CONSTEXPR
  2573. int
  2574. compare(
  2575. size_type pos1,
  2576. size_type count1,
  2577. const basic_static_string<M, CharT, Traits>& s,
  2578. size_type pos2,
  2579. size_type count2 = npos) const
  2580. {
  2581. return detail::lexicographical_compare<CharT, Traits>(
  2582. data() + pos1, capped_length(pos1, count1),
  2583. s.data() + pos2, s.capped_length(pos2, count2));
  2584. }
  2585. /** Compare a string with the string.
  2586. Let `len` be `traits_type::length(s)` and `comp` be
  2587. `traits_type::compare(data(), s, std::min(size(), len)`.
  2588. If `comp != 0`, then the result is `comp`. Otherwise, the result is
  2589. `0` if `size() == len`, `-1` if `size() < len`, and `1`
  2590. otherwise.
  2591. @par Complexity
  2592. Linear.
  2593. @return The result of lexicographically comparing `s` and the string.
  2594. @param s The string to compare.
  2595. */
  2596. BHO_STATIC_STRING_CPP14_CONSTEXPR
  2597. int
  2598. compare(const_pointer s) const noexcept
  2599. {
  2600. return detail::lexicographical_compare<CharT, Traits>(
  2601. data(), size(), s, traits_type::length(s));
  2602. }
  2603. /** Compare a string with the string.
  2604. Let `sub` be `substr(pos1, count1)`, `len` be
  2605. `traits_type::length(s)`, and `comp` be
  2606. `traits_type::compare(sub.data(), s, std::min(size(), len)`.
  2607. If `comp != 0`, then the result is `comp`. Otherwise, the result is
  2608. `0` if `sub.size() == len`, `-1` if `sub.size() < len`, and `1`
  2609. otherwise.
  2610. @par Complexity
  2611. Linear.
  2612. @par Exception Safety
  2613. Strong guarantee.
  2614. @return The result of lexicographically comparing `s` and `sub`.
  2615. @param pos1 The index at which to begin the substring.
  2616. @param count1 The size of the substring.
  2617. @param s The string to compare.
  2618. @throw std::out_of_range `pos1 > size()`
  2619. */
  2620. BHO_STATIC_STRING_CPP14_CONSTEXPR
  2621. int
  2622. compare(
  2623. size_type pos1,
  2624. size_type count1,
  2625. const_pointer s) const
  2626. {
  2627. return detail::lexicographical_compare<CharT, Traits>(
  2628. data() + pos1, capped_length(pos1, count1), s, traits_type::length(s));
  2629. }
  2630. /** Compare a string with the string.
  2631. Let `sub` be `substr(pos1, count1)`, and `comp` be
  2632. `traits_type::compare(sub.data(), s, std::min(size(), count2)`.
  2633. If `comp != 0`, then the result is `comp`. Otherwise, the result is
  2634. `0` if `sub.size() == count2`, `-1` if `sub.size() < count2`, and `1`
  2635. otherwise.
  2636. @par Complexity
  2637. Linear.
  2638. @par Exception Safety
  2639. Strong guarantee.
  2640. @return The result of lexicographically comparing `s` and `sub`.
  2641. @param pos1 The index at which to begin the substring.
  2642. @param count1 The size of the substring.
  2643. @param s The string to compare.
  2644. @param count2 The length of the string to compare.
  2645. @throw std::out_of_range `pos1 > size()`
  2646. */
  2647. BHO_STATIC_STRING_CPP14_CONSTEXPR
  2648. int
  2649. compare(
  2650. size_type pos1,
  2651. size_type count1,
  2652. const_pointer s,
  2653. size_type count2) const
  2654. {
  2655. return detail::lexicographical_compare<CharT, Traits>(
  2656. data() + pos1, capped_length(pos1, count1), s, count2);
  2657. }
  2658. /** Compare a string with the string.
  2659. Let `s` be `string_view_type(t)` and `comp` be
  2660. `traits_type::compare(data(), s.data(), std::min(size(), s.size())`.
  2661. If `comp != 0`, then the result is `comp`. Otherwise, the result is
  2662. `0` if `size() == s.size()`, `-1` if `size() < s.size()`, and `1`
  2663. otherwise.
  2664. @par Complexity
  2665. Linear.
  2666. @par Exception Safety
  2667. Strong guarantee.
  2668. @tparam T The type of the object to convert.
  2669. @par Constraints
  2670. @code
  2671. std::is_convertible<const T&, string_view>::value &&
  2672. !std::is_convertible<const T&, const_pointer>::value.
  2673. @endcode
  2674. @return The result of lexicographically comparing `s` and the string.
  2675. @param t The string to compare.
  2676. */
  2677. template<typename T
  2678. #ifndef BHO_STATIC_STRING_DOCS
  2679. , typename = detail::enable_if_viewable_t<T, CharT, Traits>
  2680. #endif
  2681. >
  2682. BHO_STATIC_STRING_CPP14_CONSTEXPR
  2683. int
  2684. compare(const T& t) const noexcept
  2685. {
  2686. detail::common_string_view_type<T, CharT, Traits> sv = t;
  2687. return detail::lexicographical_compare<CharT, Traits>(
  2688. data(), size(), sv.data(), sv.size());
  2689. }
  2690. /** Compare a string with the string.
  2691. Let `s` be `string_view_type(t)`, `sub` be
  2692. `substr(pos1, count1)`, and `comp` be
  2693. `traits_type::compare(sub.data(), s.data(), std::min(sub.size(), s.size())`.
  2694. If `comp != 0`, then the result is `comp`. Otherwise, the result is
  2695. `0` if `sub.size() == s.size()`, `-1` if `sub.size() < s.size()`, and `1`
  2696. otherwise.
  2697. @par Complexity
  2698. Linear.
  2699. @par Exception Safety
  2700. Strong guarantee.
  2701. @tparam T The type of the object to convert.
  2702. @par Constraints
  2703. @code
  2704. std::is_convertible<const T&, string_view>::value &&
  2705. !std::is_convertible<const T&, const_pointer>::value.
  2706. @endcode
  2707. @return The result of lexicographically comparing `s` and `sub`.
  2708. @param pos1 The index at which to begin the substring.
  2709. @param count1 The length of the substring.
  2710. @param t The string to compare.
  2711. */
  2712. template<typename T
  2713. #ifndef BHO_STATIC_STRING_DOCS
  2714. , typename = detail::enable_if_viewable_t<T, CharT, Traits>
  2715. #endif
  2716. >
  2717. BHO_STATIC_STRING_CPP14_CONSTEXPR
  2718. int
  2719. compare(
  2720. size_type pos1,
  2721. size_type count1,
  2722. const T& t) const
  2723. {
  2724. detail::common_string_view_type<T, CharT, Traits> sv = t;
  2725. return detail::lexicographical_compare<CharT, Traits>(
  2726. data() + pos1, capped_length(pos1, count1), sv.data(), sv.size());
  2727. }
  2728. /** Compare a string with the string.
  2729. Let `sub1` be `substr(pos1, count1)`, `sub2` be
  2730. `string_view_type(t).substr(pos2, count2)`, and `comp` be
  2731. `traits_type::compare(sub1.data(), sub2.data(), std::min(sub1.size(), sub2.size())`.
  2732. If `comp != 0`, then the result is `comp`. Otherwise, the result is
  2733. `0` if `sub1.size() == sub2.size()`, `-1` if `sub1.size() < sub2.size()`, and `1`
  2734. otherwise.
  2735. @par Complexity
  2736. Linear.
  2737. @par Exception Safety
  2738. Strong guarantee.
  2739. @tparam T The type of the object to convert.
  2740. @par Constraints
  2741. @code
  2742. std::is_convertible<const T&, string_view>::value &&
  2743. !std::is_convertible<const T&, const_pointer>::value.
  2744. @endcode
  2745. @return The result of lexicographically comparing `sub1` and `sub2`.
  2746. @param pos1 The index at which to begin the substring in the string.
  2747. @param count1 The length of the substring in the string.
  2748. @param t The string to compare.
  2749. @param pos2 The index at which to begin the substring in the string view.
  2750. @param count2 The length of the substring in the string view.
  2751. */
  2752. template<typename T
  2753. #ifndef BHO_STATIC_STRING_DOCS
  2754. , typename = detail::enable_if_viewable_t<T, CharT, Traits>
  2755. #endif
  2756. >
  2757. BHO_STATIC_STRING_CPP14_CONSTEXPR
  2758. int
  2759. compare(
  2760. size_type pos1,
  2761. size_type count1,
  2762. const T& t,
  2763. size_type pos2,
  2764. size_type count2 = npos) const
  2765. {
  2766. detail::common_string_view_type<T, CharT, Traits> sv = t;
  2767. if ( pos2 > sv.size())
  2768. detail::throw_exception<std::out_of_range>("pos2 > sv.size()");
  2769. return compare(
  2770. pos1, count1, sv.data() + pos2,
  2771. (std::min)(sv.size() - pos2, count2));
  2772. }
  2773. /** Return a substring.
  2774. Returns a substring of the string.
  2775. @par Exception Safety
  2776. Strong guarantee.
  2777. @return A string object containing the characters
  2778. `{data() + pos, std::min(count, size() - pos))`.
  2779. @param pos The index to being the substring at. The
  2780. default arugment for this parameter is `0`.
  2781. @param count The length of the substring. The default arugment
  2782. for this parameter is @ref npos.
  2783. @throw std::out_of_range `pos > size()`
  2784. */
  2785. #ifndef BHO_STATIC_STRING_GCC5_BAD_CONSTEXPR
  2786. BHO_STATIC_STRING_CPP14_CONSTEXPR
  2787. #endif
  2788. basic_static_string
  2789. substr(
  2790. size_type pos = 0,
  2791. size_type count = npos) const
  2792. {
  2793. return basic_static_string(
  2794. data() + pos, capped_length(pos, count));
  2795. }
  2796. #ifdef BHO_STATIC_STRING_HAS_ANY_STRING_VIEW
  2797. /** Return a string view of a substring.
  2798. Returns a view of a substring.
  2799. @par Exception Safety
  2800. Strong guarantee.
  2801. @return A `string_view_type` object referring
  2802. to `{data() + pos, std::min(count, size() - pos))`.
  2803. @param pos The index to being the substring at. The
  2804. default arugment for this parameter is `0`.
  2805. @param count The length of the substring. The default arugment
  2806. for this parameter is @ref npos.
  2807. @throw std::out_of_range `pos > size()`
  2808. */
  2809. BHO_STATIC_STRING_CPP14_CONSTEXPR
  2810. string_view_type
  2811. subview(
  2812. size_type pos = 0,
  2813. size_type count = npos) const
  2814. {
  2815. return string_view_type(
  2816. data() + pos, capped_length(pos, count));
  2817. }
  2818. #endif
  2819. /** Copy a substring to another string.
  2820. Copies `std::min(count, size() - pos)` characters starting at
  2821. index `pos` to the string pointed to by `dest`.
  2822. @note The resulting string is not null terminated.
  2823. @return The number of characters copied.
  2824. @param count The number of characters to copy.
  2825. @param dest The string to copy to.
  2826. @param pos The index to begin copying from. The
  2827. default argument for this parameter is `0`.
  2828. @throw std::out_of_range `pos > max_size()`
  2829. */
  2830. BHO_STATIC_STRING_CPP14_CONSTEXPR
  2831. size_type
  2832. copy(
  2833. pointer dest,
  2834. size_type count,
  2835. size_type pos = 0) const
  2836. {
  2837. const auto num_copied = capped_length(pos, count);
  2838. traits_type::copy(dest, data() + pos, num_copied);
  2839. return num_copied;
  2840. }
  2841. /** Change the size of the string.
  2842. Resizes the string to contain `n` characters. If
  2843. `n > size()`, characters with the value `CharT()` are
  2844. appended. Otherwise, `size()` is reduced to `n`.
  2845. @param n The size to resize the string to.
  2846. @throw std::out_of_range `n > max_size()`
  2847. */
  2848. BHO_STATIC_STRING_CPP14_CONSTEXPR
  2849. void
  2850. resize(size_type n)
  2851. {
  2852. resize(n, value_type());
  2853. }
  2854. /** Change the size of the string.
  2855. Resizes the string to contain `n` characters. If
  2856. `n > size()`, copies of `c` are
  2857. appended. Otherwise, `size()` is reduced to `n`.
  2858. @param n The size to resize the string to.
  2859. @param c The characters to append if the size
  2860. increases.
  2861. @throw std::out_of_range `n > max_size()`
  2862. */
  2863. BHO_STATIC_STRING_CPP14_CONSTEXPR
  2864. void
  2865. resize(
  2866. size_type n,
  2867. value_type c);
  2868. /** Swap two strings.
  2869. Swaps the contents of the string and `s`.
  2870. @par Exception Safety
  2871. Strong guarantee.
  2872. @note
  2873. All references, pointers, or iterators
  2874. referring to contained elements are invalidated. Any
  2875. past-the-end iterators are also invalidated.
  2876. @param s The string to swap with.
  2877. */
  2878. BHO_STATIC_STRING_CPP14_CONSTEXPR
  2879. void
  2880. swap(basic_static_string& s) noexcept;
  2881. /** Swap two strings.
  2882. Swaps the contents of the string and `s`.
  2883. @par Exception Safety
  2884. Strong guarantee.
  2885. @note
  2886. All references, pointers, or iterators
  2887. referring to contained elements are invalidated. Any
  2888. past-the-end iterators are also invalidated.
  2889. @tparam M The size of the string to swap with.
  2890. @param s The string to swap with.
  2891. @throw std::length_error `s.size() > max_size() || size() > s.max_size()`
  2892. */
  2893. template<std::size_t M>
  2894. BHO_STATIC_STRING_CPP14_CONSTEXPR
  2895. void
  2896. swap(basic_static_string<M, CharT, Traits>& s);
  2897. /** Replace a part of the string.
  2898. Replaces `rcount` characters starting at index `pos1` with those
  2899. of `str`, where `rcount` is `std::min(n1, size() - pos1)`.
  2900. @par Exception Safety
  2901. Strong guarantee.
  2902. @note The replacement is done unchecked when
  2903. the capacity of `str` differs from that of the
  2904. string the function is called on.
  2905. All references, pointers, or iterators
  2906. referring to contained elements are invalidated. Any
  2907. past-the-end iterators are also invalidated.
  2908. @tparam M The size of the input string.
  2909. @return `*this`
  2910. @param pos1 The index to replace at.
  2911. @param n1 The number of characters to replace.
  2912. @param str The string to replace with.
  2913. @throw std::length_error `size() + (str.size() - rcount) > max_size()`
  2914. @throw std::out_of_range `pos1 > size()`
  2915. */
  2916. template<size_t M>
  2917. BHO_STATIC_STRING_CPP14_CONSTEXPR
  2918. basic_static_string&
  2919. replace(
  2920. size_type pos1,
  2921. size_type n1,
  2922. const basic_static_string<M, CharT, Traits>& str)
  2923. {
  2924. return replace_unchecked(pos1, n1, str.data(), str.size());
  2925. }
  2926. #ifndef BHO_STATIC_STRING_DOCS
  2927. BHO_STATIC_STRING_CPP14_CONSTEXPR
  2928. basic_static_string&
  2929. replace(
  2930. size_type pos1,
  2931. size_type n1,
  2932. const basic_static_string& str)
  2933. {
  2934. return replace(pos1, n1, str.data(), str.size());
  2935. }
  2936. #endif
  2937. /** Replace a part of the string.
  2938. Replaces `rcount` characters starting at index `pos1` with those of
  2939. `str.subview(pos2, n2)`, where `rcount` is `std::min(n1, size() - pos1)`.
  2940. @par Exception Safety
  2941. Strong guarantee.
  2942. @note The replacement is done unchecked when
  2943. the capacity of `str` differs from that of the
  2944. string the function is called on.
  2945. All references, pointers, or iterators
  2946. referring to contained elements are invalidated. Any
  2947. past-the-end iterators are also invalidated.
  2948. @return `*this`
  2949. @param pos1 The index to replace at.
  2950. @param n1 The number of characters to replace.
  2951. @param str The string to replace with.
  2952. @param pos2 The index to begin the substring.
  2953. @param n2 The length of the substring.
  2954. The default argument for this parameter is @ref npos.
  2955. @throw std::length_error `size() + (std::min(str.size(), n2) - rcount) > max_size()`
  2956. @throw std::out_of_range `pos1 > size()`
  2957. @throw std::out_of_range `pos2 > str.size()`
  2958. */
  2959. template<std::size_t M>
  2960. BHO_STATIC_STRING_CPP14_CONSTEXPR
  2961. basic_static_string&
  2962. replace(
  2963. size_type pos1,
  2964. size_type n1,
  2965. const basic_static_string<M, CharT, Traits>& str,
  2966. size_type pos2,
  2967. size_type n2 = npos)
  2968. {
  2969. return replace_unchecked(pos1, n1, str.data() + pos2, str.capped_length(pos2, n2));
  2970. }
  2971. #ifndef BHO_STATIC_STRING_DOCS
  2972. BHO_STATIC_STRING_CPP14_CONSTEXPR
  2973. basic_static_string&
  2974. replace(
  2975. size_type pos1,
  2976. size_type n1,
  2977. const basic_static_string& str,
  2978. size_type pos2,
  2979. size_type n2 = npos)
  2980. {
  2981. return replace(pos1, n1, str.data() + pos2, str.capped_length(pos2, n2));
  2982. }
  2983. #endif
  2984. /** Replace a part of the string.
  2985. Constructs a temporary `string_view_type` object `sv` from `t`, and
  2986. replaces `rcount` characters starting at index `pos1` with those
  2987. of `sv`, where `rcount` is `std::min(n1, size() - pos1)`.
  2988. @par Exception Safety
  2989. Strong guarantee.
  2990. @note All references, pointers, or iterators
  2991. referring to contained elements are invalidated. Any
  2992. past-the-end iterators are also invalidated.
  2993. @tparam T The type of the object to convert.
  2994. @par Constraints
  2995. `std::is_convertible<const T&, string_view>::value &&
  2996. !std::is_convertible<const T&, const CharT*>::value`.
  2997. @return `*this`
  2998. @param pos1 The index to replace at.
  2999. @param n1 The number of characters to replace.
  3000. @param t The object to replace with.
  3001. @throw std::length_error `size() + (sv.size() - rcount) > max_size()`
  3002. @throw std::out_of_range `pos1 > size()`
  3003. */
  3004. template<typename T
  3005. #ifndef BHO_STATIC_STRING_DOCS
  3006. , typename = detail::enable_if_viewable_t<T, CharT, Traits>
  3007. #endif
  3008. >
  3009. BHO_STATIC_STRING_CPP14_CONSTEXPR
  3010. basic_static_string&
  3011. replace(
  3012. size_type pos1,
  3013. size_type n1,
  3014. const T& t)
  3015. {
  3016. detail::common_string_view_type<T, CharT, Traits> sv = t;
  3017. return replace(pos1, n1, sv.data(), sv.size());
  3018. }
  3019. /** Replace a part of the string.
  3020. Constructs a temporary `string_view_type` object `sv` from `t`, and
  3021. replaces `rcount` characters starting at index `pos1` with those
  3022. of `sv.substr(pos2, n2)`, where `rcount` is `std::min(n1, size() - pos)`.
  3023. @par Exception Safety
  3024. Strong guarantee.
  3025. @note All references, pointers, or iterators
  3026. referring to contained elements are invalidated. Any
  3027. past-the-end iterators are also invalidated.
  3028. @tparam T The type of the object to convert.
  3029. @par Constraints
  3030. `std::is_convertible<const T&, string_view>::value &&
  3031. !std::is_convertible<const T&, const CharT*>::value`.
  3032. @return `*this`
  3033. @param pos1 The index to replace at.
  3034. @param n1 The number of characters to replace.
  3035. @param t The object to replace with.
  3036. @param pos2 The index to begin the substring.
  3037. @param n2 The length of the substring.
  3038. The default argument for this parameter is @ref npos.
  3039. @throw std::length_error `size() + (std::min(n2, sv.size()) - rcount) > max_size()`
  3040. @throw std::out_of_range `pos1 > size()`
  3041. @throw std::out_of_range `pos2 > sv.size()`
  3042. */
  3043. template<typename T
  3044. #ifndef BHO_STATIC_STRING_DOCS
  3045. , typename = detail::enable_if_viewable_t<T, CharT, Traits>
  3046. #endif
  3047. >
  3048. BHO_STATIC_STRING_CPP14_CONSTEXPR
  3049. basic_static_string&
  3050. replace(
  3051. size_type pos1,
  3052. size_type n1,
  3053. const T& t,
  3054. size_type pos2,
  3055. size_type n2 = npos)
  3056. {
  3057. detail::common_string_view_type<T, CharT, Traits> sv = t;
  3058. if ( pos2 > sv.size())
  3059. detail::throw_exception<std::out_of_range>("pos2 > t.size()");
  3060. return replace(
  3061. pos1, n1, sv.data() + pos2,
  3062. (std::min)(sv.size() - pos2, n2));
  3063. }
  3064. /** Replace a part of the string.
  3065. Replaces `rcount` characters starting at index `pos` with those of
  3066. `{s, s + n2)`, where `rcount` is `std::min(n1, size() - pos)`.
  3067. @par Exception Safety
  3068. Strong guarantee.
  3069. @note All references, pointers, or iterators
  3070. referring to contained elements are invalidated. Any
  3071. past-the-end iterators are also invalidated.
  3072. @return `*this`
  3073. @param pos The index to replace at.
  3074. @param n1 The number of characters to replace.
  3075. @param s The string to replace with.
  3076. @param n2 The length of the string to replace with.
  3077. @throw std::length_error `size() + (n2 - rcount) > max_size()`
  3078. @throw std::out_of_range `pos > size()`
  3079. */
  3080. BHO_STATIC_STRING_CPP14_CONSTEXPR
  3081. basic_static_string&
  3082. replace(
  3083. size_type pos,
  3084. size_type n1,
  3085. const_pointer s,
  3086. size_type n2)
  3087. {
  3088. return replace(data() + pos, data() + pos + capped_length(pos, n1), s, n2);
  3089. }
  3090. /** Replace a part of the string.
  3091. Replaces `rcount` characters starting at index `pos` with those of
  3092. `{s, s + len)`, where the length of the string `len` is `traits_type::length(s)` and `rcount`
  3093. is `std::min(n1, size() - pos)`.
  3094. @par Exception Safety
  3095. Strong guarantee.
  3096. @note All references, pointers, or iterators
  3097. referring to contained elements are invalidated. Any
  3098. past-the-end iterators are also invalidated.
  3099. @return `*this`
  3100. @param pos The index to replace at.
  3101. @param n1 The number of characters to replace.
  3102. @param s The string to replace with.
  3103. @throw std::length_error `size() + (len - rcount) > max_size()`
  3104. @throw std::out_of_range `pos > size()`
  3105. */
  3106. BHO_STATIC_STRING_CPP14_CONSTEXPR
  3107. basic_static_string&
  3108. replace(
  3109. size_type pos,
  3110. size_type n1,
  3111. const_pointer s)
  3112. {
  3113. return replace(pos, n1, s, traits_type::length(s));
  3114. }
  3115. /** Replace a part of the string.
  3116. Replaces `rcount` characters starting at index `pos` with `n2` copies
  3117. of `c`, where `rcount` is `std::min(n1, size() - pos)`.
  3118. @par Exception Safety
  3119. Strong guarantee.
  3120. @note All references, pointers, or iterators
  3121. referring to contained elements are invalidated. Any
  3122. past-the-end iterators are also invalidated.
  3123. @return `*this`
  3124. @param pos The index to replace at.
  3125. @param n1 The number of characters to replace.
  3126. @param n2 The number of characters to replace with.
  3127. @param c The character to replace with.
  3128. @throw std::length_error `size() + (n2 - rcount) > max_size()`
  3129. @throw std::out_of_range `pos > size()`
  3130. */
  3131. BHO_STATIC_STRING_CPP14_CONSTEXPR
  3132. basic_static_string&
  3133. replace(
  3134. size_type pos,
  3135. size_type n1,
  3136. size_type n2,
  3137. value_type c)
  3138. {
  3139. return replace(data() + pos, data() + pos + capped_length(pos, n1), n2, c);
  3140. }
  3141. /** Replace a part of the string.
  3142. Replaces the characters in the range `{i1, i2)`
  3143. with those of `str`.
  3144. @par Precondition
  3145. `{i1, i2)` is a valid range.
  3146. @par Exception Safety
  3147. Strong guarantee.
  3148. @note The replacement is done unchecked when
  3149. the capacity of `str` differs from that of the
  3150. string the function is called on.
  3151. All references, pointers, or iterators
  3152. referring to contained elements are invalidated. Any
  3153. past-the-end iterators are also invalidated.
  3154. @tparam M The size of the input string.
  3155. @return `*this`
  3156. @param i1 An iterator referring to the first character to replace.
  3157. @param i2 An iterator referring past the end of
  3158. the last character to replace.
  3159. @param str The string to replace with.
  3160. @throw std::length_error `size() + (str.size() - std::distance(i1, i2)) > max_size()`
  3161. */
  3162. template<std::size_t M>
  3163. BHO_STATIC_STRING_CPP14_CONSTEXPR
  3164. basic_static_string&
  3165. replace(
  3166. const_iterator i1,
  3167. const_iterator i2,
  3168. const basic_static_string<M, CharT, Traits>& str)
  3169. {
  3170. return replace_unchecked(i1, i2, str.data(), str.size());
  3171. }
  3172. #ifndef BHO_STATIC_STRING_DOCS
  3173. BHO_STATIC_STRING_CPP14_CONSTEXPR
  3174. basic_static_string&
  3175. replace(
  3176. const_iterator i1,
  3177. const_iterator i2,
  3178. const basic_static_string& str)
  3179. {
  3180. return replace(i1, i2, str.data(), str.size());
  3181. }
  3182. #endif
  3183. /** Replace a part of the string.
  3184. Constructs a temporary `string_view_type` object `sv` from `t`, and
  3185. replaces the characters in the range `{i1, i2)` with those
  3186. of `sv`.
  3187. @par Precondition
  3188. `{i1, i2)` is a valid range.
  3189. @par Exception Safety
  3190. Strong guarantee.
  3191. @note All references, pointers, or iterators
  3192. referring to contained elements are invalidated. Any
  3193. past-the-end iterators are also invalidated.
  3194. @tparam T The type of the object to convert.
  3195. @par Constraints
  3196. `std::is_convertible<const T&, string_view>::value &&
  3197. !std::is_convertible<const T&, const CharT*>::value`.
  3198. @return `*this`
  3199. @param i1 An iterator referring to the first character to replace.
  3200. @param i2 An iterator referring past the end of
  3201. the last character to replace.
  3202. @param t The object to replace with.
  3203. @throw std::length_error `size() + (sv.size() - std::distance(i1, i2)) > max_size()`
  3204. */
  3205. template<typename T
  3206. #ifndef BHO_STATIC_STRING_DOCS
  3207. , typename = detail::enable_if_viewable_t<T, CharT, Traits>
  3208. #endif
  3209. >
  3210. BHO_STATIC_STRING_CPP14_CONSTEXPR
  3211. basic_static_string&
  3212. replace(
  3213. const_iterator i1,
  3214. const_iterator i2,
  3215. const T& t)
  3216. {
  3217. detail::common_string_view_type<T, CharT, Traits> sv = t;
  3218. return replace(i1, i2, sv.data(), sv.data() + sv.size());
  3219. }
  3220. /** Replace a part of the string.
  3221. Replaces the characters in the range `{i1, i2)` with those of
  3222. `{s, s + n)`.
  3223. @par Precondition
  3224. `{i1, i2)` is a valid range.
  3225. @par Exception Safety
  3226. Strong guarantee.
  3227. @note All references, pointers, or iterators
  3228. referring to contained elements are invalidated. Any
  3229. past-the-end iterators are also invalidated.
  3230. @return `*this`
  3231. @param i1 An iterator referring to the first character to replace.
  3232. @param i2 An iterator referring past the end of
  3233. the last character to replace.
  3234. @param s The string to replace with.
  3235. @param n The length of the string to replace with.
  3236. @throw std::length_error `size() + (n - std::distance(i1, i2)) > max_size()`
  3237. */
  3238. BHO_STATIC_STRING_CPP14_CONSTEXPR
  3239. basic_static_string&
  3240. replace(
  3241. const_iterator i1,
  3242. const_iterator i2,
  3243. const_pointer s,
  3244. size_type n)
  3245. {
  3246. return replace(i1, i2, s, s + n);
  3247. }
  3248. /** Replace a part of the string.
  3249. Replaces the characters in the range `{i1, i2)` with those of
  3250. `{s, s + len)`, where the length of the string `len` is `traits_type::length(s)`.
  3251. @par Precondition
  3252. `{i1, i2)` shall be a valid range.
  3253. @par Exception Safety
  3254. Strong guarantee.
  3255. @note All references, pointers, or iterators
  3256. referring to contained elements are invalidated. Any
  3257. past-the-end iterators are also invalidated.
  3258. @return `*this`
  3259. @param i1 An iterator referring to the first character to replace.
  3260. @param i2 An iterator referring past the end of
  3261. the last character to replace.
  3262. @param s The string to replace with.
  3263. @throw std::length_error `size() + (len - std::distance(i1, i2)) > max_size()`
  3264. */
  3265. BHO_STATIC_STRING_CPP14_CONSTEXPR
  3266. basic_static_string&
  3267. replace(
  3268. const_iterator i1,
  3269. const_iterator i2,
  3270. const_pointer s)
  3271. {
  3272. return replace(i1, i2, s, traits_type::length(s));
  3273. }
  3274. /** Replace a part of the string.
  3275. Replaces the characters in the range `{i1, i2)` with
  3276. `n` copies of `c`.
  3277. @par Precondition
  3278. `{i1, i2)` is a valid range.
  3279. @par Exception Safety
  3280. Strong guarantee.
  3281. @note All references, pointers, or iterators
  3282. referring to contained elements are invalidated. Any
  3283. past-the-end iterators are also invalidated.
  3284. @return `*this`
  3285. @param i1 An iterator referring to the first character to replace.
  3286. @param i2 An iterator past the end of
  3287. the last character to replace.
  3288. @param n The number of characters to replace with.
  3289. @param c The character to replace with.
  3290. @throw std::length_error `size() + (n - std::distance(i1, i2)) > max_size()`
  3291. */
  3292. BHO_STATIC_STRING_CPP14_CONSTEXPR
  3293. basic_static_string&
  3294. replace(
  3295. const_iterator i1,
  3296. const_iterator i2,
  3297. size_type n,
  3298. value_type c);
  3299. /** Replace a part of the string.
  3300. Replaces the characters in the range `{i1, i2)`
  3301. with those of `{j1, j2)`.
  3302. @par Precondition
  3303. `{i1, i2)` is a valid range.
  3304. `{j1, j2)` is a valid range.
  3305. @par Exception Safety
  3306. Strong guarantee.
  3307. @note All references, pointers, or iterators
  3308. referring to contained elements are invalidated. Any
  3309. past-the-end iterators are also invalidated.
  3310. @tparam InputIterator The type of the iterators.
  3311. @par Constraints
  3312. `InputIterator` satisfies __InputIterator__ and does not
  3313. satisfy __ForwardIterator__.
  3314. @return `*this`
  3315. @param i1 An iterator referring to the first character to replace.
  3316. @param i2 An iterator referring past the end of
  3317. the last character to replace.
  3318. @param j1 An iterator referring to the first character to replace with.
  3319. @param j2 An iterator referring past the end of
  3320. the last character to replace with.
  3321. @throw std::length_error `size() + (inserted - std::distance(i1, i2)) > max_size()`
  3322. */
  3323. template<typename InputIterator>
  3324. BHO_STATIC_STRING_CPP14_CONSTEXPR
  3325. #ifdef BHO_STATIC_STRING_DOCS
  3326. basic_static_string&
  3327. #else
  3328. typename std::enable_if<
  3329. detail::is_input_iterator<
  3330. InputIterator>::value &&
  3331. !detail::is_forward_iterator<
  3332. InputIterator>::value,
  3333. basic_static_string<N, CharT, Traits>&>::type
  3334. #endif
  3335. replace(
  3336. const_iterator i1,
  3337. const_iterator i2,
  3338. InputIterator j1,
  3339. InputIterator j2);
  3340. #ifndef BHO_STATIC_STRING_DOCS
  3341. template<typename ForwardIterator>
  3342. BHO_STATIC_STRING_CPP14_CONSTEXPR
  3343. typename std::enable_if<
  3344. detail::is_forward_iterator<
  3345. ForwardIterator>::value,
  3346. basic_static_string<N, CharT, Traits>&>::type
  3347. replace(
  3348. const_iterator i1,
  3349. const_iterator i2,
  3350. ForwardIterator j1,
  3351. ForwardIterator j2);
  3352. #endif
  3353. /** Replace a part of the string.
  3354. Replaces the characters in the range `{i1, i2)`
  3355. with those of contained in the initializer list `il`.
  3356. @par Precondition
  3357. `{i1, i2)` is a valid range.
  3358. @par Exception Safety
  3359. Strong guarantee.
  3360. @note All references, pointers, or iterators
  3361. referring to contained elements are invalidated. Any
  3362. past-the-end iterators are also invalidated.
  3363. @return `*this`
  3364. @param i1 An iterator referring to the first character to replace.
  3365. @param i2 An iterator past the end of
  3366. the last character to replace.
  3367. @param il The initializer list to replace with.
  3368. @throw std::length_error `size() + (il.size() - std::distance(i1, i2)) > max_size()`
  3369. */
  3370. BHO_STATIC_STRING_CPP14_CONSTEXPR
  3371. basic_static_string&
  3372. replace(
  3373. const_iterator i1,
  3374. const_iterator i2,
  3375. std::initializer_list<value_type> il)
  3376. {
  3377. return replace_unchecked(i1, i2, il.begin(), il.size());
  3378. }
  3379. //--------------------------------------------------------------------------
  3380. //
  3381. // Search
  3382. //
  3383. //--------------------------------------------------------------------------
  3384. /** Find the first occurrence of a string within the string.
  3385. Constructs a temporary `string_view_type` object `sv` from `t`, and finds
  3386. the first occurrence of `sv` within the string starting at the index `pos`.
  3387. @par Complexity
  3388. Linear.
  3389. @note An empty string is always found.
  3390. @tparam T The type of the object to convert.
  3391. @par Constraints
  3392. `std::is_convertible<const T&, string_view>::value &&
  3393. !std::is_convertible<const T&, const CharT*>::value`.
  3394. @return The lowest index `idx` greater than or equal to `pos`
  3395. where each element of `{sv.begin(), sv.end())` is equal to
  3396. that of `{begin() + idx, begin() + idx + count)` if one exists,
  3397. and @ref npos otherwise.
  3398. @param t The string to search for.
  3399. @param pos The index to start searching at. The default argument
  3400. for this parameter is `0`.
  3401. */
  3402. template<typename T
  3403. #ifndef BHO_STATIC_STRING_DOCS
  3404. , typename = detail::enable_if_viewable_t<T, CharT, Traits>
  3405. #endif
  3406. >
  3407. BHO_STATIC_STRING_CPP14_CONSTEXPR
  3408. size_type
  3409. find(
  3410. const T& t,
  3411. size_type pos = 0) const
  3412. #ifdef BHO_STATIC_STRING_DOCS
  3413. noexcept(detail::is_nothrow_convertible<const T&, string_view_type>::value)
  3414. #else
  3415. noexcept(detail::is_nothrow_convertible<const T&, detail::common_string_view_type<T, CharT, Traits>>::value)
  3416. #endif
  3417. {
  3418. detail::common_string_view_type<T, CharT, Traits> sv = t;
  3419. return find(sv.data(), pos, sv.size());
  3420. }
  3421. /** Find the first occurrence of a string within the string.
  3422. Finds the first occurrence of `str` within the
  3423. string starting at the index `pos`.
  3424. @par Complexity
  3425. Linear.
  3426. @return The lowest index `idx` greater than or equal to `pos`
  3427. where each element of `str` is equal to that of
  3428. `{begin() + idx, begin() + idx + str.size())`
  3429. if one exists, and @ref npos otherwise.
  3430. @param str The string to search for.
  3431. @param pos The index to start searching at. The default argument for
  3432. this parameter is `0`.
  3433. */
  3434. template<std::size_t M>
  3435. BHO_STATIC_STRING_CPP14_CONSTEXPR
  3436. size_type
  3437. find(
  3438. const basic_static_string<M, CharT, Traits>& str,
  3439. size_type pos = 0) const noexcept
  3440. {
  3441. return find(str.data(), pos, str.size());
  3442. }
  3443. /** Find the first occurrence of a string within the string.
  3444. Finds the first occurrence of the string pointed to
  3445. by `s` within the string starting at the index `pos`.
  3446. @par Complexity
  3447. Linear.
  3448. @note An empty string is always found.
  3449. @return The lowest index `idx` greater than or equal to `pos`
  3450. where each element of `{s, s + n)` is equal to that of
  3451. `{begin() + idx, begin() + idx + n)` if one exists,
  3452. and @ref npos otherwise.
  3453. @param s The string to search for.
  3454. @param pos The index to start searching at.
  3455. @param n The length of the string to search for.
  3456. */
  3457. BHO_STATIC_STRING_CPP14_CONSTEXPR
  3458. size_type
  3459. find(
  3460. const_pointer s,
  3461. size_type pos,
  3462. size_type n) const noexcept;
  3463. /** Find the first occurrence of a string within the string.
  3464. Finds the first occurrence of the string pointed to by `s`
  3465. of length `count` within the string starting at the index `pos`,
  3466. where `count` is `traits_type::length(s)`.
  3467. @par Complexity
  3468. Linear.
  3469. @note An empty string is always found.
  3470. @return The lowest index `idx` greater than or equal to `pos`
  3471. where each element of `{s, s + count)` is equal to that of
  3472. `{begin() + idx, begin() + idx + count)` if one exists,
  3473. and @ref npos otherwise.
  3474. @param s The string to search for.
  3475. @param pos The index to start searching at. The default argument
  3476. for this parameter is `0`.
  3477. */
  3478. BHO_STATIC_STRING_CPP14_CONSTEXPR
  3479. size_type
  3480. find(
  3481. const_pointer s,
  3482. size_type pos = 0) const noexcept
  3483. {
  3484. return find(s, pos, traits_type::length(s));
  3485. }
  3486. /** Find the first occurrence of a character within the string.
  3487. Finds the first occurrence of `c` within the string
  3488. starting at the index `pos`.
  3489. @par Complexity
  3490. Linear.
  3491. @return The index corrosponding to the first occurrence of `c` within
  3492. `{begin() + pos, end())` if it exists, and @ref npos otherwise.
  3493. @param c The character to search for.
  3494. @param pos The index to start searching at. The default argument
  3495. for this parameter is `0`.
  3496. */
  3497. BHO_STATIC_STRING_CPP14_CONSTEXPR
  3498. size_type
  3499. find(
  3500. value_type c,
  3501. size_type pos = 0) const noexcept
  3502. {
  3503. return find(&c, pos, 1);
  3504. }
  3505. /** Find the last occurrence of a string within the string.
  3506. Constructs a temporary `string_view_type` object `sv` from `t`, and finds
  3507. the last occurrence of `sv` within the string starting before or at
  3508. the index `pos`.
  3509. @par Complexity
  3510. Linear.
  3511. @tparam T The type of the object to convert.
  3512. @par Constraints
  3513. `std::is_convertible<const T&, string_view>::value &&
  3514. !std::is_convertible<const T&, const CharT*>::value`.
  3515. @return The highest index `idx` less than or equal to `pos`
  3516. where each element of `{sv.begin(), sv.end())` is equal to
  3517. that of `{begin() + idx, begin() + idx + count)` if one exists,
  3518. and @ref npos otherwise.
  3519. @param t The string to search for.
  3520. @param pos The index to start searching at. The default argument
  3521. for this parameter is @ref npos.
  3522. */
  3523. template<typename T
  3524. #ifndef BHO_STATIC_STRING_DOCS
  3525. , typename = detail::enable_if_viewable_t<T, CharT, Traits>
  3526. #endif
  3527. >
  3528. BHO_STATIC_STRING_CPP14_CONSTEXPR
  3529. size_type
  3530. rfind(
  3531. const T& t,
  3532. size_type pos = npos) const
  3533. #ifdef BHO_STATIC_STRING_DOCS
  3534. noexcept(detail::is_nothrow_convertible<const T&, string_view_type>::value)
  3535. #else
  3536. noexcept(detail::is_nothrow_convertible<const T&, detail::common_string_view_type<T, CharT, Traits>>::value)
  3537. #endif
  3538. {
  3539. detail::common_string_view_type<T, CharT, Traits> sv = t;
  3540. return rfind(sv.data(), pos, sv.size());
  3541. }
  3542. /** Find the last occurrence of a string within the string.
  3543. Finds the last occurrence of `str` within the string
  3544. starting before or at the index `pos`.
  3545. @par Complexity
  3546. Linear.
  3547. @return The highest index `idx` less than or equal to `pos`
  3548. where each element of `str` is equal to that
  3549. of `{begin() + idx, begin() + idx + str.size())`
  3550. if one exists, and @ref npos otherwise.
  3551. @param str The string to search for.
  3552. @param pos The index to start searching at. The default argument for
  3553. this parameter is @ref npos.
  3554. */
  3555. template<std::size_t M>
  3556. BHO_STATIC_STRING_CPP14_CONSTEXPR
  3557. size_type
  3558. rfind(
  3559. const basic_static_string<M, CharT, Traits>& str,
  3560. size_type pos = npos) const noexcept
  3561. {
  3562. return rfind(str.data(), pos, str.size());
  3563. }
  3564. /** Find the last occurrence of a string within the string.
  3565. Finds the last occurrence of the string pointed to
  3566. by `s` within the string starting before or at
  3567. the index `pos`.
  3568. @par Complexity
  3569. Linear.
  3570. @return The highest index `idx` less than or equal to `pos`
  3571. where each element of `{s, s + n)` is equal to that of
  3572. `{begin() + idx, begin() + idx + n)` if one exists,
  3573. and @ref npos otherwise.
  3574. @param s The string to search for.
  3575. @param pos The index to start searching at.
  3576. @param n The length of the string to search for.
  3577. */
  3578. BHO_STATIC_STRING_CPP14_CONSTEXPR
  3579. size_type
  3580. rfind(
  3581. const_pointer s,
  3582. size_type pos,
  3583. size_type n) const noexcept;
  3584. /** Find the last occurrence of a string within the string.
  3585. Finds the last occurrence of the string pointed to by `s`
  3586. of length `count` within the string starting before or at the
  3587. index `pos`, where `count` is `traits_type::length(s)`.
  3588. @par Complexity
  3589. Linear.
  3590. @return The highest index `idx` less than or equal to `pos`
  3591. where each element of `{s, s + count)` is equal to that of
  3592. `{begin() + idx, begin() + idx + count)` if one exists,
  3593. and @ref npos otherwise.
  3594. @param s The string to search for.
  3595. @param pos The index to stop searching at. The default argument
  3596. for this parameter is @ref npos.
  3597. */
  3598. BHO_STATIC_STRING_CPP14_CONSTEXPR
  3599. size_type
  3600. rfind(
  3601. const_pointer s,
  3602. size_type pos = npos) const noexcept
  3603. {
  3604. return rfind(s, pos, traits_type::length(s));
  3605. }
  3606. /** Find the last occurrence of a character within the string.
  3607. Finds the last occurrence of `c` within the string
  3608. starting before or at the index `pos`.
  3609. @par Complexity
  3610. Linear.
  3611. @return The index corrosponding to the last occurrence of `c` within
  3612. `{begin(), begin() + pos}` if it exists, and @ref npos otherwise.
  3613. @param c The character to search for.
  3614. @param pos The index to stop searching at. The default argument
  3615. for this parameter is @ref npos.
  3616. */
  3617. BHO_STATIC_STRING_CPP14_CONSTEXPR
  3618. size_type
  3619. rfind(
  3620. value_type c,
  3621. size_type pos = npos) const noexcept
  3622. {
  3623. return rfind(&c, pos, 1);
  3624. }
  3625. /** Find the first occurrence of any of the characters within the string.
  3626. Constructs a temporary `string_view_type` object `sv` from `t`, and finds
  3627. the first occurrence of any of the characters in `sv`
  3628. within the string starting at the index `pos`.
  3629. @par Complexity
  3630. Linear.
  3631. @tparam T The type of the object to convert.
  3632. @par Constraints
  3633. `std::is_convertible<const T&, string_view>::value &&
  3634. !std::is_convertible<const T&, const CharT*>::value`.
  3635. @return The index corrosponding to the first occurrence of
  3636. any of the characters in `{sv.begin(), sv.end())` within
  3637. `{begin() + pos, end())` if it exists, and @ref npos otherwise.
  3638. @param t The characters to search for.
  3639. @param pos The index to start searching at. The default argument
  3640. for this parameter is `0`.
  3641. */
  3642. template<typename T
  3643. #ifndef BHO_STATIC_STRING_DOCS
  3644. , typename = detail::enable_if_viewable_t<T, CharT, Traits>
  3645. #endif
  3646. >
  3647. BHO_STATIC_STRING_CPP14_CONSTEXPR
  3648. size_type
  3649. find_first_of(
  3650. const T& t,
  3651. size_type pos = 0) const
  3652. #ifdef BHO_STATIC_STRING_DOCS
  3653. noexcept(detail::is_nothrow_convertible<const T&, string_view_type>::value)
  3654. #else
  3655. noexcept(detail::is_nothrow_convertible<const T&, detail::common_string_view_type<T, CharT, Traits>>::value)
  3656. #endif
  3657. {
  3658. detail::common_string_view_type<T, CharT, Traits> sv = t;
  3659. return find_first_of(sv.data(), pos, sv.size());
  3660. }
  3661. /** Find the first occurrence of any of the characters within the string.
  3662. Finds the first occurrence of any of the characters within `str` within the
  3663. string starting at the index `pos`.
  3664. @par Complexity
  3665. Linear.
  3666. @return The index corrosponding to the first occurrence of any of the characters
  3667. of `str` within `{begin() + pos, end())` if it exists, and @ref npos otherwise.
  3668. @param str The characters to search for.
  3669. @param pos The index to start searching at. The default argument for
  3670. this parameter is `0`.
  3671. */
  3672. template<std::size_t M>
  3673. BHO_STATIC_STRING_CPP14_CONSTEXPR
  3674. size_type
  3675. find_first_of(
  3676. const basic_static_string<M, CharT, Traits>& str,
  3677. size_type pos = 0) const noexcept
  3678. {
  3679. return find_first_of(str.data(), pos, str.size());
  3680. }
  3681. /** Find the first occurrence of any of the characters within the string.
  3682. Finds the first occurrence of any of the characters within the string pointed to
  3683. by `s` within the string starting at the index `pos`.
  3684. @par Complexity
  3685. Linear.
  3686. @return The index corrosponding to the first occurrence
  3687. of any of the characters in `{s, s + n)` within `{begin() + pos, end())`
  3688. if it exists, and @ref npos otherwise.
  3689. @param s The characters to search for.
  3690. @param pos The index to start searching at.
  3691. @param n The length of the string to search for.
  3692. */
  3693. BHO_STATIC_STRING_CPP14_CONSTEXPR
  3694. size_type
  3695. find_first_of(
  3696. const_pointer s,
  3697. size_type pos,
  3698. size_type n) const noexcept;
  3699. /** Find the first occurrence of any of the characters within the string.
  3700. Finds the first occurrence of the any of the characters within string
  3701. pointed to by `s` of length `count` within the string starting at the
  3702. index `pos`, where `count` is `traits_type::length(s)`.
  3703. @par Complexity
  3704. Linear.
  3705. @return The index corrosponding to the first occurrence of any of
  3706. the characters in `{s, s + count)` within
  3707. `{begin() + pos, end())` if it exists, and @ref npos otherwise.
  3708. @param s The characters to search for.
  3709. @param pos The index to start searching at. The default argument
  3710. for this parameter is `0`.
  3711. */
  3712. BHO_STATIC_STRING_CPP14_CONSTEXPR
  3713. size_type
  3714. find_first_of(
  3715. const_pointer s,
  3716. size_type pos = 0) const noexcept
  3717. {
  3718. return find_first_of(s, pos, traits_type::length(s));
  3719. }
  3720. /** Find the first occurrence of a character within the string.
  3721. Finds the first occurrence of `c` within the string
  3722. starting at the index `pos`.
  3723. @par Complexity
  3724. Linear.
  3725. @return The index corrosponding to the first occurrence of `c` within
  3726. `{begin() + pos, end())` if it exists, and @ref npos otherwise.
  3727. @param c The character to search for.
  3728. @param pos The index to start searching at. The default argument
  3729. for this parameter is `0`.
  3730. */
  3731. BHO_STATIC_STRING_CPP14_CONSTEXPR
  3732. size_type
  3733. find_first_of(
  3734. value_type c,
  3735. size_type pos = 0) const noexcept
  3736. {
  3737. return find_first_of(&c, pos, 1);
  3738. }
  3739. /** Find the last occurrence of any of the characters within the string.
  3740. Constructs a temporary `string_view_type` object `sv` from `t`, and finds
  3741. the last occurrence of any of the characters in `sv`
  3742. within the string before or at the index `pos`.
  3743. @par Complexity
  3744. Linear.
  3745. @tparam T The type of the object to convert.
  3746. @par Constraints
  3747. `std::is_convertible<const T&, string_view>::value &&
  3748. !std::is_convertible<const T&, const CharT*>::value`.
  3749. @return The index corrosponding to the last occurrence of
  3750. any of the characters in `{sv.begin(), sv.end())` within
  3751. `{begin(), begin() + pos}` if it exists, and @ref npos otherwise.
  3752. @param t The characters to search for.
  3753. @param pos The index to stop searching at. The default argument
  3754. for this parameter is @ref npos.
  3755. */
  3756. template<typename T
  3757. #ifndef BHO_STATIC_STRING_DOCS
  3758. , typename = detail::enable_if_viewable_t<T, CharT, Traits>
  3759. #endif
  3760. >
  3761. BHO_STATIC_STRING_CPP14_CONSTEXPR
  3762. size_type
  3763. find_last_of(
  3764. const T& t,
  3765. size_type pos = npos) const
  3766. #ifdef BHO_STATIC_STRING_DOCS
  3767. noexcept(detail::is_nothrow_convertible<const T&, string_view_type>::value)
  3768. #else
  3769. noexcept(detail::is_nothrow_convertible<const T&, detail::common_string_view_type<T, CharT, Traits>>::value)
  3770. #endif
  3771. {
  3772. detail::common_string_view_type<T, CharT, Traits> sv = t;
  3773. return find_last_of(sv.data(), pos, sv.size());
  3774. }
  3775. /** Find the last occurrence of any of the characters within the string.
  3776. Finds the last occurrence of any of the characters within `str` within the
  3777. string starting before or at the index `pos`.
  3778. @par Complexity
  3779. Linear.
  3780. @return The index corrosponding to the last occurrence of any of the characters
  3781. of `str` within `{begin(), begin() + pos}` if it exists, and @ref npos otherwise.
  3782. @param str The characters to search for.
  3783. @param pos The index to stop searching at. The default argument for
  3784. this parameter is @ref npos.
  3785. */
  3786. template<std::size_t M>
  3787. BHO_STATIC_STRING_CPP14_CONSTEXPR
  3788. size_type
  3789. find_last_of(
  3790. const basic_static_string<M, CharT, Traits>& str,
  3791. size_type pos = npos) const noexcept
  3792. {
  3793. return find_last_of(str.data(), pos, str.size());
  3794. }
  3795. /** Find the last occurrence of any of the characters within the string.
  3796. Finds the last occurrence of any of the characters within the string pointed to
  3797. by `s` within the string before or at the index `pos`.
  3798. @par Complexity
  3799. Linear.
  3800. @return The index corrosponding to the last occurrence
  3801. of any of the characters in `{s, s + n)` within `{begin(), begin() + pos}`
  3802. if it exists, and @ref npos otherwise.
  3803. @param s The characters to search for.
  3804. @param pos The index to stop searching at.
  3805. @param n The length of the string to search for.
  3806. */
  3807. BHO_STATIC_STRING_CPP14_CONSTEXPR
  3808. size_type
  3809. find_last_of(
  3810. const_pointer s,
  3811. size_type pos,
  3812. size_type n) const noexcept;
  3813. /** Find the last occurrence of any of the characters within the string.
  3814. Finds the last occurrence of any of the characters within the string pointed to
  3815. by `s` of length `count` within the string before or at the index `pos`,
  3816. where `count` is `traits_type::length(s)`.
  3817. @par Complexity
  3818. Linear.
  3819. @return The index corrosponding to the last occurrence
  3820. of any of the characters in `{s, s + count)` within `{begin(), begin() + pos}`
  3821. if it exists, and @ref npos otherwise.
  3822. @param s The characters to search for.
  3823. @param pos The index to stop searching at. The default argument for
  3824. this parameter is @ref npos.
  3825. */
  3826. BHO_STATIC_STRING_CPP14_CONSTEXPR
  3827. size_type
  3828. find_last_of(
  3829. const_pointer s,
  3830. size_type pos = npos) const noexcept
  3831. {
  3832. return find_last_of(s, pos, traits_type::length(s));
  3833. }
  3834. /** Find the last occurrence of a character within the string.
  3835. Finds the last occurrence of `c` within the string
  3836. before or at the index `pos`.
  3837. @par Complexity
  3838. Linear.
  3839. @return The index corrosponding to the last occurrence of `c` within
  3840. `{begin(), begin() + pos}` if it exists, and @ref npos otherwise.
  3841. @param c The character to search for.
  3842. @param pos The index to stop searching at. The default argument
  3843. for this parameter is @ref npos.
  3844. */
  3845. BHO_STATIC_STRING_CPP14_CONSTEXPR
  3846. size_type
  3847. find_last_of(
  3848. value_type c,
  3849. size_type pos = npos) const noexcept
  3850. {
  3851. return find_last_of(&c, pos, 1);
  3852. }
  3853. /** Find the first occurrence of a character not within the string.
  3854. Constructs a temporary `string_view_type` object `sv` from `t`, and finds
  3855. the first character that is not within `sv`, starting at the index `pos`.
  3856. @par Complexity
  3857. Linear.
  3858. @tparam T The type of the object to convert.
  3859. @par Constraints
  3860. `std::is_convertible<const T&, string_view>::value &&
  3861. !std::is_convertible<const T&, const CharT*>::value`.
  3862. @return The index corrosponding to the first occurrence of
  3863. a character that is not in `{sv.begin(), sv.end())` within
  3864. `{begin() + pos, end())` if it exists, and @ref npos otherwise.
  3865. @param t The characters to ignore.
  3866. @param pos The index to start searching at. The default argument
  3867. for this parameter is `0`.
  3868. */
  3869. template<typename T
  3870. #ifndef BHO_STATIC_STRING_DOCS
  3871. , typename = detail::enable_if_viewable_t<T, CharT, Traits>
  3872. #endif
  3873. >
  3874. BHO_STATIC_STRING_CPP14_CONSTEXPR
  3875. size_type
  3876. find_first_not_of(
  3877. const T& t,
  3878. size_type pos = 0) const
  3879. #ifdef BHO_STATIC_STRING_DOCS
  3880. noexcept(detail::is_nothrow_convertible<const T&, string_view_type>::value)
  3881. #else
  3882. noexcept(detail::is_nothrow_convertible<const T&, detail::common_string_view_type<T, CharT, Traits>>::value)
  3883. #endif
  3884. {
  3885. detail::common_string_view_type<T, CharT, Traits> sv = t;
  3886. return find_first_not_of(sv.data(), pos, sv.size());
  3887. }
  3888. /** Find the first occurrence of any of the characters not within the string.
  3889. Finds the first occurrence of a character that is not within `str`
  3890. within the string starting at the index `pos`.
  3891. @par Complexity
  3892. Linear.
  3893. @return The index corrosponding to the first character of `{begin() + pos, end())`
  3894. that is not within `str` if it exists, and @ref npos otherwise.
  3895. @param str The characters to ignore.
  3896. @param pos The index to start searching at. The default argument for
  3897. this parameter is `0`.
  3898. */
  3899. template<std::size_t M>
  3900. BHO_STATIC_STRING_CPP14_CONSTEXPR
  3901. size_type
  3902. find_first_not_of(
  3903. const basic_static_string<M, CharT, Traits>& str,
  3904. size_type pos = 0) const noexcept
  3905. {
  3906. return find_first_not_of(str.data(), pos, str.size());
  3907. }
  3908. /** Find the first occurrence of any of the characters not within the string.
  3909. Finds the first occurrence of a character that is not within the string
  3910. pointed to by `s` within the string starting at the index `pos`.
  3911. @par Complexity
  3912. Linear.
  3913. @return The index corrosponding to the first character of `{begin() + pos, end())`
  3914. that is not within `{s, s + n)` if it exists, and @ref npos otherwise.
  3915. @param s The characters to ignore.
  3916. @param pos The index to start searching at. The default argument for
  3917. this parameter is `0`.
  3918. @param n The length of the characters to ignore.
  3919. */
  3920. BHO_STATIC_STRING_CPP14_CONSTEXPR
  3921. size_type
  3922. find_first_not_of(
  3923. const_pointer s,
  3924. size_type pos,
  3925. size_type n) const noexcept;
  3926. /** Find the first occurrence of any of the characters not within the string.
  3927. Finds the first occurrence of a character that is not within the string
  3928. pointed to by `s` of length `count` within the string starting
  3929. at the index `pos`, where `count` is `traits_type::length(s)`.
  3930. @par Complexity
  3931. Linear.
  3932. @return The index corrosponding to the first character of `{begin() + pos, end())`
  3933. that is not within `{s, s + count)` if it exists, and @ref npos otherwise.
  3934. @param s The characters to ignore.
  3935. @param pos The index to start searching at. The default argument for
  3936. this parameter is `0`.
  3937. */
  3938. BHO_STATIC_STRING_CPP14_CONSTEXPR
  3939. size_type
  3940. find_first_not_of(
  3941. const_pointer s,
  3942. size_type pos = 0) const noexcept
  3943. {
  3944. return find_first_not_of(s, pos, traits_type::length(s));
  3945. }
  3946. /** Find the first occurrence of a character not equal to `c`.
  3947. Finds the first occurrence of a character that is not equal
  3948. to `c`.
  3949. @par Complexity
  3950. Linear.
  3951. @return The index corrosponding to the first character of `{begin() + pos, end())`
  3952. that is not equal to `c` if it exists, and @ref npos otherwise.
  3953. @param c The character to ignore.
  3954. @param pos The index to start searching at. The default argument for
  3955. this parameter is `0`.
  3956. */
  3957. BHO_STATIC_STRING_CPP14_CONSTEXPR
  3958. size_type
  3959. find_first_not_of(
  3960. value_type c,
  3961. size_type pos = 0) const noexcept
  3962. {
  3963. return find_first_not_of(&c, pos, 1);
  3964. }
  3965. /** Find the last occurrence of a character not within the string.
  3966. Constructs a temporary `string_view_type` object `sv` from `t`, and finds
  3967. the last character that is not within `sv`, starting at the index `pos`.
  3968. @par Complexity
  3969. Linear.
  3970. @tparam T The type of the object to convert.
  3971. @par Constraints
  3972. `std::is_convertible<const T&, string_view>::value &&
  3973. !std::is_convertible<const T&, const CharT*>::value`.
  3974. @return The index corrosponding to the last occurrence of
  3975. a character that is not in `{sv.begin(), sv.end())` within
  3976. `{begin(), begin() + pos}` if it exists, and @ref npos otherwise.
  3977. @param t The characters to ignore.
  3978. @param pos The index to start searching at. The default argument
  3979. for this parameter is @ref npos.
  3980. */
  3981. template<typename T
  3982. #ifndef BHO_STATIC_STRING_DOCS
  3983. , typename = detail::enable_if_viewable_t<T, CharT, Traits>
  3984. #endif
  3985. >
  3986. BHO_STATIC_STRING_CPP14_CONSTEXPR
  3987. size_type
  3988. find_last_not_of(
  3989. const T& t,
  3990. size_type pos = npos) const
  3991. #ifdef BHO_STATIC_STRING_DOCS
  3992. noexcept(detail::is_nothrow_convertible<const T&, string_view_type>::value)
  3993. #else
  3994. noexcept(detail::is_nothrow_convertible<const T&, detail::common_string_view_type<T, CharT, Traits>>::value)
  3995. #endif
  3996. {
  3997. detail::common_string_view_type<T, CharT, Traits> sv = t;
  3998. return find_last_not_of(sv.data(), pos, sv.size());
  3999. }
  4000. /** Find the last occurrence of a character not within the string.
  4001. Finds the last occurrence of a character that is not within `str`
  4002. within the string before or at the index `pos`.
  4003. @par Complexity
  4004. Linear.
  4005. @return The index corrosponding to the last character of `{begin(), begin() + pos}`
  4006. that is not within `str` if it exists, and @ref npos otherwise.
  4007. @param str The characters to ignore.
  4008. @param pos The index to stop searching at. The default argument for
  4009. this parameter is @ref npos.
  4010. */
  4011. template<size_t M>
  4012. BHO_STATIC_STRING_CPP14_CONSTEXPR
  4013. size_type
  4014. find_last_not_of(
  4015. const basic_static_string<M, CharT, Traits>& str,
  4016. size_type pos = npos) const noexcept
  4017. {
  4018. return find_last_not_of(str.data(), pos, str.size());
  4019. }
  4020. /** Find the last occurrence of a character not within the string.
  4021. Finds the last occurrence of a character that is not within the
  4022. string pointed to by `s` within the string before or at the index `pos`.
  4023. @par Complexity
  4024. Linear.
  4025. @return The index corrosponding to the last character of `{begin(), begin() + pos}`
  4026. that is not within `{s, s + n)` if it exists, and @ref npos otherwise.
  4027. @param s The characters to ignore.
  4028. @param pos The index to stop searching at. The default argument for
  4029. this parameter is @ref npos.
  4030. @param n The length of the characters to ignore.
  4031. */
  4032. BHO_STATIC_STRING_CPP14_CONSTEXPR
  4033. size_type
  4034. find_last_not_of(
  4035. const_pointer s,
  4036. size_type pos,
  4037. size_type n) const noexcept;
  4038. /** Find the last occurrence of a character not within the string.
  4039. Finds the last occurrence of a character that is not within the
  4040. string pointed to by `s` of length `count` within the string
  4041. before or at the index `pos`, where `count` is `traits_type::length(s)`.
  4042. @par Complexity
  4043. Linear.
  4044. @return The index corrosponding to the last character of `{begin(), begin() + pos}`
  4045. that is not within `{s, s + count)` if it exists, and @ref npos otherwise.
  4046. @param s The characters to ignore.
  4047. @param pos The index to stop searching at. The default argument for
  4048. this parameter is @ref npos.
  4049. */
  4050. BHO_STATIC_STRING_CPP14_CONSTEXPR
  4051. size_type
  4052. find_last_not_of(
  4053. const_pointer s,
  4054. size_type pos = npos) const noexcept
  4055. {
  4056. return find_last_not_of(s, pos, traits_type::length(s));
  4057. }
  4058. /** Find the last occurrence of a character not equal to `c`.
  4059. Finds the last occurrence of a character that is not equal
  4060. to `c` before or at the index `pos`.
  4061. @par Complexity
  4062. Linear.
  4063. @return The index corrosponding to the last character of `{begin(), begin() + pos}`
  4064. that is not equal to `c` if it exists, and @ref npos otherwise.
  4065. @param c The character to ignore.
  4066. @param pos The index to start searching at. The default argument for
  4067. this parameter is @ref npos.
  4068. */
  4069. BHO_STATIC_STRING_CPP14_CONSTEXPR
  4070. size_type
  4071. find_last_not_of(
  4072. value_type c,
  4073. size_type pos = npos) const noexcept
  4074. {
  4075. return find_last_not_of(&c, pos, 1);
  4076. }
  4077. /** Return whether the string begins with a string.
  4078. Returns `true` if the string begins with `s`, and `false` otherwise.
  4079. @par Complexity
  4080. Linear.
  4081. @param t The string view to check for.
  4082. */
  4083. template<typename T
  4084. #ifndef BHO_STATIC_STRING_DOCS
  4085. , typename = detail::enable_if_viewable_t<T, CharT, Traits>
  4086. #endif
  4087. >
  4088. BHO_STATIC_STRING_CPP14_CONSTEXPR
  4089. bool
  4090. starts_with(
  4091. T const& t) const noexcept
  4092. {
  4093. detail::common_string_view_type<T, CharT, Traits> sv = t;
  4094. const size_type len = sv.size();
  4095. return size() >= len && !traits_type::compare(data(), sv.data(), len);
  4096. }
  4097. /** Return whether the string begins with a character.
  4098. Returns `true` if the string begins with `c`, and `false` otherwise.
  4099. @par Complexity
  4100. Constant.
  4101. @param c The character to check for.
  4102. */
  4103. BHO_STATIC_STRING_CPP14_CONSTEXPR
  4104. bool
  4105. starts_with(
  4106. value_type c) const noexcept
  4107. {
  4108. return !empty() && traits_type::eq(front(), c);
  4109. }
  4110. /** Return whether the string begins with a string.
  4111. Returns `true` if the string begins with the string
  4112. pointed to be `s` of length `traits_type::length(s)`,
  4113. and `false` otherwise.
  4114. @par Complexity
  4115. Linear.
  4116. @param s The string to check for.
  4117. */
  4118. BHO_STATIC_STRING_CPP14_CONSTEXPR
  4119. bool
  4120. starts_with(
  4121. const_pointer s) const noexcept
  4122. {
  4123. const size_type len = traits_type::length(s);
  4124. return size() >= len && !traits_type::compare(data(), s, len);
  4125. }
  4126. /** Return whether the string ends with a string.
  4127. Returns `true` if the string ends with `s`, and `false` otherwise.
  4128. @par Complexity
  4129. Linear.
  4130. @param t The string view to check for.
  4131. */
  4132. template<typename T
  4133. #ifndef BHO_STATIC_STRING_DOCS
  4134. , typename = detail::enable_if_viewable_t<T, CharT, Traits>
  4135. #endif
  4136. >
  4137. BHO_STATIC_STRING_CPP14_CONSTEXPR
  4138. bool
  4139. ends_with(
  4140. T const& t) const noexcept
  4141. {
  4142. detail::common_string_view_type<T, CharT, Traits> sv = t;
  4143. const size_type len = sv.size();
  4144. return size() >= len && !traits_type::compare(data() + (size() - len), sv.data(), len);
  4145. }
  4146. /** Return whether the string ends with a character.
  4147. Returns `true` if the string ends with `c`, and `false` otherwise.
  4148. @par Complexity
  4149. Constant.
  4150. @param c The character to check for.
  4151. */
  4152. BHO_STATIC_STRING_CPP14_CONSTEXPR
  4153. bool
  4154. ends_with(
  4155. value_type c) const noexcept
  4156. {
  4157. return !empty() && traits_type::eq(back(), c);
  4158. }
  4159. /** Return whether the string ends with a string.
  4160. Returns `true` if the string ends with the string
  4161. pointed to be `s` of length `traits_type::length(s)`,
  4162. and `false` otherwise.
  4163. @par Complexity
  4164. Linear.
  4165. @param s The string to check for.
  4166. */
  4167. BHO_STATIC_STRING_CPP14_CONSTEXPR
  4168. bool
  4169. ends_with(
  4170. const_pointer s) const noexcept
  4171. {
  4172. const size_type len = traits_type::length(s);
  4173. return size() >= len && !traits_type::compare(data() + (size() - len), s, len);
  4174. }
  4175. private:
  4176. BHO_STATIC_STRING_CPP14_CONSTEXPR
  4177. basic_static_string&
  4178. term() noexcept
  4179. {
  4180. this->term_impl();
  4181. return *this;
  4182. }
  4183. BHO_STATIC_STRING_CPP14_CONSTEXPR
  4184. basic_static_string&
  4185. assign_char(value_type ch, std::true_type) noexcept
  4186. {
  4187. this->set_size(1);
  4188. traits_type::assign(data()[0], ch);
  4189. return term();
  4190. }
  4191. BHO_STATIC_STRING_NORETURN
  4192. basic_static_string&
  4193. assign_char(value_type, std::false_type)
  4194. {
  4195. detail::throw_exception<std::length_error>("max_size() == 0");
  4196. // This eliminates any potential warnings
  4197. #ifdef BHO_STATIC_STRING_NO_NORETURN
  4198. return *this;
  4199. #endif
  4200. }
  4201. // Returns the size of data read from input iterator. Read data begins at data() + size() + 1.
  4202. template<typename InputIterator>
  4203. BHO_STATIC_STRING_CPP14_CONSTEXPR
  4204. size_type
  4205. read_back(
  4206. bool overwrite_null,
  4207. InputIterator first,
  4208. InputIterator last);
  4209. BHO_STATIC_STRING_CPP14_CONSTEXPR
  4210. basic_static_string&
  4211. replace_unchecked(
  4212. size_type pos,
  4213. size_type n1,
  4214. const_pointer s,
  4215. size_type n2)
  4216. {
  4217. if (pos > size())
  4218. detail::throw_exception<std::out_of_range>(
  4219. "pos > size()");
  4220. return replace_unchecked(data() + pos, data() + pos + capped_length(pos, n1), s, n2);
  4221. }
  4222. BHO_STATIC_STRING_CPP14_CONSTEXPR
  4223. basic_static_string&
  4224. replace_unchecked(
  4225. const_iterator i1,
  4226. const_iterator i2,
  4227. const_pointer s,
  4228. size_type n2);
  4229. BHO_STATIC_STRING_CPP14_CONSTEXPR
  4230. basic_static_string&
  4231. insert_unchecked(
  4232. size_type index,
  4233. const_pointer s,
  4234. size_type count)
  4235. {
  4236. if (index > size())
  4237. detail::throw_exception<std::out_of_range>(
  4238. "index > size()");
  4239. insert_unchecked(data() + index, s, count);
  4240. return *this;
  4241. }
  4242. BHO_STATIC_STRING_CPP14_CONSTEXPR
  4243. iterator
  4244. insert_unchecked(
  4245. const_iterator pos,
  4246. const_pointer s,
  4247. size_type count);
  4248. BHO_STATIC_STRING_CPP14_CONSTEXPR
  4249. basic_static_string&
  4250. assign_unchecked(
  4251. const_pointer s,
  4252. size_type count) noexcept
  4253. {
  4254. this->set_size(count);
  4255. traits_type::copy(data(), s, size() + 1);
  4256. return *this;
  4257. }
  4258. BHO_STATIC_STRING_CPP14_CONSTEXPR
  4259. size_type
  4260. capped_length(
  4261. size_type index,
  4262. size_type length) const
  4263. {
  4264. if (index > size())
  4265. detail::throw_exception<std::out_of_range>(
  4266. "index > size()");
  4267. return (std::min)(size() - index, length);
  4268. }
  4269. };
  4270. //------------------------------------------------------------------------------
  4271. //
  4272. // Non-member functions
  4273. //
  4274. //------------------------------------------------------------------------------
  4275. template<
  4276. std::size_t N, std::size_t M,
  4277. typename CharT, typename Traits>
  4278. BHO_STATIC_STRING_CPP14_CONSTEXPR
  4279. inline
  4280. bool
  4281. operator==(
  4282. const basic_static_string<N, CharT, Traits>& lhs,
  4283. const basic_static_string<M, CharT, Traits>& rhs)
  4284. {
  4285. return lhs.compare(rhs) == 0;
  4286. }
  4287. template<
  4288. std::size_t N, std::size_t M,
  4289. typename CharT, typename Traits>
  4290. BHO_STATIC_STRING_CPP14_CONSTEXPR
  4291. inline
  4292. bool
  4293. operator!=(
  4294. const basic_static_string<N, CharT, Traits>& lhs,
  4295. const basic_static_string<M, CharT, Traits>& rhs)
  4296. {
  4297. return lhs.compare(rhs) != 0;
  4298. }
  4299. template<
  4300. std::size_t N, std::size_t M,
  4301. typename CharT, typename Traits>
  4302. BHO_STATIC_STRING_CPP14_CONSTEXPR
  4303. inline
  4304. bool
  4305. operator<(
  4306. const basic_static_string<N, CharT, Traits>& lhs,
  4307. const basic_static_string<M, CharT, Traits>& rhs)
  4308. {
  4309. return lhs.compare(rhs) < 0;
  4310. }
  4311. template<
  4312. std::size_t N, std::size_t M,
  4313. typename CharT, typename Traits>
  4314. BHO_STATIC_STRING_CPP14_CONSTEXPR
  4315. inline
  4316. bool
  4317. operator<=(
  4318. const basic_static_string<N, CharT, Traits>& lhs,
  4319. const basic_static_string<M, CharT, Traits>& rhs)
  4320. {
  4321. return lhs.compare(rhs) <= 0;
  4322. }
  4323. template<
  4324. std::size_t N, std::size_t M,
  4325. typename CharT, typename Traits>
  4326. BHO_STATIC_STRING_CPP14_CONSTEXPR
  4327. inline
  4328. bool
  4329. operator>(
  4330. const basic_static_string<N, CharT, Traits>& lhs,
  4331. const basic_static_string<M, CharT, Traits>& rhs)
  4332. {
  4333. return lhs.compare(rhs) > 0;
  4334. }
  4335. template<
  4336. std::size_t N, std::size_t M,
  4337. typename CharT, typename Traits>
  4338. BHO_STATIC_STRING_CPP14_CONSTEXPR
  4339. inline
  4340. bool
  4341. operator>=(
  4342. const basic_static_string<N, CharT, Traits>& lhs,
  4343. const basic_static_string<M, CharT, Traits>& rhs)
  4344. {
  4345. return lhs.compare(rhs) >= 0;
  4346. }
  4347. template<std::size_t N, typename CharT, typename Traits>
  4348. BHO_STATIC_STRING_CPP14_CONSTEXPR
  4349. inline
  4350. bool
  4351. operator==(
  4352. const CharT* lhs,
  4353. const basic_static_string<N, CharT, Traits>& rhs)
  4354. {
  4355. return detail::lexicographical_compare<CharT, Traits>(
  4356. lhs, Traits::length(lhs),
  4357. rhs.data(), rhs.size()) == 0;
  4358. }
  4359. template<std::size_t N, typename CharT, typename Traits>
  4360. BHO_STATIC_STRING_CPP14_CONSTEXPR
  4361. inline
  4362. bool
  4363. operator==(
  4364. const basic_static_string<N, CharT, Traits>& lhs,
  4365. const CharT* rhs)
  4366. {
  4367. return detail::lexicographical_compare<CharT, Traits>(
  4368. lhs.data(), lhs.size(),
  4369. rhs, Traits::length(rhs)) == 0;
  4370. }
  4371. template<std::size_t N, typename CharT, typename Traits, class T
  4372. #ifndef BHO_STATIC_STRING_DOCS
  4373. , typename = detail::enable_if_viewable_t<T, CharT, Traits>
  4374. #endif
  4375. >
  4376. BHO_STATIC_STRING_CPP14_CONSTEXPR
  4377. inline
  4378. bool
  4379. operator==(
  4380. const T& lhs,
  4381. const basic_static_string<N, CharT, Traits>& rhs)
  4382. {
  4383. detail::common_string_view_type<T, CharT, Traits> lhsv = lhs;
  4384. return detail::lexicographical_compare<CharT, Traits>(
  4385. lhsv.data(), lhsv.size(),
  4386. rhs.data(), rhs.size()) == 0;
  4387. }
  4388. template<std::size_t N, typename CharT, typename Traits, class T
  4389. #ifndef BHO_STATIC_STRING_DOCS
  4390. , typename = detail::enable_if_viewable_t<T, CharT, Traits>
  4391. #endif
  4392. >
  4393. BHO_STATIC_STRING_CPP14_CONSTEXPR
  4394. inline
  4395. bool
  4396. operator==(
  4397. const basic_static_string<N, CharT, Traits>& lhs,
  4398. const T& rhs)
  4399. {
  4400. detail::common_string_view_type<T, CharT, Traits> rhsv = rhs;
  4401. return detail::lexicographical_compare<CharT, Traits>(
  4402. lhs.data(), lhs.size(),
  4403. rhsv.data(), rhsv.size()) == 0;
  4404. }
  4405. template<std::size_t N, typename CharT, typename Traits>
  4406. BHO_STATIC_STRING_CPP14_CONSTEXPR
  4407. inline
  4408. bool
  4409. operator!=(
  4410. const CharT* lhs,
  4411. const basic_static_string<N, CharT, Traits>& rhs)
  4412. {
  4413. return detail::lexicographical_compare<CharT, Traits>(
  4414. lhs, Traits::length(lhs),
  4415. rhs.data(), rhs.size()) != 0;
  4416. }
  4417. template<std::size_t N, typename CharT, typename Traits>
  4418. BHO_STATIC_STRING_CPP14_CONSTEXPR
  4419. inline
  4420. bool
  4421. operator!=(
  4422. const basic_static_string<N, CharT, Traits>& lhs,
  4423. const CharT* rhs)
  4424. {
  4425. return detail::lexicographical_compare<CharT, Traits>(
  4426. lhs.data(), lhs.size(),
  4427. rhs, Traits::length(rhs)) != 0;
  4428. }
  4429. template<std::size_t N, typename CharT, typename Traits, class T
  4430. #ifndef BHO_STATIC_STRING_DOCS
  4431. , typename = detail::enable_if_viewable_t<T, CharT, Traits>
  4432. #endif
  4433. >
  4434. BHO_STATIC_STRING_CPP14_CONSTEXPR
  4435. inline
  4436. bool
  4437. operator!=(
  4438. const T& lhs,
  4439. const basic_static_string<N, CharT, Traits>& rhs)
  4440. {
  4441. detail::common_string_view_type<T, CharT, Traits> lhsv = lhs;
  4442. return detail::lexicographical_compare<CharT, Traits>(
  4443. lhsv.data(), lhsv.size(),
  4444. rhs.data(), rhs.size()) != 0;
  4445. }
  4446. template<std::size_t N, typename CharT, typename Traits, class T
  4447. #ifndef BHO_STATIC_STRING_DOCS
  4448. , typename = detail::enable_if_viewable_t<T, CharT, Traits>
  4449. #endif
  4450. >
  4451. BHO_STATIC_STRING_CPP14_CONSTEXPR
  4452. inline
  4453. bool
  4454. operator!=(
  4455. const basic_static_string<N, CharT, Traits>& lhs,
  4456. const T& rhs)
  4457. {
  4458. detail::common_string_view_type<T, CharT, Traits> rhsv = rhs;
  4459. return detail::lexicographical_compare<CharT, Traits>(
  4460. lhs.data(), lhs.size(),
  4461. rhsv.data(), rhsv.size()) != 0;
  4462. }
  4463. template<std::size_t N, typename CharT, typename Traits>
  4464. BHO_STATIC_STRING_CPP14_CONSTEXPR
  4465. inline
  4466. bool
  4467. operator<(
  4468. const CharT* lhs,
  4469. const basic_static_string<N, CharT, Traits>& rhs)
  4470. {
  4471. return detail::lexicographical_compare<CharT, Traits>(
  4472. lhs, Traits::length(lhs),
  4473. rhs.data(), rhs.size()) < 0;
  4474. }
  4475. template<std::size_t N, typename CharT, typename Traits>
  4476. BHO_STATIC_STRING_CPP14_CONSTEXPR
  4477. inline
  4478. bool
  4479. operator<(
  4480. const basic_static_string<N, CharT, Traits>& lhs,
  4481. const CharT* rhs)
  4482. {
  4483. return detail::lexicographical_compare<CharT, Traits>(
  4484. lhs.data(), lhs.size(),
  4485. rhs, Traits::length(rhs)) < 0;
  4486. }
  4487. template<std::size_t N, typename CharT, typename Traits, class T
  4488. #ifndef BHO_STATIC_STRING_DOCS
  4489. , typename = detail::enable_if_viewable_t<T, CharT, Traits>
  4490. #endif
  4491. >
  4492. BHO_STATIC_STRING_CPP14_CONSTEXPR
  4493. inline
  4494. bool
  4495. operator<(
  4496. const T& lhs,
  4497. const basic_static_string<N, CharT, Traits>& rhs)
  4498. {
  4499. detail::common_string_view_type<T, CharT, Traits> lhsv = lhs;
  4500. return detail::lexicographical_compare<CharT, Traits>(
  4501. lhsv.data(), lhsv.size(),
  4502. rhs.data(), rhs.size()) < 0;
  4503. }
  4504. template<std::size_t N, typename CharT, typename Traits, class T
  4505. #ifndef BHO_STATIC_STRING_DOCS
  4506. , typename = detail::enable_if_viewable_t<T, CharT, Traits>
  4507. #endif
  4508. >
  4509. BHO_STATIC_STRING_CPP14_CONSTEXPR
  4510. inline
  4511. bool
  4512. operator<(
  4513. const basic_static_string<N, CharT, Traits>& lhs,
  4514. const T& rhs)
  4515. {
  4516. detail::common_string_view_type<T, CharT, Traits> rhsv = rhs;
  4517. return detail::lexicographical_compare<CharT, Traits>(
  4518. lhs.data(), lhs.size(),
  4519. rhsv.data(), rhsv.size()) < 0;
  4520. }
  4521. template<std::size_t N, typename CharT, typename Traits>
  4522. BHO_STATIC_STRING_CPP14_CONSTEXPR
  4523. inline
  4524. bool
  4525. operator<=(
  4526. const CharT* lhs,
  4527. const basic_static_string<N, CharT, Traits>& rhs)
  4528. {
  4529. return detail::lexicographical_compare<CharT, Traits>(
  4530. lhs, Traits::length(lhs),
  4531. rhs.data(), rhs.size()) <= 0;
  4532. }
  4533. template<std::size_t N, typename CharT, typename Traits>
  4534. BHO_STATIC_STRING_CPP14_CONSTEXPR
  4535. inline
  4536. bool
  4537. operator<=(
  4538. const basic_static_string<N, CharT, Traits>& lhs,
  4539. const CharT* rhs)
  4540. {
  4541. return detail::lexicographical_compare<CharT, Traits>(
  4542. lhs.data(), lhs.size(),
  4543. rhs, Traits::length(rhs)) <= 0;
  4544. }
  4545. template<std::size_t N, typename CharT, typename Traits, class T
  4546. #ifndef BHO_STATIC_STRING_DOCS
  4547. , typename = detail::enable_if_viewable_t<T, CharT, Traits>
  4548. #endif
  4549. >
  4550. BHO_STATIC_STRING_CPP14_CONSTEXPR
  4551. inline
  4552. bool
  4553. operator<=(
  4554. const T& lhs,
  4555. const basic_static_string<N, CharT, Traits>& rhs)
  4556. {
  4557. detail::common_string_view_type<T, CharT, Traits> lhsv = lhs;
  4558. return detail::lexicographical_compare<CharT, Traits>(
  4559. lhsv.data(), lhsv.size(),
  4560. rhs.data(), rhs.size()) <= 0;
  4561. }
  4562. template<std::size_t N, typename CharT, typename Traits, class T
  4563. #ifndef BHO_STATIC_STRING_DOCS
  4564. , typename = detail::enable_if_viewable_t<T, CharT, Traits>
  4565. #endif
  4566. >
  4567. BHO_STATIC_STRING_CPP14_CONSTEXPR
  4568. inline
  4569. bool
  4570. operator<=(
  4571. const basic_static_string<N, CharT, Traits>& lhs,
  4572. const T& rhs)
  4573. {
  4574. detail::common_string_view_type<T, CharT, Traits> rhsv = rhs;
  4575. return detail::lexicographical_compare<CharT, Traits>(
  4576. lhs.data(), lhs.size(),
  4577. rhsv.data(), rhsv.size()) <= 0;
  4578. }
  4579. template<std::size_t N, typename CharT, typename Traits>
  4580. BHO_STATIC_STRING_CPP14_CONSTEXPR
  4581. inline
  4582. bool
  4583. operator>(
  4584. const CharT* lhs,
  4585. const basic_static_string<N, CharT, Traits>& rhs)
  4586. {
  4587. return detail::lexicographical_compare<CharT, Traits>(
  4588. lhs, Traits::length(lhs),
  4589. rhs.data(), rhs.size()) > 0;
  4590. }
  4591. template<std::size_t N, typename CharT, typename Traits>
  4592. BHO_STATIC_STRING_CPP14_CONSTEXPR
  4593. inline
  4594. bool
  4595. operator>(
  4596. const basic_static_string<N, CharT, Traits>& lhs,
  4597. const CharT* rhs)
  4598. {
  4599. return detail::lexicographical_compare<CharT, Traits>(
  4600. lhs.data(), lhs.size(),
  4601. rhs, Traits::length(rhs)) > 0;
  4602. }
  4603. template<std::size_t N, typename CharT, typename Traits, class T
  4604. #ifndef BHO_STATIC_STRING_DOCS
  4605. , typename = detail::enable_if_viewable_t<T, CharT, Traits>
  4606. #endif
  4607. >
  4608. BHO_STATIC_STRING_CPP14_CONSTEXPR
  4609. inline
  4610. bool
  4611. operator>(
  4612. const T& lhs,
  4613. const basic_static_string<N, CharT, Traits>& rhs)
  4614. {
  4615. detail::common_string_view_type<T, CharT, Traits> lhsv = lhs;
  4616. return detail::lexicographical_compare<CharT, Traits>(
  4617. lhsv.data(), lhsv.size(),
  4618. rhs.data(), rhs.size()) > 0;
  4619. }
  4620. template<std::size_t N, typename CharT, typename Traits, class T
  4621. #ifndef BHO_STATIC_STRING_DOCS
  4622. , typename = detail::enable_if_viewable_t<T, CharT, Traits>
  4623. #endif
  4624. >
  4625. BHO_STATIC_STRING_CPP14_CONSTEXPR
  4626. inline
  4627. bool
  4628. operator>(
  4629. const basic_static_string<N, CharT, Traits>& lhs,
  4630. const T& rhs)
  4631. {
  4632. detail::common_string_view_type<T, CharT, Traits> rhsv = rhs;
  4633. return detail::lexicographical_compare<CharT, Traits>(
  4634. lhs.data(), lhs.size(),
  4635. rhsv.data(), rhsv.size()) > 0;
  4636. }
  4637. template<std::size_t N, typename CharT, typename Traits>
  4638. BHO_STATIC_STRING_CPP14_CONSTEXPR
  4639. inline
  4640. bool
  4641. operator>=(
  4642. const CharT* lhs,
  4643. const basic_static_string<N, CharT, Traits>& rhs)
  4644. {
  4645. return detail::lexicographical_compare<CharT, Traits>(
  4646. lhs, Traits::length(lhs),
  4647. rhs.data(), rhs.size()) >= 0;
  4648. }
  4649. template<std::size_t N, typename CharT, typename Traits>
  4650. BHO_STATIC_STRING_CPP14_CONSTEXPR
  4651. inline
  4652. bool
  4653. operator>=(
  4654. const basic_static_string<N, CharT, Traits>& lhs,
  4655. const CharT* rhs)
  4656. {
  4657. return detail::lexicographical_compare<CharT, Traits>(
  4658. lhs.data(), lhs.size(),
  4659. rhs, Traits::length(rhs)) >= 0;
  4660. }
  4661. template<std::size_t N, typename CharT, typename Traits, class T
  4662. #ifndef BHO_STATIC_STRING_DOCS
  4663. , typename = detail::enable_if_viewable_t<T, CharT, Traits>
  4664. #endif
  4665. >
  4666. BHO_STATIC_STRING_CPP14_CONSTEXPR
  4667. inline
  4668. bool
  4669. operator>=(
  4670. const T& lhs,
  4671. const basic_static_string<N, CharT, Traits>& rhs)
  4672. {
  4673. detail::common_string_view_type<T, CharT, Traits> lhsv = lhs;
  4674. return detail::lexicographical_compare<CharT, Traits>(
  4675. lhsv.data(), lhsv.size(),
  4676. rhs.data(), rhs.size()) >= 0;
  4677. }
  4678. template<std::size_t N, typename CharT, typename Traits, class T
  4679. #ifndef BHO_STATIC_STRING_DOCS
  4680. , typename = detail::enable_if_viewable_t<T, CharT, Traits>
  4681. #endif
  4682. >
  4683. BHO_STATIC_STRING_CPP14_CONSTEXPR
  4684. inline
  4685. bool
  4686. operator>=(
  4687. const basic_static_string<N, CharT, Traits>& lhs,
  4688. const T& rhs)
  4689. {
  4690. detail::common_string_view_type<T, CharT, Traits> rhsv = rhs;
  4691. return detail::lexicographical_compare<CharT, Traits>(
  4692. lhs.data(), lhs.size(),
  4693. rhsv.data(), rhsv.size()) >= 0;
  4694. }
  4695. template<
  4696. std::size_t N, std::size_t M,
  4697. typename CharT, typename Traits>
  4698. BHO_STATIC_STRING_CPP14_CONSTEXPR
  4699. inline
  4700. basic_static_string<N + M, CharT, Traits>
  4701. operator+(
  4702. const basic_static_string<N, CharT, Traits>& lhs,
  4703. const basic_static_string<M, CharT, Traits>& rhs)
  4704. {
  4705. return basic_static_string<N + M, CharT, Traits>(lhs) += rhs;
  4706. }
  4707. template<std::size_t N, typename CharT, typename Traits>
  4708. BHO_STATIC_STRING_CPP14_CONSTEXPR
  4709. inline
  4710. basic_static_string<N + 1, CharT, Traits>
  4711. operator+(
  4712. const basic_static_string<N, CharT, Traits>& lhs,
  4713. CharT rhs)
  4714. {
  4715. return basic_static_string<N + 1, CharT, Traits>(lhs) += rhs;
  4716. }
  4717. template<std::size_t N, typename CharT, typename Traits>
  4718. BHO_STATIC_STRING_CPP14_CONSTEXPR
  4719. inline
  4720. basic_static_string<N + 1, CharT, Traits>
  4721. operator+(
  4722. CharT lhs,
  4723. const basic_static_string<N, CharT, Traits>& rhs)
  4724. {
  4725. // The cast to std::size_t is needed here since 0 is a null pointer constant
  4726. return basic_static_string<N + 1, CharT, Traits>(rhs).insert(
  4727. std::size_t(0), 1, lhs);
  4728. }
  4729. // Add a null terminated character array to a string.
  4730. template<
  4731. std::size_t N, std::size_t M,
  4732. typename CharT, typename Traits>
  4733. BHO_STATIC_STRING_CPP14_CONSTEXPR
  4734. inline
  4735. basic_static_string<N + M, CharT, Traits>
  4736. operator+(
  4737. const basic_static_string<N, CharT, Traits>& lhs,
  4738. const CharT(&rhs)[M])
  4739. {
  4740. return basic_static_string<N + M, CharT, Traits>(lhs).append(+rhs);
  4741. }
  4742. // Add a string to a null terminated character array.
  4743. template<
  4744. std::size_t N, std::size_t M,
  4745. typename CharT, typename Traits>
  4746. BHO_STATIC_STRING_CPP14_CONSTEXPR
  4747. inline
  4748. basic_static_string<N + M, CharT, Traits>
  4749. operator+(
  4750. const CharT(&lhs)[N],
  4751. const basic_static_string<M, CharT, Traits>& rhs)
  4752. {
  4753. // The cast to std::size_t is needed here since 0 is a null pointer constant
  4754. return basic_static_string<N + M, CharT, Traits>(rhs).insert(
  4755. std::size_t(0), +lhs);
  4756. }
  4757. //------------------------------------------------------------------------------
  4758. //
  4759. // erase_if
  4760. //
  4761. //------------------------------------------------------------------------------
  4762. template<
  4763. std::size_t N, typename CharT,
  4764. typename Traits, typename UnaryPredicate>
  4765. BHO_STATIC_STRING_CPP14_CONSTEXPR
  4766. typename
  4767. basic_static_string<N, CharT, Traits>::size_type
  4768. erase_if(
  4769. basic_static_string<N, CharT, Traits>& str,
  4770. UnaryPredicate pred)
  4771. {
  4772. auto first = str.begin();
  4773. for (auto it = first; it != str.end(); ++it)
  4774. if (!pred(*it))
  4775. *first++ = std::move(*it);
  4776. const auto count = str.end() - first;
  4777. str.erase(first, str.end());
  4778. return count;
  4779. }
  4780. //------------------------------------------------------------------------------
  4781. //
  4782. // swap
  4783. //
  4784. //------------------------------------------------------------------------------
  4785. template<std::size_t N, typename CharT, typename Traits>
  4786. BHO_STATIC_STRING_CPP14_CONSTEXPR
  4787. inline
  4788. void
  4789. swap(
  4790. basic_static_string<N, CharT, Traits>& lhs,
  4791. basic_static_string<N, CharT, Traits>& rhs)
  4792. {
  4793. lhs.swap(rhs);
  4794. }
  4795. template<
  4796. std::size_t N, std::size_t M,
  4797. typename CharT, typename Traits>
  4798. BHO_STATIC_STRING_CPP14_CONSTEXPR
  4799. inline
  4800. void
  4801. swap(
  4802. basic_static_string<N, CharT, Traits>& lhs,
  4803. basic_static_string<M, CharT, Traits>& rhs)
  4804. {
  4805. lhs.swap(rhs);
  4806. }
  4807. //------------------------------------------------------------------------------
  4808. //
  4809. // Input/Output
  4810. //
  4811. //------------------------------------------------------------------------------
  4812. template<std::size_t N, typename CharT, typename Traits>
  4813. inline
  4814. std::basic_ostream<CharT, Traits>&
  4815. operator<<(
  4816. std::basic_ostream<CharT, Traits>& os,
  4817. const basic_static_string<N, CharT, Traits>& s)
  4818. {
  4819. #ifdef BHO_STATIC_STRING_HAS_ANY_STRING_VIEW
  4820. return os << basic_string_view<CharT, Traits>(s.data(), s.size());
  4821. #else
  4822. for (auto c: s)
  4823. os << c;
  4824. return os;
  4825. #endif
  4826. }
  4827. //------------------------------------------------------------------------------
  4828. //
  4829. // Numeric conversions
  4830. //
  4831. //------------------------------------------------------------------------------
  4832. // Signed overloads have a + 2, one for the missing digit,
  4833. // and one for the sign.
  4834. // Unsigned overloads have a + 1, for the missing digit.
  4835. // Floating point overloads have a + 4, for the sign
  4836. // of the integral part, sign of the exponent, the 'e',
  4837. // and the decimal.
  4838. /// Converts `value` to a `static_string`
  4839. static_string<std::numeric_limits<int>::digits10 + 2>
  4840. inline
  4841. to_static_string(int value) noexcept
  4842. {
  4843. return detail::to_static_string_int_impl<
  4844. std::numeric_limits<int>::digits10 + 2>(value);
  4845. }
  4846. /// Converts `value` to a `static_string`
  4847. static_string<std::numeric_limits<long>::digits10 + 2>
  4848. inline
  4849. to_static_string(long value) noexcept
  4850. {
  4851. return detail::to_static_string_int_impl<
  4852. std::numeric_limits<long>::digits10 + 2>(value);
  4853. }
  4854. /// Converts `value` to a `static_string`
  4855. static_string<std::numeric_limits<long long>::digits10 + 2>
  4856. inline
  4857. to_static_string(long long value) noexcept
  4858. {
  4859. return detail::to_static_string_int_impl<
  4860. std::numeric_limits<long long>::digits10 + 2>(value);
  4861. }
  4862. /// Converts `value` to a `static_string`
  4863. static_string<std::numeric_limits<unsigned int>::digits10 + 1>
  4864. inline
  4865. to_static_string(unsigned int value) noexcept
  4866. {
  4867. return detail::to_static_string_int_impl<
  4868. std::numeric_limits<unsigned int>::digits10 + 1>(value);
  4869. }
  4870. /// Converts `value` to a `static_string`
  4871. static_string<std::numeric_limits<unsigned long>::digits10 + 1>
  4872. inline
  4873. to_static_string(unsigned long value) noexcept
  4874. {
  4875. return detail::to_static_string_int_impl<
  4876. std::numeric_limits<unsigned long>::digits10 + 1>(value);
  4877. }
  4878. /// Converts `value` to a `static_string`
  4879. static_string<std::numeric_limits<unsigned long long>::digits10 + 1>
  4880. inline
  4881. to_static_string(unsigned long long value) noexcept
  4882. {
  4883. return detail::to_static_string_int_impl<
  4884. std::numeric_limits<unsigned long long>::digits10 + 1>(value);
  4885. }
  4886. /// Converts `value` to a `static_string`
  4887. static_string<std::numeric_limits<float>::max_digits10 + 4>
  4888. inline
  4889. to_static_string(float value) noexcept
  4890. {
  4891. return detail::to_static_string_float_impl<
  4892. std::numeric_limits<float>::max_digits10 + 4>(value);
  4893. }
  4894. /// Converts `value` to a `static_string`
  4895. static_string<std::numeric_limits<double>::max_digits10 + 4>
  4896. inline
  4897. to_static_string(double value) noexcept
  4898. {
  4899. return detail::to_static_string_float_impl<
  4900. std::numeric_limits<double>::max_digits10 + 4>(value);
  4901. }
  4902. /// Converts `value` to a `static_string`
  4903. static_string<std::numeric_limits<long double>::max_digits10 + 4>
  4904. inline
  4905. to_static_string(long double value) noexcept
  4906. {
  4907. return detail::to_static_string_float_impl<
  4908. std::numeric_limits<long double>::max_digits10 + 4>(value);
  4909. }
  4910. /// Converts `value` to a `static_wstring`
  4911. static_wstring<std::numeric_limits<int>::digits10 + 2>
  4912. inline
  4913. to_static_wstring(int value) noexcept
  4914. {
  4915. return detail::to_static_wstring_int_impl<
  4916. std::numeric_limits<int>::digits10 + 2>(value);
  4917. }
  4918. /// Converts `value` to a `static_wstring`
  4919. static_wstring<std::numeric_limits<long>::digits10 + 2>
  4920. inline
  4921. to_static_wstring(long value) noexcept
  4922. {
  4923. return detail::to_static_wstring_int_impl<
  4924. std::numeric_limits<long>::digits10 + 2>(value);
  4925. }
  4926. /// Converts `value` to a `static_wstring`
  4927. static_wstring<std::numeric_limits<long long>::digits10 + 2>
  4928. inline
  4929. to_static_wstring(long long value) noexcept
  4930. {
  4931. return detail::to_static_wstring_int_impl<
  4932. std::numeric_limits<long long>::digits10 + 2>(value);
  4933. }
  4934. /// Converts `value` to a `static_wstring`
  4935. static_wstring<std::numeric_limits<unsigned int>::digits10 + 1>
  4936. inline
  4937. to_static_wstring(unsigned int value) noexcept
  4938. {
  4939. return detail::to_static_wstring_int_impl<
  4940. std::numeric_limits<unsigned int>::digits10 + 1>(value);
  4941. }
  4942. /// Converts `value` to a `static_wstring`
  4943. static_wstring<std::numeric_limits<unsigned long>::digits10 + 1>
  4944. inline
  4945. to_static_wstring(unsigned long value) noexcept
  4946. {
  4947. return detail::to_static_wstring_int_impl<
  4948. std::numeric_limits<unsigned long>::digits10 + 1>(value);
  4949. }
  4950. /// Converts `value` to a `static_wstring`
  4951. static_wstring<std::numeric_limits<unsigned long long>::digits10 + 1>
  4952. inline
  4953. to_static_wstring(unsigned long long value) noexcept
  4954. {
  4955. return detail::to_static_wstring_int_impl<
  4956. std::numeric_limits<unsigned long long>::digits10 + 1>(value);
  4957. }
  4958. /// Converts `value` to a `static_wstring`
  4959. static_wstring<std::numeric_limits<float>::max_digits10 + 4>
  4960. inline
  4961. to_static_wstring(float value) noexcept
  4962. {
  4963. return detail::to_static_wstring_float_impl<
  4964. std::numeric_limits<float>::max_digits10 + 4>(value);
  4965. }
  4966. /// Converts `value` to a `static_wstring`
  4967. static_wstring<std::numeric_limits<double>::max_digits10 + 4>
  4968. inline
  4969. to_static_wstring(double value) noexcept
  4970. {
  4971. return detail::to_static_wstring_float_impl<
  4972. std::numeric_limits<double>::max_digits10 + 4>(value);
  4973. }
  4974. /// Converts `value` to a `static_wstring`
  4975. static_wstring<std::numeric_limits<long double>::max_digits10 + 4>
  4976. inline
  4977. to_static_wstring(long double value) noexcept
  4978. {
  4979. return detail::to_static_wstring_float_impl<
  4980. std::numeric_limits<long double>::max_digits10 + 4>(value);
  4981. }
  4982. //------------------------------------------------------------------------------
  4983. //
  4984. // Deduction Guides
  4985. //
  4986. //------------------------------------------------------------------------------
  4987. #ifdef BHO_STATIC_STRING_USE_DEDUCT
  4988. template<std::size_t N, typename CharT>
  4989. basic_static_string(const CharT(&)[N]) ->
  4990. basic_static_string<N, CharT, std::char_traits<CharT>>;
  4991. #endif
  4992. //------------------------------------------------------------------------------
  4993. //
  4994. // Hashing
  4995. //
  4996. //------------------------------------------------------------------------------
  4997. #ifndef BHO_STATIC_STRING_STANDALONE
  4998. /// hash_value overload for BHO.Container_Hash
  4999. template <std::size_t N,
  5000. typename CharT,
  5001. typename Traits>
  5002. std::size_t
  5003. hash_value(
  5004. const basic_static_string<N, CharT, Traits>& str)
  5005. {
  5006. return bho::hash_range(str.begin(), str.end());
  5007. }
  5008. #endif
  5009. } // static_strings
  5010. //------------------------------------------------------------------------------
  5011. //
  5012. // using Declarations
  5013. //
  5014. //------------------------------------------------------------------------------
  5015. using static_strings::static_string;
  5016. using static_strings::static_wstring;
  5017. using static_strings::static_u16string;
  5018. using static_strings::static_u32string;
  5019. } // bho
  5020. /// std::hash partial specialization for basic_static_string
  5021. namespace std {
  5022. template<std::size_t N, typename CharT, typename Traits>
  5023. struct hash<
  5024. #ifdef BHO_STATIC_STRING_DOCS
  5025. basic_static_string
  5026. #else
  5027. bho::static_strings::basic_static_string<N, CharT, Traits>
  5028. #endif
  5029. >
  5030. {
  5031. std::size_t
  5032. operator()(
  5033. const bho::static_strings::basic_static_string<N, CharT, Traits>& str) const noexcept
  5034. {
  5035. #if !defined(BHO_STATIC_STRING_STANDALONE)
  5036. return bho::hash_range(str.begin(), str.end());
  5037. #elif defined(BHO_STATIC_STRING_HAS_ANY_STRING_VIEW)
  5038. using view_type = typename
  5039. bho::static_strings::basic_string_view<CharT, Traits>;
  5040. return std::hash<view_type>()(view_type(str.data(), str.size()));
  5041. #else
  5042. std::size_t seed = 0;
  5043. for (CharT const& c : str) {
  5044. mix_impl(std::integral_constant<bool, sizeof(std::size_t) >= 8>{}, seed, c);
  5045. }
  5046. return seed;
  5047. #endif
  5048. }
  5049. static
  5050. void
  5051. mix_impl(std::true_type, std::size_t& seed, CharT c)
  5052. {
  5053. seed += 0x9e3779b9 + std::hash<CharT>()( c );
  5054. std::size_t const m = (std::size_t(0xe9846af) << 32) + 0x9b1a615d;
  5055. seed ^= seed >> 32;
  5056. seed *= m;
  5057. seed ^= seed >> 32;
  5058. seed *= m;
  5059. seed ^= seed >> 28;
  5060. }
  5061. static
  5062. void
  5063. mix_impl(std::false_type, std::size_t& seed, CharT c)
  5064. {
  5065. seed += 0x9e3779b9 + std::hash<CharT>()( c );
  5066. std::size_t const m1 = 0x21f0aaad;
  5067. std::size_t const m2 = 0x735a2d97;
  5068. seed ^= seed >> 16;
  5069. seed *= m1;
  5070. seed ^= seed >> 15;
  5071. seed *= m2;
  5072. seed ^= seed >> 15;
  5073. }
  5074. };
  5075. } // std
  5076. //--------------------------------------------------------------------------
  5077. //
  5078. // Implementation
  5079. //
  5080. //--------------------------------------------------------------------------
  5081. #ifndef BHO_STATIC_STRING_DOCS
  5082. namespace bho {
  5083. namespace static_strings {
  5084. template<std::size_t N, typename CharT, typename Traits>
  5085. BHO_STATIC_STRING_CPP14_CONSTEXPR
  5086. auto
  5087. basic_static_string<N, CharT, Traits>::
  5088. assign(
  5089. size_type count,
  5090. value_type ch) ->
  5091. basic_static_string&
  5092. {
  5093. if (count > max_size())
  5094. detail::throw_exception<std::length_error>(
  5095. "count > max_size()");
  5096. this->set_size(count);
  5097. traits_type::assign(data(), size(), ch);
  5098. return term();
  5099. }
  5100. template<std::size_t N, typename CharT, typename Traits>
  5101. BHO_STATIC_STRING_CPP14_CONSTEXPR
  5102. auto
  5103. basic_static_string<N, CharT, Traits>::
  5104. assign(
  5105. const_pointer s,
  5106. size_type count) ->
  5107. basic_static_string&
  5108. {
  5109. if (count > max_size())
  5110. detail::throw_exception<std::length_error>(
  5111. "count > max_size()");
  5112. this->set_size(count);
  5113. traits_type::move(data(), s, size());
  5114. return term();
  5115. }
  5116. template<std::size_t N, typename CharT, typename Traits>
  5117. template<typename InputIterator>
  5118. BHO_STATIC_STRING_CPP14_CONSTEXPR
  5119. auto
  5120. basic_static_string<N, CharT, Traits>::
  5121. assign(
  5122. InputIterator first,
  5123. InputIterator last) ->
  5124. typename std::enable_if<
  5125. detail::is_input_iterator<InputIterator>::value,
  5126. basic_static_string&>::type
  5127. {
  5128. auto ptr = data();
  5129. for (std::size_t i = 0; first != last; ++first, ++ptr, ++i)
  5130. {
  5131. if (i >= max_size())
  5132. {
  5133. this->set_size(i);
  5134. term();
  5135. detail::throw_exception<std::length_error>("n > max_size()");
  5136. }
  5137. traits_type::assign(*ptr, *first);
  5138. }
  5139. this->set_size(ptr - data());
  5140. return term();
  5141. }
  5142. template<std::size_t N, typename CharT, typename Traits>
  5143. BHO_STATIC_STRING_CPP14_CONSTEXPR
  5144. auto
  5145. basic_static_string<N, CharT, Traits>::
  5146. insert(
  5147. const_iterator pos,
  5148. size_type count,
  5149. value_type ch) ->
  5150. iterator
  5151. {
  5152. const auto curr_size = size();
  5153. const auto curr_data = data();
  5154. if (count > max_size() - curr_size)
  5155. detail::throw_exception<std::length_error>(
  5156. "count > max_size() - curr_size");
  5157. const auto index = pos - curr_data;
  5158. traits_type::move(&curr_data[index + count], &curr_data[index], curr_size - index + 1);
  5159. traits_type::assign(&curr_data[index], count, ch);
  5160. this->set_size(curr_size + count);
  5161. return &curr_data[index];
  5162. }
  5163. template<std::size_t N, typename CharT, typename Traits>
  5164. template<typename ForwardIterator>
  5165. BHO_STATIC_STRING_CPP14_CONSTEXPR
  5166. auto
  5167. basic_static_string<N, CharT, Traits>::
  5168. insert(
  5169. const_iterator pos,
  5170. ForwardIterator first,
  5171. ForwardIterator last) ->
  5172. typename std::enable_if<
  5173. detail::is_forward_iterator<
  5174. ForwardIterator>::value, iterator>::type
  5175. {
  5176. // input
  5177. const std::size_t count = detail::distance(first, last);
  5178. const auto first_addr = &*first;
  5179. const auto last_addr = first_addr + count;
  5180. // output
  5181. const auto curr_size = size();
  5182. const auto curr_data = data();
  5183. const std::size_t index = pos - curr_data;
  5184. auto dest = &curr_data[index];
  5185. if (count > max_size() - curr_size)
  5186. detail::throw_exception<std::length_error>(
  5187. "count > max_size() - curr_size");
  5188. traits_type::move(dest + count, dest, curr_size - index + 1);
  5189. const bool inside = detail::ptr_in_range(curr_data, curr_data + curr_size, first_addr);
  5190. if (!inside || last_addr <= pos)
  5191. {
  5192. detail::copy_with_traits<Traits>(first, last, dest);
  5193. }
  5194. else /* if (inside) */
  5195. {
  5196. const size_type offset = first_addr - curr_data;
  5197. if (offset < index)
  5198. {
  5199. const size_type diff = index - offset;
  5200. traits_type::copy(dest, &curr_data[offset], diff);
  5201. traits_type::copy(&curr_data[index + diff], dest + count, count - diff);
  5202. }
  5203. else
  5204. {
  5205. auto src = &curr_data[offset + count];
  5206. traits_type::copy(dest, src, count);
  5207. }
  5208. }
  5209. this->set_size(curr_size + count);
  5210. return curr_data + index;
  5211. }
  5212. template<std::size_t N, typename CharT, typename Traits>
  5213. template<typename InputIterator>
  5214. BHO_STATIC_STRING_CPP14_CONSTEXPR
  5215. auto
  5216. basic_static_string<N, CharT, Traits>::
  5217. insert(
  5218. const_iterator pos,
  5219. InputIterator first,
  5220. InputIterator last) ->
  5221. typename std::enable_if<
  5222. detail::is_input_iterator<
  5223. InputIterator>::value &&
  5224. !detail::is_forward_iterator<
  5225. InputIterator>::value, iterator>::type
  5226. {
  5227. const auto curr_size = size();
  5228. const auto curr_data = data();
  5229. const auto count = read_back(false, first, last);
  5230. const std::size_t index = pos - curr_data;
  5231. std::rotate(&curr_data[index], &curr_data[curr_size + 1], &curr_data[curr_size + count + 1]);
  5232. this->set_size(curr_size + count);
  5233. return curr_data + index;
  5234. }
  5235. template<std::size_t N, typename CharT, typename Traits>
  5236. BHO_STATIC_STRING_CPP14_CONSTEXPR
  5237. auto
  5238. basic_static_string<N, CharT, Traits>::
  5239. erase(
  5240. const_iterator first,
  5241. const_iterator last) ->
  5242. iterator
  5243. {
  5244. const auto curr_data = data();
  5245. const std::size_t index = first - curr_data;
  5246. traits_type::move(&curr_data[index], last, (end() - last) + 1);
  5247. this->set_size(size() - std::size_t(last - first));
  5248. return curr_data + index;
  5249. }
  5250. template<std::size_t N, typename CharT, typename Traits>
  5251. BHO_STATIC_STRING_CPP14_CONSTEXPR
  5252. void
  5253. basic_static_string<N, CharT, Traits>::
  5254. push_back(
  5255. value_type ch)
  5256. {
  5257. const auto curr_size = size();
  5258. if (curr_size >= max_size())
  5259. detail::throw_exception<std::length_error>(
  5260. "curr_size >= max_size()");
  5261. traits_type::assign(data()[curr_size], ch);
  5262. this->set_size(curr_size + 1);
  5263. term();
  5264. }
  5265. template<std::size_t N, typename CharT, typename Traits>
  5266. BHO_STATIC_STRING_CPP14_CONSTEXPR
  5267. auto
  5268. basic_static_string<N, CharT, Traits>::
  5269. append(
  5270. size_type count,
  5271. value_type ch) ->
  5272. basic_static_string&
  5273. {
  5274. const auto curr_size = size();
  5275. if (count > max_size() - curr_size)
  5276. detail::throw_exception<std::length_error>(
  5277. "count > max_size() - size()");
  5278. traits_type::assign(end(), count, ch);
  5279. this->set_size(curr_size + count);
  5280. return term();
  5281. }
  5282. template<std::size_t N, typename CharT, typename Traits>
  5283. BHO_STATIC_STRING_CPP14_CONSTEXPR
  5284. auto
  5285. basic_static_string<N, CharT, Traits>::
  5286. append(
  5287. const_pointer s,
  5288. size_type count) ->
  5289. basic_static_string&
  5290. {
  5291. const auto curr_size = size();
  5292. if (count > max_size() - curr_size)
  5293. detail::throw_exception<std::length_error>(
  5294. "count > max_size() - size()");
  5295. traits_type::copy(end(), s, count);
  5296. this->set_size(curr_size + count);
  5297. return term();
  5298. }
  5299. template<std::size_t N, typename CharT, typename Traits>
  5300. BHO_STATIC_STRING_CPP14_CONSTEXPR
  5301. void
  5302. basic_static_string<N, CharT, Traits>::
  5303. resize(size_type n, value_type c)
  5304. {
  5305. if (n > max_size())
  5306. detail::throw_exception<std::length_error>(
  5307. "n > max_size()");
  5308. const auto curr_size = size();
  5309. if(n > curr_size)
  5310. traits_type::assign(data() + curr_size, n - curr_size, c);
  5311. this->set_size(n);
  5312. term();
  5313. }
  5314. template<std::size_t N, typename CharT, typename Traits>
  5315. BHO_STATIC_STRING_CPP14_CONSTEXPR
  5316. void
  5317. basic_static_string<N, CharT, Traits>::
  5318. swap(basic_static_string& s) noexcept
  5319. {
  5320. const auto curr_size = size();
  5321. basic_static_string tmp(s);
  5322. s.set_size(curr_size);
  5323. traits_type::copy(&s.data()[0], data(), curr_size + 1);
  5324. this->set_size(tmp.size());
  5325. traits_type::copy(data(), tmp.data(), size() + 1);
  5326. }
  5327. template<std::size_t N, typename CharT, typename Traits>
  5328. template<std::size_t M>
  5329. BHO_STATIC_STRING_CPP14_CONSTEXPR
  5330. void
  5331. basic_static_string<N, CharT, Traits>::
  5332. swap(basic_static_string<M, CharT, Traits>& s)
  5333. {
  5334. const auto curr_size = size();
  5335. if (curr_size > s.max_size())
  5336. detail::throw_exception<std::length_error>(
  5337. "curr_size > s.max_size()");
  5338. if (s.size() > max_size())
  5339. detail::throw_exception<std::length_error>(
  5340. "s.size() > max_size()");
  5341. basic_static_string tmp(s);
  5342. s.set_size(curr_size);
  5343. traits_type::copy(&s.data()[0], data(), curr_size + 1);
  5344. this->set_size(tmp.size());
  5345. traits_type::copy(data(), &tmp.data()[0], size() + 1);
  5346. }
  5347. template<std::size_t N, typename CharT, typename Traits>
  5348. BHO_STATIC_STRING_CPP14_CONSTEXPR
  5349. auto
  5350. basic_static_string<N, CharT, Traits>::
  5351. replace(
  5352. const_iterator i1,
  5353. const_iterator i2,
  5354. size_type n,
  5355. value_type c) ->
  5356. basic_static_string<N, CharT, Traits>&
  5357. {
  5358. const auto curr_size = size();
  5359. const auto curr_data = data();
  5360. const std::size_t n1 = i2 - i1;
  5361. if (n > max_size() || curr_size - n1 >= max_size() - n)
  5362. detail::throw_exception<std::length_error>(
  5363. "replaced string exceeds max_size()");
  5364. const auto pos = i1 - curr_data;
  5365. traits_type::move(&curr_data[pos + n], i2, (end() - i2) + 1);
  5366. traits_type::assign(&curr_data[pos], n, c);
  5367. this->set_size((curr_size - n1) + n);
  5368. return *this;
  5369. }
  5370. template<std::size_t N, typename CharT, typename Traits>
  5371. template<typename ForwardIterator>
  5372. BHO_STATIC_STRING_CPP14_CONSTEXPR
  5373. auto
  5374. basic_static_string<N, CharT, Traits>::
  5375. replace(
  5376. const_iterator i1,
  5377. const_iterator i2,
  5378. ForwardIterator j1,
  5379. ForwardIterator j2) ->
  5380. typename std::enable_if<
  5381. detail::is_forward_iterator<ForwardIterator>::value,
  5382. basic_static_string<N, CharT, Traits>&>::type
  5383. {
  5384. const auto curr_size = size();
  5385. const auto curr_data = data();
  5386. const auto first_addr = &*j1;
  5387. const std::size_t n1 = i2 - i1;
  5388. const std::size_t n2 = detail::distance(j1, j2);
  5389. const std::size_t pos = i1 - curr_data;
  5390. if (n2 > max_size() || curr_size - (std::min)(n1, curr_size - pos) >= max_size() - n2)
  5391. detail::throw_exception<std::length_error>(
  5392. "replaced string exceeds max_size()");
  5393. const bool inside = detail::ptr_in_range(curr_data, curr_data + curr_size, first_addr);
  5394. if (inside && first_addr == i1 && n1 == n2)
  5395. return *this;
  5396. // Short circuit evaluation ensures that the pointer arithmetic is valid
  5397. if (!inside || (inside && (first_addr + n2 <= i1)))
  5398. {
  5399. // source outside
  5400. traits_type::move(&curr_data[pos + n2], &curr_data[pos + n1], curr_size - pos - n1 + 1);
  5401. detail::copy_with_traits<Traits>(j1, j2, &curr_data[pos]);
  5402. }
  5403. else
  5404. {
  5405. // source inside
  5406. const size_type offset = first_addr - curr_data;
  5407. if (n2 >= n1)
  5408. {
  5409. // grow/unchanged
  5410. const size_type diff = offset <= pos + n1 ? (std::min)((pos + n1) - offset, n2) : 0;
  5411. // shift all right of splice point by n2 - n1 to the right
  5412. traits_type::move(&curr_data[pos + n2], &curr_data[pos + n1], curr_size - pos - n1 + 1);
  5413. // copy all before splice point
  5414. traits_type::move(&curr_data[pos], &curr_data[offset], diff);
  5415. // copy all after splice point
  5416. traits_type::move(&curr_data[pos + diff], &curr_data[(offset - n1) + n2 + diff], n2 - diff);
  5417. }
  5418. else
  5419. {
  5420. // shrink
  5421. // copy all elements into place
  5422. traits_type::move(&curr_data[pos], &curr_data[offset], n2);
  5423. // shift all elements after splice point left
  5424. traits_type::move(&curr_data[pos + n2], &curr_data[pos + n1], curr_size - pos - n1 + 1);
  5425. }
  5426. }
  5427. this->set_size((curr_size - n1) + n2);
  5428. return *this;
  5429. }
  5430. template<std::size_t N, typename CharT, typename Traits>
  5431. template<typename InputIterator>
  5432. BHO_STATIC_STRING_CPP14_CONSTEXPR
  5433. auto
  5434. basic_static_string<N, CharT, Traits>::
  5435. replace(
  5436. const_iterator i1,
  5437. const_iterator i2,
  5438. InputIterator j1,
  5439. InputIterator j2) ->
  5440. typename std::enable_if<
  5441. detail::is_input_iterator<
  5442. InputIterator>::value &&
  5443. !detail::is_forward_iterator<
  5444. InputIterator>::value,
  5445. basic_static_string<N, CharT, Traits>&>::type
  5446. {
  5447. const auto curr_size = size();
  5448. const auto curr_data = data();
  5449. const std::size_t n1 = detail::distance(i1, i2);
  5450. const std::size_t n2 = read_back(false, j1, j2);
  5451. const std::size_t pos = i1 - curr_data;
  5452. // Rotate to the correct order. [i2, end] will now start with the replaced string,
  5453. // continue to the existing string not being replaced, and end with a null terminator
  5454. std::rotate(&curr_data[pos], &curr_data[curr_size + 1], &curr_data[curr_size + n2 + 1]);
  5455. // Move everything from the end of the splice point to the end of the rotated string to
  5456. // the begining of the splice point
  5457. traits_type::move(&curr_data[pos + n2], &curr_data[pos + n2 + n1], ((curr_size - n1) + n2) - pos);
  5458. this->set_size((curr_size - n1) + n2);
  5459. return *this;
  5460. }
  5461. template<std::size_t N, typename CharT, typename Traits>
  5462. BHO_STATIC_STRING_CPP14_CONSTEXPR
  5463. auto
  5464. basic_static_string<N, CharT, Traits>::
  5465. find(
  5466. const_pointer s,
  5467. size_type pos,
  5468. size_type n) const noexcept ->
  5469. size_type
  5470. {
  5471. const auto curr_size = size();
  5472. if (pos > curr_size || n > curr_size - pos)
  5473. return npos;
  5474. if (!n)
  5475. return pos;
  5476. const auto res = detail::search(data() + pos, data() + curr_size, s, s + n, traits_type::eq);
  5477. return res == end() ? npos : detail::distance(data(), res);
  5478. }
  5479. template<std::size_t N, typename CharT, typename Traits>
  5480. BHO_STATIC_STRING_CPP14_CONSTEXPR
  5481. auto
  5482. basic_static_string<N, CharT, Traits>::
  5483. rfind(
  5484. const_pointer s,
  5485. size_type pos,
  5486. size_type n) const noexcept ->
  5487. size_type
  5488. {
  5489. const auto curr_size = size();
  5490. const auto curr_data = data();
  5491. if (curr_size < n)
  5492. return npos;
  5493. if (pos > curr_size - n)
  5494. pos = curr_size - n;
  5495. if (!n)
  5496. return pos;
  5497. for (auto sub = &curr_data[pos]; sub >= curr_data; --sub)
  5498. if (!traits_type::compare(sub, s, n))
  5499. return detail::distance(curr_data, sub);
  5500. return npos;
  5501. }
  5502. template<std::size_t N, typename CharT, typename Traits>
  5503. BHO_STATIC_STRING_CPP14_CONSTEXPR
  5504. auto
  5505. basic_static_string<N, CharT, Traits>::
  5506. find_first_of(
  5507. const_pointer s,
  5508. size_type pos,
  5509. size_type n) const noexcept ->
  5510. size_type
  5511. {
  5512. const auto curr_data = data();
  5513. if (pos >= size() || !n)
  5514. return npos;
  5515. const auto res = detail::find_first_of(&curr_data[pos], &curr_data[size()], s, &s[n], traits_type::eq);
  5516. return res == end() ? npos : detail::distance(curr_data, res);
  5517. }
  5518. template<std::size_t N, typename CharT, typename Traits>
  5519. BHO_STATIC_STRING_CPP14_CONSTEXPR
  5520. auto
  5521. basic_static_string<N, CharT, Traits>::
  5522. find_last_of(
  5523. const_pointer s,
  5524. size_type pos,
  5525. size_type n) const noexcept ->
  5526. size_type
  5527. {
  5528. const auto curr_size = size();
  5529. if (!n)
  5530. return npos;
  5531. if (pos >= curr_size)
  5532. pos = 0;
  5533. else
  5534. pos = curr_size - (pos + 1);
  5535. const auto res = detail::find_first_of(rbegin() + pos, rend(), s, &s[n], traits_type::eq);
  5536. return res == rend() ? npos : curr_size - 1 - detail::distance(rbegin(), res);
  5537. }
  5538. template<std::size_t N, typename CharT, typename Traits>
  5539. BHO_STATIC_STRING_CPP14_CONSTEXPR
  5540. auto
  5541. basic_static_string<N, CharT, Traits>::
  5542. find_first_not_of(
  5543. const_pointer s,
  5544. size_type pos,
  5545. size_type n) const noexcept ->
  5546. size_type
  5547. {
  5548. if (pos >= size())
  5549. return npos;
  5550. if (!n)
  5551. return pos;
  5552. const auto res = detail::find_not_of<Traits>(data() + pos, data() + size(), s, n);
  5553. return res == end() ? npos : detail::distance(data(), res);
  5554. }
  5555. template<std::size_t N, typename CharT, typename Traits>
  5556. BHO_STATIC_STRING_CPP14_CONSTEXPR
  5557. auto
  5558. basic_static_string<N, CharT, Traits>::
  5559. find_last_not_of(
  5560. const_pointer s,
  5561. size_type pos,
  5562. size_type n) const noexcept ->
  5563. size_type
  5564. {
  5565. const auto curr_size = size();
  5566. if (pos >= curr_size)
  5567. pos = curr_size - 1;
  5568. if (!n)
  5569. return pos;
  5570. pos = curr_size - (pos + 1);
  5571. const auto res = detail::find_not_of<Traits>(rbegin() + pos, rend(), s, n);
  5572. return res == rend() ? npos : curr_size - 1 - detail::distance(rbegin(), res);
  5573. }
  5574. template<std::size_t N, typename CharT, typename Traits>
  5575. template<typename InputIterator>
  5576. BHO_STATIC_STRING_CPP14_CONSTEXPR
  5577. auto
  5578. basic_static_string<N, CharT, Traits>::
  5579. read_back(
  5580. bool overwrite_null,
  5581. InputIterator first,
  5582. InputIterator last) ->
  5583. size_type
  5584. {
  5585. const auto curr_data = data();
  5586. auto new_size = size();
  5587. for (; first != last; ++first)
  5588. {
  5589. if (new_size >= max_size())
  5590. {
  5591. // if we overwrote the null terminator,
  5592. // put it back
  5593. if (overwrite_null)
  5594. term();
  5595. detail::throw_exception<std::length_error>(
  5596. "count > max_size() - size()");
  5597. }
  5598. traits_type::assign(curr_data[new_size++ + (!overwrite_null)], *first);
  5599. }
  5600. return new_size - size();
  5601. }
  5602. template<std::size_t N, typename CharT, typename Traits>
  5603. BHO_STATIC_STRING_CPP14_CONSTEXPR
  5604. auto
  5605. basic_static_string<N, CharT, Traits>::
  5606. replace_unchecked(
  5607. const_iterator i1,
  5608. const_iterator i2,
  5609. const_pointer s,
  5610. size_type n2) ->
  5611. basic_static_string&
  5612. {
  5613. const auto curr_data = data();
  5614. const auto curr_size = size();
  5615. const std::size_t pos = i1 - curr_data;
  5616. const std::size_t n1 = i2 - i1;
  5617. if (n2 > max_size() || curr_size - (std::min)(n1, curr_size - pos) >= max_size() - n2)
  5618. detail::throw_exception<std::length_error>(
  5619. "replaced string exceeds max_size()");
  5620. traits_type::move(&curr_data[pos + n2], i2, (end() - i2) + 1);
  5621. traits_type::copy(&curr_data[pos], s, n2);
  5622. this->set_size((curr_size - n1) + n2);
  5623. return *this;
  5624. }
  5625. template<std::size_t N, typename CharT, typename Traits>
  5626. BHO_STATIC_STRING_CPP14_CONSTEXPR
  5627. auto
  5628. basic_static_string<N, CharT, Traits>::
  5629. insert_unchecked(
  5630. const_iterator pos,
  5631. const_pointer s,
  5632. size_type count) ->
  5633. iterator
  5634. {
  5635. const auto curr_data = data();
  5636. const auto curr_size = size();
  5637. if (count > max_size() - curr_size)
  5638. detail::throw_exception<std::length_error>(
  5639. "count > max_size() - curr_size");
  5640. const std::size_t index = pos - curr_data;
  5641. traits_type::move(&curr_data[index + count], pos, (end() - pos) + 1);
  5642. traits_type::copy(&curr_data[index], s, count);
  5643. this->set_size(curr_size + count);
  5644. return curr_data + index;
  5645. }
  5646. } // static_strings
  5647. } // bho
  5648. #if defined(__GNUC__) && __GNUC__ >= 7
  5649. #pragma GCC diagnostic pop
  5650. #endif
  5651. #if defined(__GNUC__) && __GNUC__ >= 8
  5652. #pragma GCC diagnostic pop
  5653. #endif
  5654. #endif
  5655. #endif