| 1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897189818991900190119021903190419051906190719081909191019111912191319141915191619171918191919201921192219231924192519261927192819291930193119321933193419351936193719381939194019411942194319441945194619471948194919501951195219531954195519561957195819591960196119621963196419651966196719681969197019711972197319741975197619771978197919801981198219831984198519861987198819891990199119921993199419951996199719981999200020012002200320042005200620072008200920102011201220132014201520162017201820192020202120222023202420252026202720282029203020312032203320342035203620372038203920402041204220432044204520462047204820492050205120522053205420552056205720582059206020612062206320642065206620672068206920702071207220732074207520762077207820792080208120822083208420852086208720882089209020912092209320942095209620972098209921002101210221032104210521062107210821092110211121122113211421152116211721182119212021212122212321242125212621272128212921302131213221332134213521362137213821392140214121422143214421452146214721482149215021512152215321542155215621572158215921602161216221632164216521662167216821692170217121722173217421752176217721782179218021812182218321842185218621872188218921902191219221932194219521962197219821992200220122022203220422052206220722082209221022112212221322142215221622172218221922202221222222232224222522262227222822292230223122322233223422352236223722382239224022412242224322442245224622472248224922502251225222532254225522562257225822592260226122622263226422652266226722682269227022712272227322742275227622772278227922802281228222832284228522862287228822892290229122922293229422952296229722982299230023012302230323042305230623072308230923102311231223132314231523162317231823192320232123222323232423252326232723282329233023312332233323342335233623372338233923402341234223432344234523462347234823492350235123522353235423552356235723582359236023612362236323642365236623672368236923702371237223732374237523762377237823792380238123822383238423852386238723882389239023912392239323942395239623972398239924002401240224032404240524062407240824092410241124122413241424152416241724182419242024212422242324242425242624272428242924302431243224332434243524362437243824392440244124422443244424452446244724482449245024512452245324542455245624572458245924602461246224632464246524662467246824692470247124722473247424752476247724782479248024812482248324842485248624872488248924902491249224932494249524962497249824992500250125022503250425052506250725082509251025112512251325142515251625172518251925202521252225232524252525262527252825292530253125322533253425352536253725382539254025412542254325442545254625472548254925502551255225532554255525562557255825592560256125622563256425652566256725682569257025712572257325742575257625772578257925802581258225832584258525862587258825892590259125922593259425952596259725982599260026012602260326042605260626072608260926102611261226132614261526162617261826192620262126222623262426252626262726282629263026312632263326342635263626372638263926402641264226432644264526462647264826492650265126522653265426552656265726582659266026612662266326642665266626672668266926702671267226732674267526762677267826792680268126822683268426852686268726882689269026912692269326942695269626972698269927002701270227032704270527062707270827092710271127122713271427152716271727182719272027212722272327242725272627272728272927302731273227332734273527362737273827392740274127422743274427452746274727482749275027512752275327542755275627572758275927602761276227632764276527662767276827692770277127722773277427752776277727782779278027812782278327842785278627872788278927902791279227932794279527962797279827992800280128022803280428052806280728082809281028112812281328142815281628172818281928202821282228232824282528262827282828292830283128322833283428352836283728382839284028412842284328442845284628472848284928502851285228532854285528562857285828592860286128622863286428652866286728682869287028712872287328742875287628772878287928802881288228832884288528862887288828892890289128922893289428952896289728982899290029012902290329042905290629072908290929102911291229132914291529162917291829192920292129222923292429252926292729282929293029312932293329342935293629372938293929402941294229432944294529462947294829492950295129522953295429552956295729582959296029612962296329642965296629672968296929702971297229732974297529762977297829792980298129822983298429852986298729882989299029912992299329942995299629972998299930003001300230033004300530063007300830093010301130123013301430153016301730183019302030213022302330243025302630273028302930303031303230333034303530363037303830393040304130423043304430453046304730483049305030513052305330543055305630573058305930603061306230633064306530663067306830693070307130723073307430753076307730783079308030813082308330843085308630873088308930903091309230933094309530963097309830993100310131023103310431053106310731083109311031113112311331143115311631173118311931203121312231233124312531263127312831293130313131323133313431353136313731383139314031413142314331443145314631473148314931503151315231533154315531563157315831593160316131623163316431653166316731683169317031713172317331743175317631773178317931803181318231833184318531863187318831893190319131923193319431953196319731983199320032013202320332043205320632073208320932103211321232133214321532163217321832193220322132223223322432253226322732283229323032313232323332343235323632373238323932403241324232433244324532463247324832493250325132523253325432553256325732583259326032613262326332643265326632673268326932703271327232733274327532763277327832793280328132823283328432853286328732883289329032913292329332943295329632973298329933003301330233033304330533063307330833093310331133123313331433153316331733183319332033213322332333243325332633273328332933303331333233333334333533363337333833393340334133423343334433453346334733483349335033513352335333543355335633573358335933603361336233633364336533663367336833693370337133723373337433753376337733783379338033813382338333843385338633873388338933903391339233933394339533963397339833993400340134023403340434053406340734083409341034113412341334143415341634173418341934203421342234233424342534263427342834293430343134323433343434353436343734383439344034413442344334443445344634473448344934503451345234533454345534563457345834593460346134623463346434653466346734683469347034713472347334743475347634773478347934803481348234833484348534863487348834893490349134923493349434953496349734983499350035013502350335043505350635073508350935103511351235133514351535163517351835193520352135223523352435253526352735283529353035313532353335343535353635373538353935403541354235433544354535463547354835493550355135523553355435553556355735583559356035613562356335643565356635673568356935703571357235733574357535763577357835793580358135823583358435853586358735883589359035913592359335943595359635973598359936003601360236033604360536063607360836093610361136123613361436153616361736183619362036213622362336243625362636273628362936303631363236333634363536363637363836393640364136423643364436453646364736483649365036513652365336543655365636573658365936603661366236633664366536663667366836693670367136723673367436753676367736783679368036813682368336843685368636873688368936903691369236933694369536963697369836993700370137023703370437053706370737083709371037113712371337143715371637173718371937203721372237233724372537263727372837293730373137323733373437353736373737383739374037413742374337443745374637473748374937503751375237533754375537563757375837593760376137623763376437653766376737683769377037713772377337743775377637773778377937803781378237833784378537863787378837893790379137923793379437953796379737983799380038013802380338043805380638073808380938103811381238133814381538163817381838193820382138223823382438253826382738283829383038313832383338343835383638373838383938403841384238433844384538463847384838493850385138523853385438553856385738583859386038613862386338643865386638673868386938703871387238733874387538763877387838793880388138823883388438853886388738883889389038913892389338943895389638973898389939003901390239033904390539063907390839093910391139123913391439153916391739183919392039213922392339243925392639273928392939303931393239333934393539363937393839393940394139423943394439453946394739483949395039513952395339543955395639573958395939603961396239633964396539663967396839693970397139723973397439753976397739783979398039813982398339843985398639873988398939903991399239933994399539963997399839994000400140024003400440054006400740084009401040114012401340144015401640174018401940204021402240234024402540264027402840294030403140324033403440354036403740384039404040414042404340444045404640474048404940504051405240534054405540564057405840594060406140624063406440654066406740684069407040714072407340744075407640774078407940804081408240834084408540864087408840894090409140924093409440954096409740984099410041014102410341044105410641074108410941104111411241134114411541164117411841194120412141224123412441254126412741284129413041314132413341344135413641374138413941404141414241434144414541464147414841494150415141524153415441554156415741584159416041614162416341644165416641674168416941704171417241734174417541764177417841794180418141824183418441854186418741884189419041914192419341944195419641974198419942004201420242034204420542064207420842094210421142124213421442154216421742184219422042214222422342244225422642274228422942304231423242334234423542364237423842394240424142424243424442454246424742484249425042514252425342544255425642574258425942604261426242634264426542664267426842694270427142724273427442754276427742784279428042814282428342844285428642874288428942904291429242934294429542964297429842994300430143024303430443054306430743084309431043114312431343144315431643174318431943204321432243234324432543264327432843294330433143324333433443354336433743384339434043414342434343444345434643474348434943504351435243534354435543564357435843594360436143624363436443654366436743684369437043714372437343744375437643774378437943804381438243834384438543864387438843894390439143924393439443954396439743984399440044014402440344044405440644074408440944104411441244134414441544164417441844194420442144224423442444254426442744284429443044314432443344344435443644374438443944404441444244434444444544464447444844494450445144524453445444554456445744584459446044614462446344644465446644674468446944704471447244734474447544764477447844794480448144824483448444854486448744884489449044914492449344944495449644974498449945004501450245034504450545064507450845094510451145124513451445154516451745184519452045214522452345244525452645274528452945304531453245334534453545364537453845394540454145424543454445454546454745484549455045514552455345544555455645574558455945604561456245634564456545664567456845694570457145724573457445754576457745784579458045814582458345844585458645874588458945904591459245934594459545964597459845994600460146024603460446054606460746084609461046114612461346144615461646174618461946204621462246234624462546264627462846294630463146324633463446354636463746384639464046414642464346444645464646474648464946504651465246534654465546564657465846594660466146624663466446654666466746684669467046714672467346744675467646774678467946804681468246834684468546864687468846894690469146924693469446954696469746984699470047014702470347044705470647074708470947104711471247134714471547164717471847194720472147224723472447254726472747284729473047314732473347344735473647374738473947404741474247434744474547464747474847494750475147524753475447554756475747584759476047614762476347644765476647674768476947704771477247734774477547764777477847794780478147824783478447854786478747884789479047914792479347944795479647974798479948004801480248034804480548064807480848094810481148124813481448154816481748184819482048214822482348244825482648274828482948304831483248334834483548364837483848394840484148424843484448454846484748484849485048514852485348544855485648574858485948604861486248634864486548664867486848694870487148724873487448754876487748784879488048814882488348844885488648874888488948904891489248934894489548964897489848994900490149024903490449054906490749084909491049114912491349144915491649174918491949204921492249234924492549264927492849294930493149324933493449354936493749384939494049414942494349444945494649474948494949504951495249534954495549564957495849594960496149624963496449654966496749684969497049714972497349744975497649774978497949804981498249834984498549864987498849894990499149924993499449954996499749984999500050015002500350045005500650075008500950105011501250135014501550165017501850195020502150225023502450255026502750285029503050315032503350345035503650375038503950405041504250435044504550465047504850495050505150525053505450555056505750585059506050615062506350645065506650675068506950705071507250735074507550765077507850795080508150825083508450855086508750885089509050915092509350945095509650975098509951005101510251035104510551065107510851095110511151125113511451155116511751185119512051215122512351245125512651275128512951305131513251335134513551365137513851395140514151425143514451455146514751485149515051515152515351545155515651575158515951605161516251635164516551665167516851695170517151725173517451755176517751785179518051815182518351845185518651875188518951905191519251935194519551965197519851995200520152025203520452055206520752085209521052115212521352145215521652175218521952205221522252235224522552265227522852295230523152325233523452355236523752385239524052415242524352445245524652475248524952505251525252535254525552565257525852595260526152625263526452655266526752685269527052715272527352745275527652775278527952805281528252835284528552865287528852895290529152925293529452955296529752985299530053015302530353045305530653075308530953105311531253135314531553165317531853195320532153225323532453255326532753285329533053315332533353345335533653375338533953405341534253435344534553465347534853495350535153525353535453555356535753585359536053615362536353645365536653675368536953705371537253735374537553765377537853795380538153825383538453855386538753885389539053915392539353945395539653975398539954005401540254035404540554065407540854095410541154125413541454155416541754185419542054215422542354245425542654275428542954305431543254335434543554365437543854395440544154425443544454455446544754485449545054515452545354545455545654575458545954605461546254635464546554665467546854695470547154725473547454755476547754785479548054815482548354845485548654875488548954905491549254935494549554965497549854995500550155025503550455055506550755085509551055115512551355145515551655175518551955205521552255235524552555265527552855295530553155325533553455355536553755385539554055415542554355445545554655475548554955505551555255535554555555565557555855595560556155625563556455655566556755685569557055715572557355745575557655775578557955805581558255835584558555865587558855895590559155925593559455955596559755985599560056015602560356045605560656075608560956105611561256135614561556165617561856195620562156225623562456255626562756285629563056315632563356345635563656375638563956405641564256435644564556465647564856495650565156525653565456555656565756585659566056615662566356645665566656675668566956705671567256735674567556765677567856795680568156825683568456855686568756885689569056915692569356945695569656975698569957005701570257035704570557065707570857095710571157125713571457155716571757185719572057215722572357245725572657275728572957305731573257335734573557365737573857395740574157425743574457455746574757485749575057515752575357545755575657575758575957605761576257635764576557665767576857695770577157725773577457755776577757785779578057815782578357845785578657875788578957905791579257935794579557965797579857995800580158025803580458055806580758085809581058115812581358145815581658175818581958205821582258235824582558265827582858295830583158325833583458355836583758385839584058415842584358445845584658475848584958505851585258535854585558565857585858595860586158625863586458655866586758685869587058715872587358745875587658775878587958805881588258835884588558865887588858895890589158925893589458955896589758985899590059015902590359045905590659075908590959105911591259135914591559165917591859195920592159225923592459255926592759285929593059315932593359345935593659375938593959405941594259435944594559465947594859495950595159525953595459555956595759585959596059615962596359645965596659675968596959705971597259735974597559765977597859795980598159825983598459855986598759885989599059915992599359945995599659975998599960006001600260036004600560066007600860096010601160126013601460156016601760186019602060216022602360246025602660276028602960306031603260336034603560366037603860396040604160426043604460456046604760486049605060516052605360546055605660576058605960606061606260636064606560666067606860696070607160726073607460756076607760786079608060816082608360846085608660876088608960906091609260936094609560966097609860996100610161026103610461056106610761086109611061116112611361146115611661176118611961206121612261236124612561266127612861296130613161326133613461356136613761386139614061416142614361446145614661476148614961506151615261536154615561566157615861596160616161626163616461656166616761686169617061716172617361746175617661776178617961806181618261836184618561866187618861896190619161926193619461956196619761986199620062016202620362046205620662076208620962106211621262136214621562166217621862196220622162226223622462256226622762286229623062316232623362346235623662376238623962406241624262436244624562466247624862496250625162526253625462556256625762586259626062616262626362646265626662676268626962706271627262736274627562766277627862796280628162826283628462856286628762886289629062916292629362946295629662976298629963006301630263036304630563066307630863096310631163126313631463156316631763186319632063216322632363246325632663276328632963306331633263336334633563366337633863396340634163426343634463456346634763486349635063516352635363546355635663576358635963606361636263636364636563666367636863696370637163726373637463756376637763786379638063816382638363846385638663876388638963906391639263936394639563966397639863996400640164026403640464056406640764086409641064116412641364146415641664176418641964206421642264236424642564266427642864296430643164326433643464356436643764386439644064416442644364446445644664476448644964506451645264536454645564566457645864596460646164626463646464656466646764686469647064716472647364746475647664776478647964806481648264836484648564866487648864896490649164926493649464956496649764986499650065016502650365046505650665076508650965106511651265136514651565166517651865196520652165226523652465256526652765286529653065316532653365346535653665376538653965406541654265436544654565466547654865496550655165526553655465556556655765586559656065616562656365646565656665676568656965706571657265736574657565766577657865796580658165826583658465856586658765886589659065916592659365946595659665976598659966006601660266036604660566066607660866096610661166126613661466156616661766186619662066216622662366246625662666276628662966306631663266336634663566366637663866396640664166426643664466456646664766486649665066516652665366546655665666576658665966606661666266636664666566666667666866696670667166726673667466756676667766786679668066816682668366846685668666876688668966906691669266936694669566966697669866996700670167026703670467056706670767086709671067116712671367146715671667176718671967206721672267236724672567266727672867296730673167326733673467356736673767386739674067416742674367446745674667476748674967506751675267536754675567566757675867596760676167626763676467656766676767686769677067716772677367746775677667776778677967806781678267836784678567866787678867896790679167926793679467956796679767986799680068016802680368046805680668076808680968106811681268136814681568166817681868196820682168226823682468256826682768286829683068316832683368346835683668376838683968406841684268436844684568466847684868496850685168526853685468556856685768586859686068616862686368646865686668676868686968706871687268736874687568766877687868796880688168826883688468856886688768886889689068916892689368946895689668976898689969006901690269036904690569066907690869096910691169126913691469156916691769186919692069216922692369246925692669276928692969306931693269336934693569366937693869396940694169426943694469456946694769486949695069516952695369546955695669576958695969606961696269636964696569666967696869696970697169726973697469756976697769786979698069816982698369846985698669876988698969906991699269936994699569966997699869997000700170027003700470057006700770087009701070117012701370147015701670177018701970207021702270237024702570267027702870297030703170327033703470357036703770387039704070417042704370447045704670477048704970507051705270537054705570567057705870597060706170627063706470657066706770687069707070717072707370747075707670777078707970807081708270837084708570867087708870897090709170927093709470957096709770987099710071017102710371047105710671077108710971107111711271137114711571167117711871197120712171227123712471257126712771287129713071317132713371347135713671377138713971407141714271437144714571467147714871497150715171527153715471557156715771587159716071617162716371647165716671677168716971707171717271737174717571767177717871797180718171827183718471857186718771887189719071917192719371947195719671977198719972007201720272037204720572067207720872097210721172127213721472157216721772187219722072217222722372247225722672277228722972307231723272337234723572367237723872397240724172427243724472457246724772487249725072517252725372547255725672577258725972607261726272637264726572667267726872697270727172727273727472757276727772787279728072817282728372847285728672877288728972907291729272937294729572967297729872997300730173027303730473057306730773087309731073117312731373147315731673177318731973207321732273237324732573267327732873297330733173327333733473357336733773387339734073417342734373447345734673477348734973507351735273537354735573567357735873597360736173627363736473657366736773687369737073717372737373747375737673777378737973807381738273837384738573867387738873897390739173927393739473957396739773987399740074017402740374047405740674077408740974107411741274137414741574167417741874197420742174227423742474257426742774287429743074317432743374347435743674377438743974407441744274437444744574467447744874497450745174527453745474557456745774587459746074617462746374647465746674677468746974707471747274737474747574767477747874797480748174827483748474857486748774887489749074917492749374947495749674977498749975007501750275037504750575067507750875097510751175127513751475157516751775187519752075217522752375247525752675277528752975307531753275337534753575367537753875397540754175427543754475457546754775487549755075517552755375547555755675577558755975607561756275637564756575667567756875697570757175727573757475757576757775787579758075817582758375847585758675877588758975907591759275937594759575967597759875997600760176027603760476057606760776087609761076117612761376147615761676177618761976207621762276237624762576267627762876297630763176327633763476357636763776387639764076417642764376447645764676477648764976507651765276537654765576567657765876597660766176627663766476657666766776687669767076717672767376747675767676777678767976807681768276837684768576867687768876897690769176927693769476957696769776987699770077017702770377047705770677077708770977107711771277137714771577167717771877197720772177227723772477257726772777287729773077317732773377347735773677377738773977407741774277437744774577467747774877497750775177527753775477557756775777587759776077617762776377647765776677677768776977707771777277737774777577767777777877797780778177827783778477857786778777887789779077917792779377947795779677977798779978007801780278037804780578067807780878097810781178127813781478157816781778187819782078217822782378247825782678277828782978307831783278337834783578367837783878397840784178427843784478457846784778487849785078517852785378547855785678577858785978607861786278637864786578667867786878697870787178727873787478757876787778787879788078817882788378847885788678877888788978907891789278937894789578967897789878997900790179027903790479057906790779087909791079117912791379147915791679177918791979207921792279237924792579267927792879297930793179327933793479357936793779387939794079417942794379447945794679477948794979507951795279537954795579567957795879597960796179627963796479657966796779687969797079717972797379747975797679777978797979807981798279837984798579867987798879897990799179927993799479957996799779987999800080018002800380048005800680078008800980108011801280138014801580168017801880198020802180228023802480258026802780288029803080318032803380348035803680378038803980408041804280438044804580468047804880498050805180528053805480558056805780588059806080618062806380648065806680678068806980708071807280738074807580768077807880798080808180828083808480858086808780888089809080918092809380948095809680978098809981008101810281038104810581068107810881098110811181128113811481158116811781188119812081218122812381248125812681278128812981308131813281338134813581368137813881398140814181428143814481458146814781488149815081518152815381548155815681578158815981608161816281638164816581668167816881698170817181728173817481758176817781788179818081818182818381848185818681878188818981908191819281938194819581968197819881998200820182028203820482058206820782088209821082118212821382148215821682178218821982208221822282238224822582268227822882298230823182328233823482358236823782388239824082418242824382448245824682478248824982508251825282538254825582568257825882598260826182628263826482658266826782688269827082718272827382748275827682778278827982808281828282838284828582868287828882898290829182928293829482958296829782988299830083018302830383048305830683078308830983108311831283138314831583168317831883198320832183228323832483258326832783288329833083318332833383348335833683378338833983408341834283438344834583468347834883498350835183528353835483558356835783588359836083618362836383648365836683678368836983708371837283738374837583768377837883798380838183828383838483858386838783888389839083918392839383948395839683978398839984008401840284038404840584068407840884098410841184128413841484158416841784188419842084218422842384248425842684278428842984308431843284338434843584368437843884398440844184428443844484458446844784488449845084518452845384548455845684578458845984608461846284638464846584668467846884698470847184728473847484758476847784788479848084818482848384848485848684878488848984908491849284938494849584968497849884998500850185028503850485058506850785088509851085118512851385148515851685178518851985208521852285238524852585268527852885298530853185328533853485358536853785388539854085418542854385448545854685478548854985508551855285538554855585568557855885598560856185628563856485658566856785688569857085718572857385748575857685778578857985808581858285838584858585868587858885898590859185928593859485958596859785988599860086018602860386048605860686078608860986108611861286138614861586168617861886198620862186228623862486258626862786288629863086318632863386348635863686378638863986408641864286438644864586468647864886498650865186528653865486558656865786588659866086618662866386648665866686678668866986708671867286738674867586768677867886798680868186828683868486858686868786888689869086918692869386948695869686978698869987008701870287038704870587068707870887098710871187128713871487158716871787188719872087218722872387248725872687278728872987308731873287338734873587368737873887398740874187428743874487458746874787488749875087518752875387548755875687578758875987608761876287638764876587668767876887698770877187728773877487758776877787788779878087818782878387848785878687878788878987908791879287938794879587968797879887998800880188028803880488058806880788088809881088118812881388148815881688178818881988208821882288238824882588268827882888298830883188328833883488358836883788388839884088418842884388448845884688478848884988508851885288538854885588568857885888598860886188628863886488658866886788688869887088718872887388748875887688778878887988808881888288838884888588868887888888898890889188928893889488958896889788988899890089018902890389048905890689078908890989108911891289138914891589168917891889198920892189228923892489258926892789288929893089318932893389348935893689378938893989408941894289438944894589468947894889498950895189528953895489558956895789588959896089618962896389648965896689678968896989708971897289738974897589768977897889798980898189828983898489858986898789888989899089918992899389948995899689978998899990009001900290039004900590069007900890099010901190129013901490159016901790189019902090219022902390249025902690279028902990309031903290339034903590369037903890399040904190429043904490459046904790489049905090519052905390549055905690579058905990609061906290639064906590669067906890699070907190729073907490759076907790789079908090819082908390849085908690879088908990909091909290939094909590969097909890999100910191029103910491059106910791089109911091119112911391149115911691179118911991209121912291239124912591269127912891299130913191329133913491359136913791389139914091419142914391449145914691479148914991509151915291539154915591569157915891599160916191629163916491659166916791689169917091719172917391749175917691779178917991809181918291839184918591869187918891899190919191929193919491959196919791989199920092019202920392049205920692079208920992109211921292139214921592169217921892199220922192229223922492259226922792289229923092319232923392349235923692379238923992409241924292439244924592469247924892499250925192529253925492559256925792589259926092619262926392649265926692679268926992709271927292739274927592769277927892799280928192829283928492859286928792889289929092919292929392949295929692979298929993009301930293039304930593069307930893099310931193129313931493159316931793189319932093219322932393249325932693279328932993309331933293339334933593369337933893399340934193429343934493459346934793489349935093519352935393549355935693579358935993609361936293639364936593669367936893699370937193729373937493759376937793789379938093819382938393849385938693879388938993909391939293939394939593969397939893999400940194029403940494059406940794089409941094119412941394149415941694179418941994209421942294239424942594269427942894299430943194329433943494359436943794389439944094419442944394449445944694479448944994509451945294539454945594569457945894599460946194629463946494659466946794689469947094719472947394749475947694779478947994809481948294839484948594869487948894899490949194929493949494959496949794989499950095019502950395049505950695079508950995109511951295139514951595169517951895199520952195229523952495259526952795289529953095319532953395349535953695379538953995409541954295439544954595469547954895499550955195529553955495559556955795589559956095619562956395649565956695679568956995709571957295739574957595769577957895799580958195829583958495859586958795889589959095919592959395949595959695979598959996009601960296039604960596069607960896099610961196129613961496159616961796189619962096219622962396249625962696279628962996309631963296339634963596369637963896399640964196429643964496459646964796489649965096519652965396549655965696579658965996609661966296639664966596669667966896699670967196729673967496759676967796789679968096819682968396849685968696879688968996909691969296939694969596969697969896999700970197029703970497059706970797089709971097119712971397149715971697179718971997209721972297239724972597269727972897299730973197329733973497359736973797389739974097419742974397449745974697479748974997509751975297539754975597569757975897599760976197629763976497659766976797689769977097719772977397749775977697779778977997809781978297839784978597869787978897899790979197929793979497959796979797989799980098019802980398049805980698079808980998109811981298139814981598169817981898199820982198229823982498259826982798289829983098319832983398349835983698379838983998409841984298439844984598469847984898499850985198529853985498559856985798589859986098619862986398649865986698679868986998709871987298739874987598769877987898799880988198829883988498859886988798889889989098919892989398949895989698979898989999009901990299039904990599069907990899099910991199129913991499159916991799189919992099219922992399249925992699279928992999309931993299339934993599369937993899399940994199429943994499459946994799489949995099519952995399549955995699579958995999609961996299639964996599669967996899699970997199729973997499759976997799789979998099819982998399849985998699879988998999909991999299939994999599969997999899991000010001100021000310004100051000610007100081000910010100111001210013100141001510016100171001810019100201002110022100231002410025100261002710028100291003010031100321003310034100351003610037100381003910040100411004210043100441004510046100471004810049100501005110052100531005410055100561005710058100591006010061100621006310064100651006610067100681006910070100711007210073100741007510076100771007810079100801008110082100831008410085100861008710088100891009010091100921009310094100951009610097100981009910100101011010210103101041010510106101071010810109101101011110112101131011410115101161011710118101191012010121101221012310124101251012610127101281012910130101311013210133101341013510136101371013810139101401014110142101431014410145101461014710148101491015010151101521015310154101551015610157101581015910160101611016210163101641016510166101671016810169101701017110172101731017410175101761017710178101791018010181101821018310184101851018610187101881018910190101911019210193101941019510196101971019810199102001020110202102031020410205102061020710208102091021010211102121021310214102151021610217102181021910220102211022210223102241022510226102271022810229102301023110232102331023410235102361023710238102391024010241102421024310244102451024610247102481024910250102511025210253102541025510256102571025810259102601026110262102631026410265102661026710268102691027010271102721027310274102751027610277102781027910280102811028210283102841028510286102871028810289102901029110292102931029410295102961029710298102991030010301103021030310304103051030610307103081030910310103111031210313103141031510316103171031810319103201032110322103231032410325103261032710328103291033010331103321033310334103351033610337103381033910340103411034210343103441034510346103471034810349103501035110352103531035410355103561035710358103591036010361103621036310364103651036610367103681036910370103711037210373103741037510376103771037810379103801038110382103831038410385103861038710388103891039010391103921039310394103951039610397103981039910400104011040210403104041040510406104071040810409104101041110412104131041410415104161041710418104191042010421104221042310424104251042610427104281042910430104311043210433104341043510436104371043810439104401044110442104431044410445104461044710448104491045010451104521045310454104551045610457104581045910460104611046210463104641046510466104671046810469104701047110472104731047410475104761047710478104791048010481104821048310484104851048610487104881048910490104911049210493104941049510496104971049810499105001050110502105031050410505105061050710508105091051010511105121051310514105151051610517105181051910520105211052210523105241052510526105271052810529105301053110532105331053410535105361053710538105391054010541105421054310544105451054610547105481054910550105511055210553105541055510556105571055810559105601056110562105631056410565105661056710568105691057010571105721057310574105751057610577105781057910580105811058210583105841058510586105871058810589105901059110592105931059410595105961059710598105991060010601106021060310604106051060610607106081060910610106111061210613106141061510616106171061810619106201062110622106231062410625106261062710628106291063010631106321063310634106351063610637106381063910640106411064210643106441064510646106471064810649106501065110652106531065410655106561065710658106591066010661106621066310664106651066610667106681066910670106711067210673106741067510676106771067810679106801068110682106831068410685106861068710688106891069010691106921069310694106951069610697106981069910700107011070210703107041070510706107071070810709107101071110712107131071410715107161071710718107191072010721107221072310724107251072610727107281072910730107311073210733107341073510736107371073810739107401074110742107431074410745107461074710748107491075010751107521075310754107551075610757107581075910760107611076210763107641076510766107671076810769107701077110772107731077410775107761077710778107791078010781107821078310784107851078610787107881078910790107911079210793107941079510796107971079810799108001080110802108031080410805108061080710808108091081010811108121081310814108151081610817108181081910820108211082210823108241082510826108271082810829108301083110832108331083410835108361083710838108391084010841108421084310844108451084610847108481084910850108511085210853108541085510856108571085810859108601086110862108631086410865108661086710868108691087010871108721087310874108751087610877108781087910880108811088210883108841088510886108871088810889108901089110892108931089410895108961089710898108991090010901109021090310904109051090610907109081090910910109111091210913109141091510916109171091810919109201092110922109231092410925109261092710928109291093010931109321093310934109351093610937109381093910940109411094210943109441094510946109471094810949109501095110952109531095410955109561095710958109591096010961109621096310964109651096610967109681096910970109711097210973109741097510976109771097810979109801098110982109831098410985109861098710988109891099010991109921099310994109951099610997109981099911000110011100211003110041100511006110071100811009110101101111012110131101411015110161101711018110191102011021110221102311024110251102611027110281102911030110311103211033110341103511036110371103811039110401104111042110431104411045110461104711048110491105011051110521105311054110551105611057110581105911060110611106211063110641106511066110671106811069110701107111072110731107411075110761107711078110791108011081110821108311084110851108611087110881108911090110911109211093110941109511096110971109811099111001110111102111031110411105111061110711108111091111011111111121111311114111151111611117111181111911120111211112211123111241112511126111271112811129111301113111132111331113411135111361113711138111391114011141111421114311144111451114611147111481114911150111511115211153111541115511156111571115811159111601116111162111631116411165111661116711168111691117011171111721117311174111751117611177111781117911180111811118211183111841118511186111871118811189111901119111192111931119411195111961119711198111991120011201112021120311204112051120611207112081120911210112111121211213112141121511216112171121811219112201122111222112231122411225112261122711228112291123011231112321123311234112351123611237112381123911240112411124211243112441124511246112471124811249112501125111252112531125411255112561125711258112591126011261112621126311264112651126611267112681126911270112711127211273112741127511276112771127811279112801128111282112831128411285112861128711288112891129011291112921129311294112951129611297112981129911300113011130211303113041130511306113071130811309113101131111312113131131411315113161131711318113191132011321113221132311324113251132611327113281132911330113311133211333113341133511336113371133811339113401134111342113431134411345113461134711348113491135011351113521135311354113551135611357113581135911360113611136211363113641136511366113671136811369113701137111372113731137411375113761137711378113791138011381113821138311384113851138611387113881138911390113911139211393113941139511396113971139811399114001140111402114031140411405114061140711408114091141011411114121141311414114151141611417114181141911420114211142211423114241142511426114271142811429114301143111432114331143411435114361143711438114391144011441114421144311444114451144611447114481144911450114511145211453114541145511456114571145811459114601146111462114631146411465114661146711468114691147011471114721147311474114751147611477114781147911480114811148211483114841148511486114871148811489114901149111492114931149411495114961149711498114991150011501115021150311504115051150611507115081150911510115111151211513115141151511516115171151811519115201152111522115231152411525115261152711528115291153011531115321153311534115351153611537115381153911540115411154211543115441154511546115471154811549115501155111552115531155411555115561155711558115591156011561115621156311564115651156611567115681156911570115711157211573115741157511576115771157811579115801158111582115831158411585115861158711588115891159011591115921159311594115951159611597115981159911600116011160211603116041160511606116071160811609116101161111612116131161411615116161161711618116191162011621116221162311624116251162611627116281162911630116311163211633116341163511636116371163811639116401164111642116431164411645116461164711648116491165011651116521165311654116551165611657116581165911660116611166211663116641166511666116671166811669116701167111672116731167411675116761167711678116791168011681116821168311684116851168611687116881168911690116911169211693116941169511696116971169811699117001170111702117031170411705117061170711708117091171011711117121171311714117151171611717117181171911720117211172211723117241172511726117271172811729117301173111732117331173411735117361173711738117391174011741117421174311744117451174611747117481174911750117511175211753117541175511756117571175811759117601176111762117631176411765117661176711768117691177011771117721177311774117751177611777117781177911780117811178211783117841178511786117871178811789117901179111792117931179411795117961179711798117991180011801118021180311804118051180611807118081180911810118111181211813118141181511816118171181811819118201182111822118231182411825118261182711828118291183011831118321183311834118351183611837118381183911840118411184211843118441184511846118471184811849118501185111852118531185411855118561185711858118591186011861118621186311864118651186611867118681186911870118711187211873118741187511876118771187811879118801188111882118831188411885118861188711888118891189011891118921189311894118951189611897118981189911900119011190211903119041190511906119071190811909119101191111912119131191411915119161191711918119191192011921119221192311924119251192611927119281192911930119311193211933119341193511936119371193811939119401194111942119431194411945119461194711948119491195011951119521195311954119551195611957119581195911960119611196211963119641196511966119671196811969119701197111972119731197411975119761197711978119791198011981119821198311984119851198611987119881198911990119911199211993119941199511996119971199811999120001200112002120031200412005120061200712008120091201012011120121201312014120151201612017120181201912020120211202212023120241202512026120271202812029120301203112032120331203412035120361203712038120391204012041120421204312044120451204612047120481204912050120511205212053120541205512056120571205812059120601206112062120631206412065120661206712068120691207012071120721207312074120751207612077120781207912080120811208212083120841208512086120871208812089120901209112092120931209412095120961209712098120991210012101121021210312104121051210612107121081210912110121111211212113121141211512116121171211812119121201212112122121231212412125121261212712128121291213012131121321213312134121351213612137121381213912140121411214212143121441214512146121471214812149121501215112152121531215412155121561215712158121591216012161121621216312164121651216612167121681216912170121711217212173121741217512176121771217812179121801218112182121831218412185121861218712188121891219012191121921219312194121951219612197121981219912200122011220212203122041220512206122071220812209122101221112212122131221412215122161221712218122191222012221122221222312224122251222612227122281222912230122311223212233122341223512236122371223812239122401224112242122431224412245122461224712248122491225012251122521225312254122551225612257122581225912260122611226212263122641226512266122671226812269122701227112272122731227412275122761227712278122791228012281122821228312284122851228612287122881228912290122911229212293122941229512296122971229812299123001230112302123031230412305123061230712308123091231012311123121231312314123151231612317123181231912320123211232212323123241232512326123271232812329123301233112332123331233412335123361233712338123391234012341123421234312344123451234612347123481234912350123511235212353123541235512356123571235812359123601236112362123631236412365123661236712368123691237012371123721237312374123751237612377123781237912380123811238212383123841238512386123871238812389123901239112392123931239412395123961239712398123991240012401124021240312404124051240612407124081240912410124111241212413124141241512416124171241812419124201242112422124231242412425124261242712428124291243012431124321243312434124351243612437124381243912440124411244212443124441244512446124471244812449124501245112452124531245412455124561245712458124591246012461124621246312464124651246612467124681246912470124711247212473124741247512476124771247812479124801248112482124831248412485124861248712488124891249012491124921249312494124951249612497124981249912500125011250212503125041250512506125071250812509125101251112512125131251412515125161251712518125191252012521125221252312524125251252612527125281252912530125311253212533125341253512536125371253812539125401254112542125431254412545125461254712548125491255012551125521255312554125551255612557125581255912560125611256212563125641256512566125671256812569125701257112572125731257412575125761257712578125791258012581125821258312584125851258612587125881258912590125911259212593125941259512596125971259812599126001260112602126031260412605126061260712608126091261012611126121261312614126151261612617126181261912620126211262212623126241262512626126271262812629126301263112632126331263412635126361263712638126391264012641126421264312644126451264612647126481264912650126511265212653126541265512656126571265812659126601266112662126631266412665126661266712668126691267012671126721267312674126751267612677126781267912680126811268212683126841268512686126871268812689126901269112692126931269412695126961269712698126991270012701127021270312704127051270612707127081270912710127111271212713127141271512716127171271812719127201272112722127231272412725127261272712728127291273012731127321273312734127351273612737127381273912740127411274212743127441274512746127471274812749127501275112752127531275412755127561275712758127591276012761127621276312764127651276612767127681276912770127711277212773127741277512776127771277812779127801278112782127831278412785127861278712788127891279012791127921279312794127951279612797127981279912800128011280212803128041280512806128071280812809128101281112812128131281412815128161281712818128191282012821128221282312824128251282612827128281282912830128311283212833128341283512836128371283812839128401284112842128431284412845128461284712848128491285012851128521285312854128551285612857128581285912860128611286212863128641286512866128671286812869128701287112872128731287412875128761287712878128791288012881128821288312884128851288612887128881288912890128911289212893128941289512896128971289812899129001290112902129031290412905129061290712908129091291012911129121291312914129151291612917129181291912920129211292212923129241292512926129271292812929129301293112932129331293412935129361293712938129391294012941129421294312944129451294612947129481294912950129511295212953129541295512956129571295812959129601296112962129631296412965129661296712968129691297012971129721297312974129751297612977129781297912980129811298212983129841298512986129871298812989129901299112992129931299412995129961299712998129991300013001130021300313004130051300613007130081300913010130111301213013130141301513016130171301813019130201302113022130231302413025130261302713028130291303013031130321303313034130351303613037130381303913040130411304213043130441304513046130471304813049130501305113052130531305413055130561305713058130591306013061130621306313064130651306613067130681306913070130711307213073130741307513076130771307813079130801308113082130831308413085130861308713088130891309013091130921309313094130951309613097130981309913100131011310213103131041310513106131071310813109131101311113112131131311413115131161311713118131191312013121131221312313124131251312613127131281312913130131311313213133131341313513136131371313813139131401314113142131431314413145131461314713148131491315013151131521315313154131551315613157131581315913160131611316213163131641316513166131671316813169131701317113172131731317413175131761317713178131791318013181131821318313184131851318613187131881318913190131911319213193131941319513196131971319813199132001320113202132031320413205132061320713208132091321013211132121321313214132151321613217132181321913220132211322213223132241322513226132271322813229132301323113232132331323413235132361323713238132391324013241132421324313244132451324613247132481324913250132511325213253132541325513256132571325813259132601326113262132631326413265132661326713268132691327013271132721327313274132751327613277132781327913280132811328213283132841328513286132871328813289132901329113292132931329413295132961329713298132991330013301133021330313304133051330613307133081330913310133111331213313133141331513316133171331813319133201332113322133231332413325133261332713328133291333013331133321333313334133351333613337133381333913340133411334213343133441334513346133471334813349133501335113352133531335413355133561335713358133591336013361133621336313364133651336613367133681336913370133711337213373133741337513376133771337813379133801338113382133831338413385133861338713388133891339013391133921339313394133951339613397133981339913400134011340213403134041340513406134071340813409134101341113412134131341413415134161341713418134191342013421134221342313424134251342613427134281342913430134311343213433134341343513436134371343813439134401344113442134431344413445134461344713448134491345013451134521345313454134551345613457134581345913460134611346213463134641346513466134671346813469134701347113472134731347413475134761347713478134791348013481134821348313484134851348613487134881348913490134911349213493134941349513496134971349813499135001350113502135031350413505135061350713508135091351013511135121351313514135151351613517135181351913520135211352213523135241352513526135271352813529135301353113532135331353413535135361353713538135391354013541135421354313544135451354613547135481354913550135511355213553135541355513556135571355813559135601356113562135631356413565135661356713568135691357013571135721357313574135751357613577135781357913580135811358213583135841358513586135871358813589135901359113592135931359413595135961359713598135991360013601136021360313604136051360613607136081360913610136111361213613136141361513616136171361813619136201362113622136231362413625136261362713628136291363013631136321363313634136351363613637136381363913640136411364213643136441364513646136471364813649136501365113652136531365413655136561365713658136591366013661136621366313664136651366613667136681366913670136711367213673136741367513676136771367813679136801368113682136831368413685136861368713688136891369013691136921369313694136951369613697136981369913700137011370213703137041370513706137071370813709137101371113712137131371413715137161371713718137191372013721137221372313724137251372613727137281372913730137311373213733137341373513736137371373813739137401374113742137431374413745137461374713748137491375013751137521375313754137551375613757137581375913760137611376213763137641376513766137671376813769137701377113772137731377413775137761377713778137791378013781137821378313784137851378613787137881378913790137911379213793137941379513796137971379813799138001380113802138031380413805138061380713808138091381013811138121381313814138151381613817138181381913820138211382213823138241382513826138271382813829138301383113832138331383413835138361383713838138391384013841138421384313844138451384613847138481384913850138511385213853138541385513856138571385813859138601386113862138631386413865138661386713868138691387013871138721387313874138751387613877138781387913880138811388213883138841388513886138871388813889138901389113892138931389413895138961389713898138991390013901139021390313904139051390613907139081390913910139111391213913139141391513916139171391813919139201392113922139231392413925139261392713928139291393013931139321393313934139351393613937139381393913940139411394213943139441394513946139471394813949139501395113952139531395413955139561395713958139591396013961139621396313964139651396613967139681396913970139711397213973139741397513976139771397813979139801398113982139831398413985139861398713988139891399013991139921399313994139951399613997139981399914000140011400214003140041400514006140071400814009140101401114012140131401414015140161401714018140191402014021140221402314024140251402614027140281402914030140311403214033140341403514036140371403814039140401404114042140431404414045140461404714048140491405014051140521405314054140551405614057140581405914060140611406214063140641406514066140671406814069140701407114072140731407414075140761407714078140791408014081140821408314084140851408614087140881408914090140911409214093140941409514096140971409814099141001410114102141031410414105141061410714108141091411014111141121411314114141151411614117141181411914120141211412214123141241412514126141271412814129141301413114132141331413414135141361413714138141391414014141141421414314144141451414614147141481414914150141511415214153141541415514156141571415814159141601416114162141631416414165141661416714168141691417014171141721417314174141751417614177141781417914180141811418214183141841418514186141871418814189141901419114192141931419414195141961419714198141991420014201142021420314204142051420614207142081420914210142111421214213142141421514216142171421814219142201422114222142231422414225142261422714228142291423014231142321423314234142351423614237142381423914240142411424214243142441424514246142471424814249142501425114252142531425414255142561425714258142591426014261142621426314264142651426614267142681426914270142711427214273142741427514276142771427814279142801428114282142831428414285142861428714288142891429014291142921429314294142951429614297142981429914300143011430214303143041430514306143071430814309143101431114312143131431414315143161431714318143191432014321143221432314324143251432614327143281432914330143311433214333143341433514336143371433814339143401434114342143431434414345143461434714348143491435014351143521435314354143551435614357143581435914360143611436214363143641436514366143671436814369143701437114372143731437414375143761437714378143791438014381143821438314384143851438614387143881438914390143911439214393143941439514396143971439814399144001440114402144031440414405144061440714408144091441014411144121441314414144151441614417144181441914420144211442214423144241442514426144271442814429144301443114432144331443414435144361443714438144391444014441144421444314444144451444614447144481444914450144511445214453144541445514456144571445814459144601446114462144631446414465144661446714468144691447014471144721447314474144751447614477144781447914480144811448214483144841448514486144871448814489144901449114492144931449414495144961449714498144991450014501145021450314504145051450614507145081450914510145111451214513145141451514516145171451814519145201452114522145231452414525145261452714528145291453014531145321453314534145351453614537145381453914540145411454214543145441454514546145471454814549145501455114552145531455414555145561455714558145591456014561145621456314564145651456614567145681456914570145711457214573145741457514576145771457814579145801458114582145831458414585145861458714588145891459014591145921459314594145951459614597145981459914600146011460214603146041460514606146071460814609146101461114612146131461414615146161461714618146191462014621146221462314624146251462614627146281462914630146311463214633146341463514636146371463814639146401464114642146431464414645146461464714648146491465014651146521465314654146551465614657146581465914660146611466214663146641466514666146671466814669146701467114672146731467414675146761467714678146791468014681146821468314684146851468614687146881468914690146911469214693146941469514696146971469814699147001470114702147031470414705147061470714708147091471014711147121471314714147151471614717147181471914720147211472214723147241472514726147271472814729147301473114732147331473414735147361473714738147391474014741147421474314744147451474614747147481474914750147511475214753147541475514756147571475814759147601476114762147631476414765147661476714768147691477014771147721477314774147751477614777147781477914780147811478214783147841478514786147871478814789147901479114792147931479414795147961479714798147991480014801148021480314804148051480614807148081480914810148111481214813148141481514816148171481814819148201482114822148231482414825148261482714828148291483014831148321483314834148351483614837148381483914840148411484214843148441484514846148471484814849148501485114852148531485414855148561485714858148591486014861148621486314864148651486614867148681486914870148711487214873148741487514876148771487814879148801488114882148831488414885148861488714888148891489014891148921489314894148951489614897148981489914900149011490214903149041490514906149071490814909149101491114912149131491414915149161491714918149191492014921149221492314924149251492614927149281492914930149311493214933149341493514936149371493814939149401494114942149431494414945149461494714948149491495014951149521495314954149551495614957149581495914960149611496214963149641496514966149671496814969149701497114972149731497414975149761497714978149791498014981149821498314984149851498614987149881498914990149911499214993149941499514996149971499814999150001500115002150031500415005150061500715008150091501015011150121501315014150151501615017150181501915020150211502215023150241502515026150271502815029150301503115032150331503415035150361503715038150391504015041150421504315044150451504615047150481504915050150511505215053150541505515056150571505815059150601506115062150631506415065150661506715068150691507015071150721507315074150751507615077150781507915080150811508215083150841508515086150871508815089150901509115092150931509415095150961509715098150991510015101151021510315104151051510615107151081510915110151111511215113151141511515116151171511815119151201512115122151231512415125151261512715128151291513015131151321513315134151351513615137151381513915140151411514215143151441514515146151471514815149151501515115152151531515415155151561515715158151591516015161151621516315164151651516615167151681516915170151711517215173151741517515176151771517815179151801518115182151831518415185151861518715188151891519015191151921519315194151951519615197151981519915200152011520215203152041520515206152071520815209152101521115212152131521415215152161521715218152191522015221152221522315224152251522615227152281522915230152311523215233152341523515236152371523815239152401524115242152431524415245152461524715248152491525015251152521525315254152551525615257152581525915260152611526215263152641526515266152671526815269152701527115272152731527415275152761527715278152791528015281152821528315284152851528615287152881528915290152911529215293152941529515296152971529815299153001530115302153031530415305153061530715308153091531015311153121531315314153151531615317153181531915320153211532215323153241532515326153271532815329153301533115332153331533415335153361533715338153391534015341153421534315344153451534615347153481534915350153511535215353153541535515356153571535815359153601536115362153631536415365153661536715368153691537015371153721537315374153751537615377153781537915380153811538215383153841538515386153871538815389153901539115392153931539415395153961539715398153991540015401154021540315404154051540615407154081540915410154111541215413154141541515416154171541815419154201542115422154231542415425154261542715428154291543015431154321543315434154351543615437154381543915440154411544215443154441544515446154471544815449154501545115452154531545415455154561545715458154591546015461154621546315464154651546615467154681546915470154711547215473154741547515476154771547815479154801548115482154831548415485154861548715488154891549015491154921549315494154951549615497154981549915500155011550215503155041550515506155071550815509155101551115512155131551415515155161551715518155191552015521155221552315524155251552615527155281552915530155311553215533155341553515536155371553815539155401554115542155431554415545155461554715548155491555015551155521555315554155551555615557155581555915560155611556215563155641556515566155671556815569155701557115572155731557415575155761557715578155791558015581155821558315584155851558615587155881558915590155911559215593155941559515596155971559815599156001560115602156031560415605156061560715608156091561015611156121561315614156151561615617156181561915620156211562215623156241562515626156271562815629156301563115632156331563415635156361563715638156391564015641156421564315644156451564615647156481564915650156511565215653156541565515656156571565815659156601566115662156631566415665156661566715668156691567015671156721567315674156751567615677156781567915680156811568215683156841568515686156871568815689156901569115692156931569415695156961569715698156991570015701157021570315704157051570615707157081570915710157111571215713157141571515716157171571815719157201572115722157231572415725157261572715728157291573015731157321573315734157351573615737157381573915740157411574215743157441574515746157471574815749157501575115752157531575415755157561575715758157591576015761157621576315764157651576615767157681576915770157711577215773157741577515776157771577815779157801578115782157831578415785157861578715788157891579015791157921579315794157951579615797157981579915800158011580215803158041580515806158071580815809158101581115812158131581415815158161581715818158191582015821158221582315824158251582615827158281582915830158311583215833158341583515836158371583815839158401584115842158431584415845158461584715848158491585015851158521585315854158551585615857158581585915860158611586215863158641586515866158671586815869158701587115872158731587415875158761587715878158791588015881158821588315884158851588615887158881588915890158911589215893158941589515896158971589815899159001590115902159031590415905159061590715908159091591015911159121591315914159151591615917159181591915920159211592215923159241592515926159271592815929159301593115932159331593415935159361593715938159391594015941159421594315944159451594615947159481594915950159511595215953159541595515956159571595815959159601596115962159631596415965159661596715968159691597015971159721597315974159751597615977159781597915980159811598215983159841598515986159871598815989159901599115992159931599415995159961599715998159991600016001160021600316004160051600616007160081600916010160111601216013160141601516016160171601816019160201602116022160231602416025160261602716028160291603016031160321603316034160351603616037160381603916040160411604216043160441604516046160471604816049160501605116052160531605416055160561605716058160591606016061160621606316064160651606616067160681606916070160711607216073160741607516076160771607816079160801608116082160831608416085160861608716088160891609016091160921609316094160951609616097160981609916100161011610216103161041610516106161071610816109161101611116112161131611416115161161611716118161191612016121161221612316124161251612616127161281612916130161311613216133161341613516136161371613816139161401614116142161431614416145161461614716148161491615016151161521615316154161551615616157161581615916160161611616216163161641616516166161671616816169161701617116172161731617416175161761617716178161791618016181161821618316184161851618616187161881618916190161911619216193161941619516196161971619816199162001620116202162031620416205162061620716208162091621016211162121621316214162151621616217162181621916220162211622216223162241622516226162271622816229162301623116232162331623416235162361623716238162391624016241162421624316244162451624616247162481624916250162511625216253162541625516256162571625816259162601626116262162631626416265162661626716268162691627016271162721627316274162751627616277162781627916280162811628216283162841628516286162871628816289162901629116292162931629416295162961629716298162991630016301163021630316304163051630616307163081630916310163111631216313163141631516316163171631816319163201632116322163231632416325163261632716328163291633016331163321633316334163351633616337163381633916340163411634216343163441634516346163471634816349163501635116352163531635416355163561635716358163591636016361163621636316364163651636616367163681636916370163711637216373163741637516376163771637816379163801638116382163831638416385163861638716388163891639016391163921639316394163951639616397163981639916400164011640216403164041640516406164071640816409164101641116412164131641416415164161641716418164191642016421164221642316424164251642616427164281642916430164311643216433164341643516436164371643816439164401644116442164431644416445164461644716448164491645016451164521645316454164551645616457164581645916460164611646216463164641646516466164671646816469164701647116472164731647416475164761647716478164791648016481164821648316484164851648616487164881648916490164911649216493164941649516496164971649816499165001650116502165031650416505165061650716508165091651016511165121651316514165151651616517165181651916520165211652216523165241652516526165271652816529165301653116532165331653416535165361653716538165391654016541165421654316544165451654616547165481654916550165511655216553165541655516556165571655816559165601656116562165631656416565165661656716568165691657016571165721657316574165751657616577165781657916580165811658216583165841658516586165871658816589165901659116592165931659416595165961659716598165991660016601166021660316604166051660616607166081660916610166111661216613166141661516616166171661816619166201662116622166231662416625166261662716628166291663016631166321663316634166351663616637166381663916640166411664216643166441664516646166471664816649166501665116652166531665416655166561665716658166591666016661166621666316664166651666616667166681666916670166711667216673166741667516676166771667816679166801668116682166831668416685166861668716688166891669016691166921669316694166951669616697166981669916700167011670216703167041670516706167071670816709167101671116712167131671416715167161671716718167191672016721167221672316724167251672616727167281672916730167311673216733167341673516736167371673816739167401674116742167431674416745167461674716748167491675016751167521675316754167551675616757167581675916760167611676216763167641676516766167671676816769167701677116772167731677416775167761677716778167791678016781167821678316784167851678616787167881678916790167911679216793167941679516796167971679816799168001680116802168031680416805168061680716808168091681016811168121681316814168151681616817168181681916820168211682216823168241682516826168271682816829168301683116832168331683416835168361683716838168391684016841168421684316844168451684616847168481684916850168511685216853168541685516856168571685816859168601686116862168631686416865168661686716868168691687016871168721687316874168751687616877168781687916880168811688216883168841688516886168871688816889168901689116892168931689416895168961689716898168991690016901169021690316904169051690616907169081690916910169111691216913169141691516916169171691816919169201692116922169231692416925169261692716928169291693016931169321693316934169351693616937169381693916940169411694216943169441694516946169471694816949169501695116952169531695416955169561695716958169591696016961169621696316964169651696616967169681696916970169711697216973169741697516976169771697816979169801698116982169831698416985169861698716988169891699016991169921699316994169951699616997169981699917000170011700217003170041700517006170071700817009170101701117012170131701417015170161701717018170191702017021170221702317024170251702617027170281702917030170311703217033170341703517036170371703817039170401704117042170431704417045170461704717048170491705017051170521705317054170551705617057170581705917060170611706217063170641706517066170671706817069170701707117072170731707417075170761707717078170791708017081170821708317084170851708617087170881708917090170911709217093170941709517096170971709817099171001710117102171031710417105171061710717108171091711017111171121711317114171151711617117171181711917120171211712217123171241712517126171271712817129171301713117132171331713417135171361713717138171391714017141171421714317144171451714617147171481714917150171511715217153171541715517156171571715817159171601716117162171631716417165171661716717168171691717017171171721717317174171751717617177171781717917180171811718217183171841718517186171871718817189171901719117192171931719417195171961719717198171991720017201172021720317204172051720617207172081720917210172111721217213172141721517216172171721817219172201722117222172231722417225172261722717228172291723017231172321723317234172351723617237172381723917240172411724217243172441724517246172471724817249172501725117252172531725417255172561725717258172591726017261172621726317264172651726617267172681726917270172711727217273172741727517276172771727817279172801728117282172831728417285172861728717288172891729017291172921729317294172951729617297172981729917300173011730217303173041730517306173071730817309173101731117312173131731417315173161731717318173191732017321173221732317324173251732617327173281732917330173311733217333173341733517336173371733817339173401734117342173431734417345173461734717348173491735017351173521735317354173551735617357173581735917360173611736217363173641736517366173671736817369173701737117372173731737417375173761737717378173791738017381173821738317384173851738617387173881738917390173911739217393173941739517396173971739817399174001740117402174031740417405174061740717408174091741017411174121741317414174151741617417174181741917420174211742217423174241742517426174271742817429174301743117432174331743417435174361743717438174391744017441174421744317444174451744617447174481744917450174511745217453174541745517456174571745817459174601746117462174631746417465174661746717468174691747017471174721747317474174751747617477174781747917480174811748217483174841748517486174871748817489174901749117492174931749417495174961749717498174991750017501175021750317504175051750617507175081750917510175111751217513175141751517516175171751817519175201752117522175231752417525175261752717528175291753017531175321753317534175351753617537175381753917540175411754217543175441754517546175471754817549175501755117552175531755417555175561755717558175591756017561175621756317564175651756617567175681756917570175711757217573175741757517576175771757817579175801758117582175831758417585175861758717588175891759017591175921759317594175951759617597175981759917600176011760217603176041760517606176071760817609176101761117612176131761417615176161761717618176191762017621176221762317624176251762617627176281762917630176311763217633176341763517636176371763817639176401764117642176431764417645176461764717648176491765017651176521765317654176551765617657176581765917660176611766217663176641766517666176671766817669176701767117672176731767417675176761767717678176791768017681176821768317684176851768617687176881768917690176911769217693176941769517696176971769817699177001770117702177031770417705177061770717708177091771017711177121771317714177151771617717177181771917720177211772217723177241772517726177271772817729177301773117732177331773417735177361773717738177391774017741177421774317744177451774617747177481774917750177511775217753177541775517756177571775817759177601776117762177631776417765177661776717768177691777017771177721777317774177751777617777177781777917780177811778217783177841778517786177871778817789177901779117792177931779417795177961779717798177991780017801178021780317804178051780617807178081780917810178111781217813178141781517816178171781817819178201782117822178231782417825178261782717828178291783017831178321783317834178351783617837178381783917840178411784217843178441784517846178471784817849178501785117852178531785417855178561785717858178591786017861178621786317864178651786617867178681786917870178711787217873178741787517876178771787817879178801788117882178831788417885178861788717888178891789017891178921789317894178951789617897178981789917900179011790217903179041790517906179071790817909179101791117912179131791417915179161791717918179191792017921179221792317924179251792617927179281792917930179311793217933179341793517936179371793817939179401794117942179431794417945179461794717948179491795017951179521795317954179551795617957179581795917960179611796217963179641796517966179671796817969179701797117972179731797417975179761797717978179791798017981179821798317984179851798617987179881798917990179911799217993179941799517996179971799817999180001800118002180031800418005180061800718008180091801018011180121801318014180151801618017180181801918020180211802218023180241802518026180271802818029180301803118032180331803418035180361803718038180391804018041180421804318044180451804618047180481804918050180511805218053180541805518056180571805818059180601806118062180631806418065180661806718068180691807018071180721807318074180751807618077180781807918080180811808218083180841808518086180871808818089180901809118092180931809418095180961809718098180991810018101181021810318104181051810618107181081810918110181111811218113181141811518116181171811818119181201812118122181231812418125181261812718128181291813018131181321813318134181351813618137181381813918140181411814218143181441814518146181471814818149181501815118152181531815418155181561815718158181591816018161181621816318164181651816618167181681816918170181711817218173181741817518176181771817818179181801818118182181831818418185181861818718188181891819018191181921819318194181951819618197181981819918200182011820218203182041820518206182071820818209182101821118212182131821418215182161821718218182191822018221182221822318224182251822618227182281822918230182311823218233182341823518236182371823818239182401824118242182431824418245182461824718248182491825018251182521825318254182551825618257182581825918260182611826218263182641826518266182671826818269182701827118272182731827418275182761827718278182791828018281182821828318284182851828618287182881828918290182911829218293182941829518296182971829818299183001830118302183031830418305183061830718308183091831018311183121831318314183151831618317183181831918320183211832218323183241832518326183271832818329183301833118332183331833418335183361833718338183391834018341183421834318344183451834618347183481834918350183511835218353183541835518356183571835818359183601836118362183631836418365183661836718368183691837018371183721837318374183751837618377183781837918380183811838218383183841838518386183871838818389183901839118392183931839418395183961839718398183991840018401184021840318404184051840618407184081840918410184111841218413184141841518416184171841818419184201842118422184231842418425184261842718428184291843018431184321843318434184351843618437184381843918440184411844218443184441844518446184471844818449184501845118452184531845418455184561845718458184591846018461184621846318464184651846618467184681846918470184711847218473184741847518476184771847818479184801848118482184831848418485184861848718488184891849018491184921849318494184951849618497184981849918500185011850218503185041850518506185071850818509185101851118512185131851418515185161851718518185191852018521185221852318524185251852618527185281852918530185311853218533185341853518536185371853818539185401854118542185431854418545185461854718548185491855018551185521855318554185551855618557185581855918560185611856218563185641856518566185671856818569185701857118572185731857418575185761857718578185791858018581185821858318584185851858618587185881858918590185911859218593185941859518596185971859818599186001860118602186031860418605186061860718608186091861018611186121861318614186151861618617186181861918620186211862218623186241862518626186271862818629186301863118632186331863418635186361863718638186391864018641186421864318644186451864618647186481864918650186511865218653186541865518656186571865818659186601866118662186631866418665186661866718668186691867018671186721867318674186751867618677186781867918680186811868218683186841868518686186871868818689186901869118692186931869418695186961869718698186991870018701187021870318704187051870618707187081870918710187111871218713187141871518716187171871818719187201872118722187231872418725187261872718728187291873018731187321873318734187351873618737187381873918740187411874218743187441874518746187471874818749187501875118752187531875418755187561875718758187591876018761187621876318764187651876618767187681876918770187711877218773187741877518776187771877818779187801878118782187831878418785187861878718788187891879018791187921879318794187951879618797187981879918800188011880218803188041880518806188071880818809188101881118812188131881418815188161881718818188191882018821188221882318824188251882618827188281882918830188311883218833188341883518836188371883818839188401884118842188431884418845188461884718848188491885018851188521885318854188551885618857188581885918860188611886218863188641886518866188671886818869188701887118872188731887418875188761887718878188791888018881188821888318884188851888618887188881888918890188911889218893188941889518896188971889818899189001890118902189031890418905189061890718908189091891018911189121891318914189151891618917189181891918920189211892218923189241892518926189271892818929189301893118932189331893418935189361893718938189391894018941189421894318944189451894618947189481894918950189511895218953189541895518956189571895818959189601896118962189631896418965189661896718968189691897018971189721897318974189751897618977189781897918980189811898218983189841898518986189871898818989189901899118992189931899418995189961899718998189991900019001190021900319004190051900619007190081900919010190111901219013190141901519016190171901819019190201902119022190231902419025190261902719028190291903019031190321903319034190351903619037190381903919040190411904219043190441904519046190471904819049190501905119052190531905419055190561905719058190591906019061190621906319064190651906619067190681906919070190711907219073190741907519076190771907819079190801908119082190831908419085190861908719088190891909019091190921909319094190951909619097190981909919100191011910219103191041910519106191071910819109191101911119112191131911419115191161911719118191191912019121191221912319124191251912619127191281912919130191311913219133191341913519136191371913819139191401914119142191431914419145191461914719148191491915019151191521915319154191551915619157191581915919160191611916219163191641916519166191671916819169191701917119172191731917419175191761917719178191791918019181191821918319184191851918619187191881918919190191911919219193191941919519196191971919819199192001920119202192031920419205192061920719208192091921019211192121921319214192151921619217192181921919220192211922219223192241922519226192271922819229192301923119232192331923419235192361923719238192391924019241192421924319244192451924619247192481924919250192511925219253192541925519256192571925819259192601926119262192631926419265192661926719268192691927019271192721927319274192751927619277192781927919280192811928219283192841928519286192871928819289192901929119292192931929419295192961929719298192991930019301193021930319304193051930619307193081930919310193111931219313193141931519316193171931819319193201932119322193231932419325193261932719328193291933019331193321933319334193351933619337193381933919340193411934219343193441934519346193471934819349193501935119352193531935419355193561935719358193591936019361193621936319364193651936619367193681936919370193711937219373193741937519376193771937819379193801938119382193831938419385193861938719388193891939019391193921939319394193951939619397193981939919400194011940219403194041940519406194071940819409194101941119412194131941419415194161941719418194191942019421194221942319424194251942619427194281942919430194311943219433194341943519436194371943819439194401944119442194431944419445194461944719448194491945019451194521945319454194551945619457194581945919460194611946219463194641946519466194671946819469194701947119472194731947419475194761947719478194791948019481194821948319484194851948619487194881948919490194911949219493194941949519496194971949819499195001950119502195031950419505195061950719508195091951019511195121951319514195151951619517195181951919520195211952219523195241952519526195271952819529195301953119532195331953419535195361953719538195391954019541195421954319544195451954619547195481954919550195511955219553195541955519556195571955819559195601956119562195631956419565195661956719568195691957019571195721957319574195751957619577195781957919580195811958219583195841958519586195871958819589195901959119592195931959419595195961959719598195991960019601196021960319604196051960619607196081960919610196111961219613196141961519616196171961819619196201962119622196231962419625196261962719628196291963019631196321963319634196351963619637196381963919640196411964219643196441964519646196471964819649196501965119652196531965419655196561965719658196591966019661196621966319664196651966619667196681966919670196711967219673196741967519676196771967819679196801968119682196831968419685196861968719688196891969019691196921969319694196951969619697196981969919700197011970219703197041970519706197071970819709197101971119712197131971419715197161971719718197191972019721197221972319724197251972619727197281972919730197311973219733197341973519736197371973819739197401974119742197431974419745197461974719748197491975019751197521975319754197551975619757197581975919760197611976219763197641976519766197671976819769197701977119772197731977419775197761977719778197791978019781197821978319784197851978619787197881978919790197911979219793197941979519796197971979819799198001980119802198031980419805198061980719808198091981019811198121981319814198151981619817198181981919820198211982219823198241982519826198271982819829198301983119832198331983419835198361983719838198391984019841198421984319844198451984619847198481984919850198511985219853198541985519856198571985819859198601986119862198631986419865198661986719868198691987019871198721987319874198751987619877198781987919880198811988219883198841988519886198871988819889198901989119892198931989419895198961989719898198991990019901199021990319904199051990619907199081990919910199111991219913199141991519916199171991819919199201992119922199231992419925199261992719928199291993019931199321993319934199351993619937199381993919940199411994219943199441994519946199471994819949199501995119952199531995419955199561995719958199591996019961199621996319964199651996619967199681996919970199711997219973199741997519976199771997819979199801998119982199831998419985199861998719988199891999019991199921999319994199951999619997199981999920000200012000220003200042000520006200072000820009200102001120012200132001420015200162001720018200192002020021200222002320024200252002620027200282002920030200312003220033200342003520036200372003820039200402004120042200432004420045200462004720048200492005020051200522005320054200552005620057200582005920060200612006220063200642006520066200672006820069200702007120072200732007420075200762007720078200792008020081200822008320084200852008620087200882008920090200912009220093200942009520096200972009820099201002010120102201032010420105201062010720108201092011020111201122011320114201152011620117201182011920120201212012220123201242012520126201272012820129201302013120132201332013420135201362013720138201392014020141201422014320144201452014620147201482014920150201512015220153201542015520156201572015820159201602016120162201632016420165201662016720168201692017020171201722017320174201752017620177201782017920180201812018220183201842018520186201872018820189201902019120192201932019420195201962019720198201992020020201202022020320204202052020620207202082020920210202112021220213202142021520216202172021820219202202022120222202232022420225202262022720228202292023020231202322023320234202352023620237202382023920240202412024220243202442024520246202472024820249202502025120252202532025420255202562025720258202592026020261202622026320264202652026620267202682026920270202712027220273202742027520276202772027820279202802028120282202832028420285202862028720288202892029020291202922029320294202952029620297202982029920300203012030220303203042030520306203072030820309203102031120312203132031420315203162031720318203192032020321203222032320324203252032620327203282032920330203312033220333203342033520336203372033820339203402034120342203432034420345203462034720348203492035020351203522035320354203552035620357203582035920360203612036220363203642036520366203672036820369203702037120372203732037420375203762037720378203792038020381203822038320384203852038620387203882038920390203912039220393203942039520396203972039820399204002040120402204032040420405204062040720408204092041020411204122041320414204152041620417204182041920420204212042220423204242042520426204272042820429204302043120432204332043420435204362043720438204392044020441204422044320444204452044620447204482044920450204512045220453204542045520456204572045820459204602046120462204632046420465204662046720468204692047020471204722047320474204752047620477204782047920480204812048220483204842048520486204872048820489204902049120492204932049420495204962049720498204992050020501205022050320504205052050620507205082050920510205112051220513205142051520516205172051820519205202052120522205232052420525205262052720528205292053020531205322053320534205352053620537205382053920540205412054220543205442054520546205472054820549205502055120552205532055420555205562055720558205592056020561205622056320564205652056620567205682056920570205712057220573205742057520576205772057820579205802058120582205832058420585205862058720588205892059020591205922059320594205952059620597205982059920600206012060220603206042060520606206072060820609206102061120612206132061420615206162061720618206192062020621206222062320624206252062620627206282062920630206312063220633206342063520636206372063820639206402064120642206432064420645206462064720648206492065020651206522065320654206552065620657206582065920660206612066220663206642066520666206672066820669206702067120672206732067420675206762067720678206792068020681206822068320684206852068620687206882068920690206912069220693206942069520696206972069820699207002070120702207032070420705207062070720708207092071020711207122071320714207152071620717207182071920720207212072220723207242072520726207272072820729207302073120732207332073420735207362073720738207392074020741207422074320744207452074620747207482074920750207512075220753207542075520756207572075820759207602076120762207632076420765207662076720768207692077020771207722077320774207752077620777207782077920780207812078220783207842078520786207872078820789207902079120792207932079420795207962079720798207992080020801208022080320804208052080620807208082080920810208112081220813208142081520816208172081820819208202082120822208232082420825208262082720828208292083020831208322083320834208352083620837208382083920840208412084220843208442084520846208472084820849208502085120852208532085420855208562085720858208592086020861208622086320864208652086620867208682086920870208712087220873208742087520876208772087820879208802088120882208832088420885208862088720888208892089020891208922089320894208952089620897208982089920900209012090220903209042090520906209072090820909209102091120912209132091420915209162091720918209192092020921209222092320924209252092620927209282092920930209312093220933209342093520936209372093820939209402094120942209432094420945209462094720948209492095020951209522095320954209552095620957209582095920960209612096220963209642096520966209672096820969209702097120972209732097420975209762097720978209792098020981209822098320984209852098620987209882098920990209912099220993209942099520996209972099820999210002100121002210032100421005210062100721008210092101021011210122101321014210152101621017210182101921020210212102221023210242102521026210272102821029210302103121032210332103421035210362103721038210392104021041210422104321044210452104621047210482104921050210512105221053210542105521056210572105821059210602106121062210632106421065210662106721068210692107021071210722107321074210752107621077210782107921080210812108221083210842108521086210872108821089210902109121092210932109421095210962109721098210992110021101211022110321104211052110621107211082110921110211112111221113211142111521116211172111821119211202112121122211232112421125211262112721128211292113021131211322113321134211352113621137211382113921140211412114221143211442114521146211472114821149211502115121152211532115421155211562115721158211592116021161211622116321164211652116621167211682116921170211712117221173211742117521176211772117821179211802118121182211832118421185211862118721188211892119021191211922119321194211952119621197211982119921200212012120221203212042120521206212072120821209212102121121212212132121421215212162121721218212192122021221212222122321224212252122621227212282122921230212312123221233212342123521236212372123821239212402124121242212432124421245212462124721248212492125021251212522125321254212552125621257212582125921260212612126221263212642126521266212672126821269212702127121272212732127421275212762127721278212792128021281212822128321284212852128621287212882128921290212912129221293212942129521296212972129821299213002130121302213032130421305213062130721308213092131021311213122131321314213152131621317213182131921320213212132221323213242132521326213272132821329213302133121332213332133421335213362133721338213392134021341213422134321344213452134621347213482134921350213512135221353213542135521356213572135821359213602136121362213632136421365213662136721368213692137021371213722137321374213752137621377213782137921380213812138221383213842138521386213872138821389213902139121392213932139421395213962139721398213992140021401214022140321404214052140621407214082140921410214112141221413214142141521416214172141821419214202142121422214232142421425214262142721428214292143021431214322143321434214352143621437214382143921440214412144221443214442144521446214472144821449214502145121452214532145421455214562145721458214592146021461214622146321464214652146621467214682146921470214712147221473214742147521476214772147821479214802148121482214832148421485214862148721488214892149021491214922149321494214952149621497214982149921500215012150221503215042150521506215072150821509215102151121512215132151421515215162151721518215192152021521215222152321524215252152621527215282152921530215312153221533215342153521536215372153821539215402154121542215432154421545215462154721548215492155021551215522155321554215552155621557215582155921560215612156221563215642156521566215672156821569215702157121572215732157421575215762157721578215792158021581215822158321584215852158621587215882158921590215912159221593215942159521596215972159821599216002160121602216032160421605216062160721608216092161021611216122161321614216152161621617216182161921620216212162221623216242162521626216272162821629216302163121632216332163421635216362163721638216392164021641216422164321644216452164621647216482164921650216512165221653216542165521656216572165821659216602166121662216632166421665216662166721668216692167021671216722167321674216752167621677216782167921680216812168221683216842168521686216872168821689216902169121692216932169421695216962169721698216992170021701217022170321704217052170621707217082170921710217112171221713217142171521716217172171821719217202172121722217232172421725217262172721728217292173021731217322173321734217352173621737217382173921740217412174221743217442174521746217472174821749217502175121752217532175421755217562175721758217592176021761217622176321764217652176621767217682176921770217712177221773217742177521776217772177821779217802178121782217832178421785217862178721788217892179021791217922179321794217952179621797217982179921800218012180221803218042180521806218072180821809218102181121812218132181421815218162181721818218192182021821218222182321824218252182621827218282182921830218312183221833218342183521836218372183821839218402184121842218432184421845218462184721848218492185021851218522185321854218552185621857218582185921860218612186221863218642186521866218672186821869218702187121872218732187421875218762187721878218792188021881218822188321884218852188621887218882188921890218912189221893218942189521896218972189821899219002190121902219032190421905219062190721908219092191021911219122191321914219152191621917219182191921920219212192221923219242192521926219272192821929219302193121932219332193421935219362193721938219392194021941219422194321944219452194621947219482194921950219512195221953219542195521956219572195821959219602196121962219632196421965219662196721968219692197021971219722197321974219752197621977219782197921980219812198221983219842198521986219872198821989219902199121992219932199421995219962199721998219992200022001220022200322004220052200622007220082200922010220112201222013220142201522016220172201822019220202202122022220232202422025220262202722028220292203022031220322203322034220352203622037220382203922040220412204222043220442204522046220472204822049220502205122052220532205422055220562205722058220592206022061220622206322064220652206622067220682206922070220712207222073220742207522076220772207822079220802208122082220832208422085220862208722088220892209022091220922209322094220952209622097220982209922100221012210222103221042210522106221072210822109221102211122112221132211422115221162211722118221192212022121221222212322124221252212622127221282212922130221312213222133221342213522136221372213822139221402214122142221432214422145221462214722148221492215022151221522215322154221552215622157221582215922160221612216222163221642216522166221672216822169221702217122172221732217422175221762217722178221792218022181221822218322184221852218622187221882218922190221912219222193221942219522196221972219822199222002220122202222032220422205222062220722208222092221022211222122221322214222152221622217222182221922220222212222222223222242222522226222272222822229222302223122232222332223422235222362223722238222392224022241222422224322244222452224622247222482224922250222512225222253222542225522256222572225822259222602226122262222632226422265222662226722268222692227022271222722227322274222752227622277222782227922280222812228222283222842228522286222872228822289222902229122292222932229422295222962229722298222992230022301223022230322304223052230622307223082230922310223112231222313223142231522316223172231822319223202232122322223232232422325223262232722328223292233022331223322233322334223352233622337223382233922340223412234222343223442234522346223472234822349223502235122352223532235422355223562235722358223592236022361223622236322364223652236622367223682236922370223712237222373223742237522376223772237822379223802238122382223832238422385223862238722388223892239022391223922239322394223952239622397223982239922400224012240222403224042240522406224072240822409224102241122412224132241422415224162241722418224192242022421224222242322424224252242622427224282242922430224312243222433224342243522436224372243822439224402244122442224432244422445224462244722448224492245022451224522245322454224552245622457224582245922460224612246222463224642246522466224672246822469224702247122472224732247422475224762247722478224792248022481224822248322484224852248622487224882248922490224912249222493224942249522496224972249822499225002250122502225032250422505225062250722508225092251022511225122251322514225152251622517225182251922520225212252222523225242252522526225272252822529225302253122532225332253422535225362253722538225392254022541225422254322544225452254622547225482254922550225512255222553225542255522556225572255822559225602256122562225632256422565225662256722568225692257022571225722257322574225752257622577225782257922580225812258222583225842258522586225872258822589225902259122592225932259422595225962259722598225992260022601226022260322604226052260622607226082260922610226112261222613226142261522616226172261822619226202262122622226232262422625226262262722628226292263022631226322263322634226352263622637226382263922640226412264222643226442264522646226472264822649226502265122652226532265422655226562265722658226592266022661226622266322664226652266622667226682266922670226712267222673226742267522676226772267822679226802268122682226832268422685226862268722688226892269022691226922269322694226952269622697226982269922700227012270222703227042270522706227072270822709227102271122712227132271422715227162271722718227192272022721227222272322724227252272622727227282272922730227312273222733227342273522736227372273822739227402274122742227432274422745227462274722748227492275022751227522275322754227552275622757227582275922760227612276222763227642276522766227672276822769227702277122772227732277422775227762277722778227792278022781227822278322784227852278622787227882278922790227912279222793227942279522796227972279822799228002280122802228032280422805228062280722808228092281022811228122281322814228152281622817228182281922820228212282222823228242282522826228272282822829228302283122832228332283422835228362283722838228392284022841228422284322844228452284622847228482284922850228512285222853228542285522856228572285822859228602286122862228632286422865228662286722868228692287022871228722287322874228752287622877228782287922880228812288222883228842288522886228872288822889228902289122892228932289422895228962289722898228992290022901229022290322904229052290622907229082290922910229112291222913229142291522916229172291822919229202292122922229232292422925229262292722928229292293022931229322293322934229352293622937229382293922940229412294222943229442294522946229472294822949229502295122952229532295422955229562295722958229592296022961229622296322964229652296622967229682296922970229712297222973229742297522976229772297822979229802298122982229832298422985229862298722988229892299022991229922299322994229952299622997229982299923000230012300223003230042300523006230072300823009230102301123012230132301423015230162301723018230192302023021230222302323024230252302623027230282302923030230312303223033230342303523036230372303823039230402304123042230432304423045230462304723048230492305023051230522305323054230552305623057230582305923060230612306223063230642306523066230672306823069230702307123072230732307423075230762307723078230792308023081230822308323084230852308623087230882308923090230912309223093230942309523096230972309823099231002310123102231032310423105231062310723108231092311023111231122311323114231152311623117231182311923120231212312223123231242312523126231272312823129231302313123132231332313423135231362313723138231392314023141231422314323144231452314623147231482314923150231512315223153231542315523156231572315823159231602316123162231632316423165231662316723168231692317023171231722317323174231752317623177231782317923180231812318223183231842318523186231872318823189231902319123192231932319423195231962319723198231992320023201232022320323204232052320623207232082320923210232112321223213232142321523216232172321823219232202322123222232232322423225232262322723228232292323023231232322323323234232352323623237232382323923240232412324223243232442324523246232472324823249232502325123252232532325423255232562325723258232592326023261232622326323264232652326623267232682326923270232712327223273232742327523276232772327823279232802328123282232832328423285232862328723288232892329023291232922329323294232952329623297232982329923300233012330223303233042330523306233072330823309233102331123312233132331423315233162331723318233192332023321233222332323324233252332623327233282332923330233312333223333233342333523336233372333823339233402334123342233432334423345233462334723348233492335023351233522335323354233552335623357233582335923360233612336223363233642336523366233672336823369233702337123372233732337423375233762337723378233792338023381233822338323384233852338623387233882338923390233912339223393233942339523396233972339823399234002340123402234032340423405234062340723408234092341023411234122341323414234152341623417234182341923420234212342223423234242342523426234272342823429234302343123432234332343423435234362343723438234392344023441234422344323444234452344623447234482344923450234512345223453234542345523456234572345823459234602346123462234632346423465234662346723468234692347023471234722347323474234752347623477234782347923480234812348223483234842348523486234872348823489234902349123492234932349423495234962349723498234992350023501235022350323504235052350623507235082350923510235112351223513235142351523516235172351823519235202352123522235232352423525235262352723528235292353023531235322353323534235352353623537235382353923540235412354223543235442354523546235472354823549235502355123552235532355423555235562355723558235592356023561235622356323564235652356623567235682356923570235712357223573235742357523576235772357823579235802358123582235832358423585235862358723588235892359023591235922359323594235952359623597235982359923600236012360223603236042360523606236072360823609236102361123612236132361423615236162361723618236192362023621236222362323624236252362623627236282362923630236312363223633236342363523636236372363823639236402364123642236432364423645236462364723648236492365023651236522365323654236552365623657236582365923660236612366223663236642366523666236672366823669236702367123672236732367423675236762367723678236792368023681236822368323684236852368623687236882368923690236912369223693236942369523696236972369823699237002370123702237032370423705237062370723708237092371023711237122371323714237152371623717237182371923720237212372223723237242372523726237272372823729237302373123732237332373423735237362373723738237392374023741237422374323744237452374623747237482374923750237512375223753237542375523756237572375823759237602376123762237632376423765237662376723768237692377023771237722377323774237752377623777237782377923780237812378223783237842378523786237872378823789237902379123792237932379423795237962379723798237992380023801238022380323804238052380623807238082380923810238112381223813238142381523816238172381823819238202382123822238232382423825238262382723828238292383023831238322383323834238352383623837238382383923840238412384223843238442384523846238472384823849238502385123852238532385423855238562385723858238592386023861238622386323864238652386623867238682386923870238712387223873238742387523876238772387823879238802388123882238832388423885238862388723888238892389023891238922389323894238952389623897238982389923900239012390223903239042390523906239072390823909239102391123912239132391423915239162391723918239192392023921239222392323924239252392623927239282392923930239312393223933239342393523936239372393823939239402394123942239432394423945239462394723948239492395023951239522395323954239552395623957239582395923960239612396223963239642396523966239672396823969239702397123972239732397423975239762397723978239792398023981239822398323984239852398623987239882398923990239912399223993239942399523996239972399823999240002400124002240032400424005240062400724008240092401024011240122401324014240152401624017240182401924020240212402224023240242402524026240272402824029240302403124032240332403424035240362403724038240392404024041240422404324044240452404624047240482404924050240512405224053240542405524056240572405824059240602406124062240632406424065240662406724068240692407024071240722407324074240752407624077240782407924080240812408224083240842408524086240872408824089240902409124092240932409424095240962409724098240992410024101241022410324104241052410624107241082410924110241112411224113241142411524116241172411824119241202412124122241232412424125241262412724128241292413024131241322413324134241352413624137241382413924140241412414224143241442414524146241472414824149241502415124152241532415424155241562415724158241592416024161241622416324164241652416624167241682416924170241712417224173241742417524176241772417824179241802418124182241832418424185241862418724188241892419024191241922419324194241952419624197241982419924200242012420224203242042420524206242072420824209242102421124212242132421424215242162421724218242192422024221242222422324224242252422624227242282422924230242312423224233242342423524236242372423824239242402424124242242432424424245242462424724248242492425024251242522425324254242552425624257242582425924260242612426224263242642426524266242672426824269242702427124272242732427424275242762427724278242792428024281242822428324284242852428624287242882428924290242912429224293242942429524296242972429824299243002430124302243032430424305243062430724308243092431024311243122431324314243152431624317243182431924320243212432224323243242432524326243272432824329243302433124332243332433424335243362433724338243392434024341243422434324344243452434624347243482434924350243512435224353243542435524356243572435824359243602436124362243632436424365243662436724368243692437024371243722437324374243752437624377243782437924380243812438224383243842438524386243872438824389243902439124392243932439424395243962439724398243992440024401244022440324404244052440624407244082440924410244112441224413244142441524416244172441824419244202442124422244232442424425244262442724428244292443024431244322443324434244352443624437244382443924440244412444224443244442444524446244472444824449244502445124452244532445424455244562445724458244592446024461244622446324464244652446624467244682446924470244712447224473244742447524476244772447824479244802448124482244832448424485244862448724488244892449024491244922449324494244952449624497244982449924500245012450224503245042450524506245072450824509245102451124512245132451424515245162451724518245192452024521245222452324524245252452624527245282452924530245312453224533245342453524536245372453824539245402454124542245432454424545245462454724548245492455024551245522455324554245552455624557245582455924560245612456224563245642456524566245672456824569245702457124572245732457424575245762457724578245792458024581245822458324584245852458624587245882458924590245912459224593245942459524596245972459824599246002460124602246032460424605246062460724608246092461024611246122461324614246152461624617246182461924620246212462224623246242462524626246272462824629246302463124632246332463424635246362463724638246392464024641246422464324644246452464624647246482464924650246512465224653246542465524656246572465824659246602466124662246632466424665246662466724668246692467024671246722467324674246752467624677246782467924680246812468224683246842468524686246872468824689246902469124692246932469424695246962469724698246992470024701247022470324704247052470624707247082470924710247112471224713247142471524716247172471824719247202472124722247232472424725247262472724728247292473024731247322473324734247352473624737247382473924740247412474224743247442474524746247472474824749247502475124752247532475424755247562475724758247592476024761247622476324764247652476624767247682476924770247712477224773247742477524776247772477824779247802478124782247832478424785247862478724788247892479024791247922479324794247952479624797247982479924800248012480224803248042480524806248072480824809248102481124812248132481424815248162481724818248192482024821248222482324824248252482624827248282482924830248312483224833248342483524836248372483824839248402484124842248432484424845248462484724848248492485024851248522485324854248552485624857248582485924860248612486224863248642486524866248672486824869248702487124872248732487424875248762487724878248792488024881248822488324884248852488624887248882488924890248912489224893248942489524896248972489824899249002490124902249032490424905249062490724908249092491024911249122491324914249152491624917249182491924920249212492224923249242492524926249272492824929249302493124932249332493424935249362493724938249392494024941249422494324944249452494624947249482494924950249512495224953249542495524956249572495824959249602496124962249632496424965249662496724968249692497024971249722497324974249752497624977249782497924980249812498224983249842498524986249872498824989249902499124992249932499424995249962499724998249992500025001250022500325004250052500625007250082500925010250112501225013250142501525016250172501825019250202502125022250232502425025250262502725028250292503025031250322503325034250352503625037250382503925040250412504225043250442504525046250472504825049250502505125052250532505425055250562505725058250592506025061250622506325064250652506625067250682506925070250712507225073250742507525076250772507825079250802508125082250832508425085250862508725088250892509025091250922509325094250952509625097250982509925100251012510225103251042510525106251072510825109251102511125112251132511425115251162511725118251192512025121251222512325124251252512625127251282512925130251312513225133251342513525136251372513825139251402514125142251432514425145251462514725148251492515025151251522515325154251552515625157251582515925160251612516225163251642516525166251672516825169251702517125172251732517425175251762517725178251792518025181251822518325184251852518625187251882518925190251912519225193251942519525196251972519825199252002520125202252032520425205252062520725208252092521025211252122521325214252152521625217252182521925220252212522225223252242522525226252272522825229252302523125232252332523425235252362523725238252392524025241252422524325244252452524625247252482524925250252512525225253252542525525256252572525825259252602526125262252632526425265252662526725268252692527025271252722527325274252752527625277252782527925280252812528225283252842528525286252872528825289252902529125292252932529425295252962529725298252992530025301253022530325304253052530625307253082530925310253112531225313253142531525316253172531825319253202532125322253232532425325253262532725328253292533025331253322533325334253352533625337253382533925340253412534225343253442534525346253472534825349253502535125352253532535425355253562535725358253592536025361253622536325364253652536625367253682536925370253712537225373253742537525376253772537825379253802538125382253832538425385253862538725388253892539025391253922539325394253952539625397253982539925400254012540225403254042540525406254072540825409254102541125412254132541425415254162541725418254192542025421254222542325424254252542625427254282542925430254312543225433254342543525436254372543825439254402544125442254432544425445254462544725448254492545025451254522545325454254552545625457254582545925460254612546225463254642546525466254672546825469254702547125472254732547425475254762547725478254792548025481254822548325484254852548625487254882548925490254912549225493254942549525496254972549825499255002550125502255032550425505255062550725508255092551025511255122551325514255152551625517255182551925520255212552225523255242552525526255272552825529255302553125532255332553425535255362553725538255392554025541255422554325544255452554625547255482554925550255512555225553255542555525556255572555825559255602556125562255632556425565255662556725568255692557025571255722557325574255752557625577255782557925580255812558225583255842558525586255872558825589255902559125592255932559425595255962559725598255992560025601256022560325604256052560625607256082560925610256112561225613256142561525616256172561825619256202562125622256232562425625256262562725628256292563025631256322563325634256352563625637256382563925640256412564225643256442564525646256472564825649256502565125652256532565425655256562565725658256592566025661256622566325664256652566625667256682566925670256712567225673256742567525676256772567825679256802568125682256832568425685256862568725688256892569025691256922569325694256952569625697256982569925700257012570225703257042570525706257072570825709257102571125712257132571425715257162571725718257192572025721257222572325724257252572625727257282572925730257312573225733257342573525736257372573825739257402574125742257432574425745257462574725748257492575025751257522575325754257552575625757257582575925760257612576225763257642576525766257672576825769257702577125772257732577425775257762577725778257792578025781257822578325784257852578625787257882578925790257912579225793257942579525796257972579825799258002580125802258032580425805258062580725808258092581025811258122581325814258152581625817258182581925820258212582225823258242582525826258272582825829258302583125832258332583425835258362583725838258392584025841258422584325844258452584625847258482584925850258512585225853258542585525856258572585825859258602586125862258632586425865258662586725868258692587025871258722587325874258752587625877258782587925880258812588225883258842588525886258872588825889258902589125892258932589425895258962589725898258992590025901259022590325904259052590625907259082590925910259112591225913259142591525916259172591825919259202592125922259232592425925259262592725928259292593025931259322593325934259352593625937259382593925940259412594225943259442594525946259472594825949259502595125952259532595425955259562595725958259592596025961259622596325964259652596625967259682596925970259712597225973259742597525976259772597825979259802598125982259832598425985259862598725988259892599025991259922599325994259952599625997259982599926000260012600226003260042600526006260072600826009260102601126012260132601426015260162601726018260192602026021260222602326024260252602626027260282602926030260312603226033260342603526036260372603826039260402604126042260432604426045260462604726048260492605026051260522605326054260552605626057260582605926060260612606226063260642606526066260672606826069260702607126072260732607426075260762607726078260792608026081260822608326084260852608626087260882608926090260912609226093260942609526096260972609826099261002610126102261032610426105261062610726108261092611026111261122611326114261152611626117261182611926120261212612226123261242612526126261272612826129261302613126132261332613426135261362613726138261392614026141261422614326144261452614626147261482614926150261512615226153261542615526156261572615826159261602616126162261632616426165261662616726168261692617026171261722617326174261752617626177261782617926180261812618226183261842618526186261872618826189261902619126192261932619426195261962619726198261992620026201262022620326204262052620626207262082620926210262112621226213262142621526216262172621826219262202622126222262232622426225262262622726228262292623026231262322623326234262352623626237262382623926240262412624226243262442624526246262472624826249262502625126252262532625426255262562625726258262592626026261262622626326264262652626626267262682626926270262712627226273262742627526276262772627826279262802628126282262832628426285262862628726288262892629026291262922629326294262952629626297262982629926300263012630226303263042630526306263072630826309263102631126312263132631426315263162631726318263192632026321263222632326324263252632626327263282632926330263312633226333263342633526336263372633826339263402634126342263432634426345263462634726348263492635026351263522635326354263552635626357263582635926360263612636226363263642636526366263672636826369263702637126372263732637426375263762637726378263792638026381263822638326384263852638626387263882638926390263912639226393263942639526396263972639826399264002640126402264032640426405264062640726408264092641026411264122641326414264152641626417264182641926420264212642226423264242642526426264272642826429264302643126432264332643426435264362643726438264392644026441264422644326444264452644626447264482644926450264512645226453264542645526456264572645826459264602646126462264632646426465264662646726468264692647026471264722647326474264752647626477264782647926480264812648226483264842648526486264872648826489264902649126492264932649426495264962649726498264992650026501265022650326504265052650626507265082650926510265112651226513265142651526516265172651826519265202652126522265232652426525265262652726528265292653026531265322653326534265352653626537265382653926540265412654226543265442654526546265472654826549265502655126552265532655426555265562655726558265592656026561265622656326564265652656626567265682656926570265712657226573265742657526576265772657826579265802658126582265832658426585265862658726588265892659026591265922659326594265952659626597265982659926600266012660226603266042660526606266072660826609266102661126612266132661426615266162661726618266192662026621266222662326624266252662626627266282662926630266312663226633266342663526636266372663826639266402664126642266432664426645266462664726648266492665026651266522665326654266552665626657266582665926660266612666226663266642666526666266672666826669266702667126672266732667426675266762667726678266792668026681266822668326684266852668626687266882668926690266912669226693266942669526696266972669826699267002670126702267032670426705267062670726708267092671026711267122671326714267152671626717267182671926720267212672226723267242672526726267272672826729267302673126732267332673426735267362673726738267392674026741267422674326744267452674626747267482674926750267512675226753267542675526756267572675826759267602676126762267632676426765267662676726768267692677026771267722677326774267752677626777267782677926780267812678226783267842678526786267872678826789267902679126792267932679426795267962679726798267992680026801268022680326804268052680626807268082680926810268112681226813268142681526816268172681826819268202682126822268232682426825268262682726828268292683026831268322683326834268352683626837268382683926840268412684226843268442684526846268472684826849268502685126852268532685426855268562685726858268592686026861268622686326864268652686626867268682686926870268712687226873268742687526876268772687826879268802688126882268832688426885268862688726888268892689026891268922689326894268952689626897268982689926900269012690226903269042690526906269072690826909269102691126912269132691426915269162691726918269192692026921269222692326924269252692626927269282692926930269312693226933269342693526936269372693826939269402694126942269432694426945269462694726948269492695026951269522695326954269552695626957269582695926960269612696226963269642696526966269672696826969269702697126972269732697426975269762697726978269792698026981269822698326984269852698626987269882698926990269912699226993269942699526996269972699826999270002700127002270032700427005270062700727008270092701027011270122701327014270152701627017270182701927020270212702227023270242702527026270272702827029270302703127032270332703427035270362703727038270392704027041270422704327044270452704627047270482704927050270512705227053270542705527056270572705827059270602706127062270632706427065270662706727068270692707027071270722707327074270752707627077270782707927080270812708227083270842708527086270872708827089270902709127092270932709427095270962709727098270992710027101271022710327104271052710627107271082710927110271112711227113271142711527116271172711827119271202712127122271232712427125271262712727128271292713027131271322713327134271352713627137271382713927140271412714227143271442714527146271472714827149271502715127152271532715427155271562715727158271592716027161271622716327164271652716627167271682716927170271712717227173271742717527176271772717827179271802718127182271832718427185271862718727188271892719027191271922719327194271952719627197271982719927200272012720227203272042720527206272072720827209272102721127212272132721427215272162721727218272192722027221272222722327224272252722627227272282722927230272312723227233272342723527236272372723827239272402724127242272432724427245272462724727248272492725027251272522725327254272552725627257272582725927260272612726227263272642726527266272672726827269272702727127272272732727427275272762727727278272792728027281272822728327284272852728627287272882728927290272912729227293272942729527296272972729827299273002730127302273032730427305273062730727308273092731027311273122731327314273152731627317273182731927320273212732227323273242732527326273272732827329273302733127332273332733427335273362733727338273392734027341273422734327344273452734627347273482734927350273512735227353273542735527356273572735827359273602736127362273632736427365273662736727368273692737027371273722737327374273752737627377273782737927380273812738227383273842738527386273872738827389273902739127392273932739427395273962739727398273992740027401274022740327404274052740627407274082740927410274112741227413274142741527416274172741827419274202742127422274232742427425274262742727428274292743027431274322743327434274352743627437274382743927440274412744227443274442744527446274472744827449274502745127452274532745427455274562745727458274592746027461274622746327464274652746627467274682746927470274712747227473274742747527476274772747827479274802748127482274832748427485274862748727488274892749027491274922749327494274952749627497274982749927500275012750227503275042750527506275072750827509275102751127512275132751427515275162751727518275192752027521275222752327524275252752627527275282752927530275312753227533275342753527536275372753827539275402754127542275432754427545275462754727548275492755027551275522755327554275552755627557275582755927560275612756227563275642756527566275672756827569275702757127572275732757427575275762757727578275792758027581275822758327584275852758627587275882758927590275912759227593275942759527596275972759827599276002760127602276032760427605276062760727608276092761027611276122761327614276152761627617276182761927620276212762227623276242762527626276272762827629276302763127632276332763427635276362763727638276392764027641276422764327644276452764627647276482764927650276512765227653276542765527656276572765827659276602766127662276632766427665276662766727668276692767027671276722767327674276752767627677276782767927680276812768227683276842768527686276872768827689276902769127692276932769427695276962769727698276992770027701277022770327704277052770627707277082770927710277112771227713277142771527716277172771827719277202772127722277232772427725277262772727728277292773027731277322773327734277352773627737277382773927740277412774227743277442774527746277472774827749277502775127752277532775427755277562775727758277592776027761277622776327764277652776627767277682776927770277712777227773277742777527776277772777827779277802778127782277832778427785277862778727788277892779027791277922779327794277952779627797277982779927800278012780227803278042780527806278072780827809278102781127812278132781427815278162781727818278192782027821278222782327824278252782627827278282782927830278312783227833278342783527836278372783827839278402784127842278432784427845278462784727848278492785027851278522785327854278552785627857278582785927860278612786227863278642786527866278672786827869278702787127872278732787427875278762787727878278792788027881278822788327884278852788627887278882788927890278912789227893278942789527896278972789827899279002790127902279032790427905279062790727908279092791027911279122791327914279152791627917279182791927920279212792227923279242792527926279272792827929279302793127932279332793427935279362793727938279392794027941279422794327944279452794627947279482794927950279512795227953279542795527956279572795827959279602796127962279632796427965279662796727968279692797027971279722797327974279752797627977279782797927980279812798227983279842798527986279872798827989279902799127992279932799427995279962799727998279992800028001280022800328004280052800628007280082800928010280112801228013280142801528016280172801828019280202802128022280232802428025280262802728028280292803028031280322803328034280352803628037280382803928040280412804228043280442804528046280472804828049280502805128052280532805428055280562805728058280592806028061280622806328064280652806628067280682806928070280712807228073280742807528076280772807828079280802808128082280832808428085280862808728088280892809028091280922809328094280952809628097280982809928100281012810228103281042810528106281072810828109281102811128112281132811428115281162811728118281192812028121281222812328124281252812628127281282812928130281312813228133281342813528136281372813828139281402814128142281432814428145281462814728148281492815028151281522815328154281552815628157281582815928160281612816228163281642816528166281672816828169281702817128172281732817428175281762817728178281792818028181281822818328184281852818628187281882818928190281912819228193281942819528196281972819828199282002820128202282032820428205282062820728208282092821028211282122821328214282152821628217282182821928220282212822228223282242822528226282272822828229282302823128232282332823428235282362823728238282392824028241282422824328244282452824628247282482824928250282512825228253282542825528256282572825828259282602826128262282632826428265282662826728268282692827028271282722827328274282752827628277282782827928280282812828228283282842828528286282872828828289282902829128292282932829428295282962829728298282992830028301283022830328304283052830628307283082830928310283112831228313283142831528316283172831828319283202832128322283232832428325283262832728328283292833028331283322833328334283352833628337283382833928340283412834228343283442834528346283472834828349283502835128352283532835428355283562835728358283592836028361283622836328364283652836628367283682836928370283712837228373283742837528376283772837828379283802838128382283832838428385283862838728388283892839028391283922839328394283952839628397283982839928400284012840228403284042840528406284072840828409284102841128412284132841428415284162841728418284192842028421284222842328424284252842628427284282842928430284312843228433284342843528436284372843828439284402844128442284432844428445284462844728448284492845028451284522845328454284552845628457284582845928460284612846228463284642846528466284672846828469284702847128472284732847428475284762847728478284792848028481284822848328484284852848628487284882848928490284912849228493284942849528496284972849828499285002850128502285032850428505285062850728508285092851028511285122851328514285152851628517285182851928520285212852228523285242852528526285272852828529285302853128532285332853428535285362853728538285392854028541285422854328544285452854628547285482854928550285512855228553285542855528556285572855828559285602856128562285632856428565285662856728568285692857028571285722857328574285752857628577285782857928580285812858228583285842858528586285872858828589285902859128592285932859428595285962859728598285992860028601286022860328604286052860628607286082860928610286112861228613286142861528616286172861828619286202862128622286232862428625286262862728628286292863028631286322863328634286352863628637286382863928640286412864228643286442864528646286472864828649286502865128652286532865428655286562865728658286592866028661286622866328664286652866628667286682866928670286712867228673286742867528676286772867828679286802868128682286832868428685286862868728688286892869028691286922869328694286952869628697286982869928700287012870228703287042870528706287072870828709287102871128712287132871428715287162871728718287192872028721287222872328724287252872628727287282872928730287312873228733287342873528736287372873828739287402874128742287432874428745287462874728748287492875028751287522875328754287552875628757287582875928760287612876228763287642876528766287672876828769287702877128772287732877428775287762877728778287792878028781287822878328784287852878628787287882878928790287912879228793287942879528796287972879828799288002880128802288032880428805288062880728808288092881028811288122881328814288152881628817288182881928820288212882228823288242882528826288272882828829288302883128832288332883428835288362883728838288392884028841288422884328844288452884628847288482884928850288512885228853288542885528856288572885828859288602886128862288632886428865288662886728868288692887028871288722887328874288752887628877288782887928880288812888228883288842888528886288872888828889288902889128892288932889428895288962889728898288992890028901289022890328904289052890628907289082890928910289112891228913289142891528916289172891828919289202892128922289232892428925289262892728928289292893028931289322893328934289352893628937289382893928940289412894228943289442894528946289472894828949289502895128952289532895428955289562895728958289592896028961289622896328964289652896628967289682896928970289712897228973289742897528976289772897828979289802898128982289832898428985289862898728988289892899028991289922899328994289952899628997289982899929000290012900229003290042900529006290072900829009290102901129012290132901429015290162901729018290192902029021290222902329024290252902629027290282902929030290312903229033290342903529036290372903829039290402904129042290432904429045290462904729048290492905029051290522905329054290552905629057290582905929060290612906229063290642906529066290672906829069290702907129072290732907429075290762907729078290792908029081290822908329084290852908629087290882908929090290912909229093290942909529096290972909829099291002910129102291032910429105291062910729108291092911029111291122911329114291152911629117291182911929120291212912229123291242912529126291272912829129291302913129132291332913429135291362913729138291392914029141291422914329144291452914629147291482914929150291512915229153291542915529156291572915829159291602916129162291632916429165291662916729168291692917029171291722917329174291752917629177291782917929180291812918229183291842918529186291872918829189291902919129192291932919429195291962919729198291992920029201292022920329204292052920629207292082920929210292112921229213292142921529216292172921829219292202922129222292232922429225292262922729228292292923029231292322923329234292352923629237292382923929240292412924229243292442924529246292472924829249292502925129252292532925429255292562925729258292592926029261292622926329264292652926629267292682926929270292712927229273292742927529276292772927829279292802928129282292832928429285292862928729288292892929029291292922929329294292952929629297292982929929300293012930229303293042930529306293072930829309293102931129312293132931429315293162931729318293192932029321293222932329324293252932629327293282932929330293312933229333293342933529336293372933829339293402934129342293432934429345293462934729348293492935029351293522935329354293552935629357293582935929360293612936229363293642936529366293672936829369293702937129372293732937429375293762937729378293792938029381293822938329384293852938629387293882938929390293912939229393293942939529396293972939829399294002940129402294032940429405294062940729408294092941029411294122941329414294152941629417294182941929420294212942229423294242942529426294272942829429294302943129432294332943429435294362943729438294392944029441294422944329444294452944629447294482944929450294512945229453294542945529456294572945829459294602946129462294632946429465294662946729468294692947029471294722947329474294752947629477294782947929480294812948229483294842948529486294872948829489294902949129492294932949429495294962949729498294992950029501295022950329504295052950629507295082950929510295112951229513295142951529516295172951829519295202952129522295232952429525295262952729528295292953029531295322953329534295352953629537295382953929540295412954229543295442954529546295472954829549295502955129552295532955429555295562955729558295592956029561295622956329564295652956629567295682956929570295712957229573295742957529576295772957829579295802958129582295832958429585295862958729588295892959029591295922959329594295952959629597295982959929600296012960229603296042960529606296072960829609296102961129612296132961429615296162961729618296192962029621296222962329624296252962629627296282962929630296312963229633296342963529636296372963829639296402964129642296432964429645296462964729648296492965029651296522965329654296552965629657296582965929660296612966229663296642966529666296672966829669296702967129672296732967429675296762967729678296792968029681296822968329684296852968629687296882968929690296912969229693296942969529696296972969829699297002970129702297032970429705297062970729708297092971029711297122971329714297152971629717297182971929720297212972229723297242972529726297272972829729297302973129732297332973429735297362973729738297392974029741297422974329744297452974629747297482974929750297512975229753297542975529756297572975829759297602976129762297632976429765297662976729768297692977029771297722977329774297752977629777297782977929780297812978229783297842978529786297872978829789297902979129792297932979429795297962979729798297992980029801298022980329804298052980629807298082980929810298112981229813298142981529816298172981829819298202982129822298232982429825298262982729828298292983029831298322983329834298352983629837298382983929840298412984229843298442984529846298472984829849298502985129852298532985429855298562985729858298592986029861298622986329864298652986629867298682986929870298712987229873298742987529876298772987829879298802988129882298832988429885298862988729888298892989029891298922989329894298952989629897298982989929900299012990229903299042990529906299072990829909299102991129912299132991429915299162991729918299192992029921299222992329924299252992629927299282992929930299312993229933299342993529936299372993829939299402994129942299432994429945299462994729948299492995029951299522995329954299552995629957299582995929960299612996229963299642996529966299672996829969299702997129972299732997429975299762997729978299792998029981299822998329984299852998629987299882998929990299912999229993299942999529996299972999829999300003000130002300033000430005300063000730008300093001030011300123001330014300153001630017300183001930020300213002230023300243002530026300273002830029300303003130032300333003430035300363003730038300393004030041300423004330044300453004630047300483004930050300513005230053300543005530056300573005830059300603006130062300633006430065300663006730068300693007030071300723007330074300753007630077300783007930080300813008230083300843008530086300873008830089300903009130092300933009430095300963009730098300993010030101301023010330104301053010630107301083010930110301113011230113301143011530116301173011830119301203012130122301233012430125301263012730128301293013030131301323013330134301353013630137301383013930140301413014230143301443014530146301473014830149301503015130152301533015430155301563015730158301593016030161301623016330164301653016630167301683016930170301713017230173301743017530176301773017830179301803018130182301833018430185301863018730188301893019030191301923019330194301953019630197301983019930200302013020230203302043020530206302073020830209302103021130212302133021430215302163021730218302193022030221302223022330224302253022630227302283022930230302313023230233302343023530236302373023830239302403024130242302433024430245302463024730248302493025030251302523025330254302553025630257302583025930260302613026230263302643026530266302673026830269302703027130272302733027430275302763027730278302793028030281302823028330284302853028630287302883028930290302913029230293302943029530296302973029830299303003030130302303033030430305303063030730308303093031030311303123031330314303153031630317303183031930320303213032230323303243032530326303273032830329303303033130332303333033430335303363033730338303393034030341303423034330344303453034630347303483034930350303513035230353303543035530356303573035830359303603036130362303633036430365303663036730368303693037030371303723037330374303753037630377303783037930380303813038230383303843038530386303873038830389303903039130392303933039430395303963039730398303993040030401304023040330404304053040630407304083040930410304113041230413304143041530416304173041830419304203042130422304233042430425304263042730428304293043030431304323043330434304353043630437304383043930440304413044230443304443044530446304473044830449304503045130452304533045430455304563045730458304593046030461304623046330464304653046630467304683046930470304713047230473304743047530476304773047830479304803048130482304833048430485304863048730488304893049030491304923049330494304953049630497304983049930500305013050230503305043050530506305073050830509305103051130512305133051430515305163051730518305193052030521305223052330524305253052630527305283052930530305313053230533305343053530536305373053830539305403054130542305433054430545305463054730548305493055030551305523055330554305553055630557305583055930560305613056230563305643056530566305673056830569305703057130572305733057430575305763057730578305793058030581305823058330584305853058630587305883058930590305913059230593305943059530596305973059830599306003060130602306033060430605306063060730608306093061030611306123061330614306153061630617306183061930620306213062230623306243062530626306273062830629306303063130632306333063430635306363063730638306393064030641306423064330644306453064630647306483064930650306513065230653306543065530656306573065830659306603066130662306633066430665306663066730668306693067030671306723067330674306753067630677306783067930680306813068230683306843068530686306873068830689306903069130692306933069430695306963069730698306993070030701307023070330704307053070630707307083070930710307113071230713307143071530716307173071830719307203072130722307233072430725307263072730728307293073030731307323073330734307353073630737307383073930740307413074230743307443074530746307473074830749307503075130752307533075430755307563075730758307593076030761307623076330764307653076630767307683076930770307713077230773307743077530776307773077830779307803078130782307833078430785307863078730788307893079030791307923079330794307953079630797307983079930800308013080230803308043080530806308073080830809308103081130812308133081430815308163081730818308193082030821308223082330824308253082630827308283082930830308313083230833308343083530836308373083830839308403084130842308433084430845308463084730848308493085030851308523085330854308553085630857308583085930860308613086230863308643086530866308673086830869308703087130872308733087430875308763087730878308793088030881308823088330884308853088630887308883088930890308913089230893308943089530896308973089830899309003090130902309033090430905309063090730908309093091030911309123091330914309153091630917309183091930920309213092230923309243092530926309273092830929309303093130932309333093430935309363093730938309393094030941309423094330944309453094630947309483094930950309513095230953309543095530956309573095830959309603096130962309633096430965309663096730968309693097030971309723097330974309753097630977309783097930980309813098230983309843098530986309873098830989309903099130992309933099430995309963099730998309993100031001310023100331004310053100631007310083100931010310113101231013310143101531016310173101831019310203102131022310233102431025310263102731028310293103031031310323103331034310353103631037310383103931040310413104231043310443104531046310473104831049310503105131052310533105431055310563105731058310593106031061310623106331064310653106631067310683106931070310713107231073310743107531076310773107831079310803108131082310833108431085310863108731088310893109031091310923109331094310953109631097310983109931100311013110231103311043110531106311073110831109311103111131112311133111431115311163111731118311193112031121311223112331124311253112631127311283112931130311313113231133311343113531136311373113831139311403114131142311433114431145311463114731148311493115031151311523115331154311553115631157311583115931160311613116231163311643116531166311673116831169311703117131172311733117431175311763117731178311793118031181311823118331184311853118631187311883118931190311913119231193311943119531196311973119831199312003120131202312033120431205312063120731208312093121031211312123121331214312153121631217312183121931220312213122231223312243122531226312273122831229312303123131232312333123431235312363123731238312393124031241312423124331244312453124631247312483124931250312513125231253312543125531256312573125831259312603126131262312633126431265312663126731268312693127031271312723127331274312753127631277312783127931280312813128231283312843128531286312873128831289312903129131292312933129431295312963129731298312993130031301313023130331304313053130631307313083130931310313113131231313313143131531316313173131831319313203132131322313233132431325313263132731328313293133031331313323133331334313353133631337313383133931340313413134231343313443134531346313473134831349313503135131352313533135431355313563135731358313593136031361313623136331364313653136631367313683136931370313713137231373313743137531376313773137831379313803138131382313833138431385313863138731388313893139031391313923139331394313953139631397313983139931400314013140231403314043140531406314073140831409314103141131412314133141431415314163141731418314193142031421314223142331424314253142631427314283142931430314313143231433314343143531436314373143831439314403144131442314433144431445314463144731448314493145031451314523145331454314553145631457314583145931460314613146231463314643146531466314673146831469314703147131472314733147431475314763147731478314793148031481314823148331484314853148631487314883148931490314913149231493314943149531496314973149831499315003150131502315033150431505315063150731508315093151031511315123151331514315153151631517315183151931520315213152231523315243152531526315273152831529315303153131532315333153431535315363153731538315393154031541315423154331544315453154631547315483154931550315513155231553315543155531556315573155831559315603156131562315633156431565315663156731568315693157031571315723157331574315753157631577315783157931580315813158231583315843158531586315873158831589315903159131592315933159431595315963159731598315993160031601316023160331604316053160631607316083160931610316113161231613316143161531616316173161831619316203162131622316233162431625316263162731628316293163031631316323163331634316353163631637316383163931640316413164231643316443164531646316473164831649316503165131652316533165431655316563165731658316593166031661316623166331664316653166631667316683166931670316713167231673316743167531676316773167831679316803168131682316833168431685316863168731688316893169031691316923169331694316953169631697316983169931700317013170231703317043170531706317073170831709317103171131712317133171431715317163171731718317193172031721317223172331724317253172631727317283172931730317313173231733317343173531736317373173831739317403174131742317433174431745317463174731748317493175031751317523175331754317553175631757317583175931760317613176231763317643176531766317673176831769317703177131772317733177431775317763177731778317793178031781317823178331784317853178631787317883178931790317913179231793317943179531796317973179831799318003180131802318033180431805318063180731808318093181031811318123181331814318153181631817318183181931820318213182231823318243182531826318273182831829318303183131832318333183431835318363183731838318393184031841318423184331844318453184631847318483184931850318513185231853318543185531856318573185831859318603186131862318633186431865318663186731868318693187031871318723187331874318753187631877318783187931880318813188231883318843188531886318873188831889318903189131892318933189431895318963189731898318993190031901319023190331904319053190631907319083190931910319113191231913319143191531916319173191831919319203192131922319233192431925319263192731928319293193031931319323193331934319353193631937319383193931940319413194231943319443194531946319473194831949319503195131952319533195431955319563195731958319593196031961319623196331964319653196631967319683196931970319713197231973319743197531976319773197831979319803198131982319833198431985319863198731988319893199031991319923199331994319953199631997319983199932000320013200232003320043200532006320073200832009320103201132012320133201432015320163201732018320193202032021320223202332024320253202632027320283202932030320313203232033320343203532036320373203832039320403204132042320433204432045320463204732048320493205032051320523205332054320553205632057320583205932060320613206232063320643206532066320673206832069320703207132072320733207432075320763207732078320793208032081320823208332084320853208632087320883208932090320913209232093320943209532096320973209832099321003210132102321033210432105321063210732108321093211032111321123211332114321153211632117321183211932120321213212232123321243212532126321273212832129321303213132132321333213432135321363213732138321393214032141321423214332144321453214632147321483214932150321513215232153321543215532156321573215832159321603216132162321633216432165321663216732168321693217032171321723217332174321753217632177321783217932180321813218232183321843218532186321873218832189321903219132192321933219432195321963219732198321993220032201322023220332204322053220632207322083220932210322113221232213322143221532216322173221832219322203222132222322233222432225322263222732228322293223032231322323223332234322353223632237322383223932240322413224232243322443224532246322473224832249322503225132252322533225432255322563225732258322593226032261322623226332264322653226632267322683226932270322713227232273322743227532276322773227832279322803228132282322833228432285322863228732288322893229032291322923229332294322953229632297322983229932300323013230232303323043230532306323073230832309323103231132312323133231432315323163231732318323193232032321323223232332324323253232632327323283232932330323313233232333323343233532336323373233832339323403234132342323433234432345323463234732348323493235032351323523235332354323553235632357323583235932360323613236232363323643236532366323673236832369323703237132372323733237432375323763237732378323793238032381323823238332384323853238632387323883238932390323913239232393323943239532396323973239832399324003240132402324033240432405324063240732408324093241032411324123241332414324153241632417324183241932420324213242232423324243242532426324273242832429324303243132432324333243432435324363243732438324393244032441324423244332444324453244632447324483244932450324513245232453324543245532456324573245832459324603246132462324633246432465324663246732468324693247032471324723247332474324753247632477324783247932480324813248232483324843248532486324873248832489324903249132492324933249432495324963249732498324993250032501325023250332504325053250632507325083250932510325113251232513325143251532516325173251832519325203252132522325233252432525325263252732528325293253032531325323253332534325353253632537325383253932540325413254232543325443254532546325473254832549325503255132552325533255432555325563255732558325593256032561325623256332564325653256632567325683256932570325713257232573325743257532576325773257832579325803258132582325833258432585325863258732588325893259032591325923259332594325953259632597325983259932600326013260232603326043260532606326073260832609326103261132612326133261432615326163261732618326193262032621326223262332624326253262632627326283262932630326313263232633326343263532636326373263832639326403264132642326433264432645326463264732648326493265032651326523265332654326553265632657326583265932660326613266232663326643266532666326673266832669326703267132672326733267432675326763267732678326793268032681326823268332684326853268632687326883268932690326913269232693326943269532696326973269832699327003270132702327033270432705327063270732708327093271032711327123271332714327153271632717327183271932720327213272232723327243272532726327273272832729327303273132732327333273432735327363273732738327393274032741327423274332744327453274632747327483274932750327513275232753327543275532756327573275832759327603276132762327633276432765327663276732768327693277032771327723277332774327753277632777327783277932780327813278232783327843278532786327873278832789327903279132792327933279432795327963279732798327993280032801328023280332804328053280632807328083280932810328113281232813328143281532816328173281832819328203282132822328233282432825328263282732828328293283032831328323283332834328353283632837328383283932840328413284232843328443284532846328473284832849328503285132852328533285432855328563285732858328593286032861328623286332864328653286632867328683286932870328713287232873328743287532876328773287832879328803288132882328833288432885328863288732888328893289032891328923289332894328953289632897328983289932900329013290232903329043290532906329073290832909329103291132912329133291432915329163291732918329193292032921329223292332924329253292632927329283292932930329313293232933329343293532936329373293832939329403294132942329433294432945329463294732948329493295032951329523295332954329553295632957329583295932960329613296232963329643296532966329673296832969329703297132972329733297432975329763297732978329793298032981329823298332984329853298632987329883298932990329913299232993329943299532996329973299832999330003300133002330033300433005330063300733008330093301033011330123301333014330153301633017330183301933020330213302233023330243302533026330273302833029330303303133032330333303433035330363303733038330393304033041330423304333044330453304633047330483304933050330513305233053330543305533056330573305833059330603306133062330633306433065330663306733068330693307033071330723307333074330753307633077330783307933080330813308233083330843308533086330873308833089330903309133092330933309433095330963309733098330993310033101331023310333104331053310633107331083310933110331113311233113331143311533116331173311833119331203312133122331233312433125331263312733128331293313033131331323313333134331353313633137331383313933140331413314233143331443314533146331473314833149331503315133152331533315433155331563315733158331593316033161331623316333164331653316633167331683316933170331713317233173331743317533176331773317833179331803318133182331833318433185331863318733188331893319033191331923319333194331953319633197331983319933200332013320233203332043320533206332073320833209332103321133212332133321433215332163321733218332193322033221332223322333224332253322633227332283322933230332313323233233332343323533236332373323833239332403324133242332433324433245332463324733248332493325033251332523325333254332553325633257332583325933260332613326233263332643326533266332673326833269332703327133272332733327433275332763327733278332793328033281332823328333284332853328633287332883328933290332913329233293332943329533296332973329833299333003330133302333033330433305333063330733308333093331033311333123331333314333153331633317333183331933320333213332233323333243332533326333273332833329333303333133332333333333433335333363333733338333393334033341333423334333344333453334633347333483334933350333513335233353333543335533356333573335833359333603336133362333633336433365333663336733368333693337033371333723337333374333753337633377333783337933380333813338233383333843338533386333873338833389333903339133392333933339433395333963339733398333993340033401334023340333404334053340633407334083340933410334113341233413334143341533416334173341833419334203342133422334233342433425334263342733428334293343033431334323343333434334353343633437334383343933440334413344233443334443344533446334473344833449334503345133452334533345433455334563345733458334593346033461334623346333464334653346633467334683346933470334713347233473334743347533476334773347833479334803348133482334833348433485334863348733488334893349033491334923349333494334953349633497334983349933500335013350233503335043350533506335073350833509335103351133512335133351433515335163351733518335193352033521335223352333524335253352633527335283352933530335313353233533335343353533536335373353833539335403354133542335433354433545335463354733548335493355033551335523355333554335553355633557335583355933560335613356233563335643356533566335673356833569335703357133572335733357433575335763357733578335793358033581335823358333584335853358633587335883358933590335913359233593335943359533596335973359833599336003360133602336033360433605336063360733608336093361033611336123361333614336153361633617336183361933620336213362233623336243362533626336273362833629336303363133632336333363433635336363363733638336393364033641336423364333644336453364633647336483364933650336513365233653336543365533656336573365833659336603366133662336633366433665336663366733668336693367033671336723367333674336753367633677336783367933680336813368233683336843368533686336873368833689336903369133692336933369433695336963369733698336993370033701337023370333704337053370633707337083370933710337113371233713337143371533716337173371833719337203372133722337233372433725337263372733728337293373033731337323373333734337353373633737337383373933740337413374233743337443374533746337473374833749337503375133752337533375433755337563375733758337593376033761337623376333764337653376633767337683376933770337713377233773337743377533776337773377833779337803378133782337833378433785337863378733788337893379033791337923379333794337953379633797337983379933800338013380233803338043380533806338073380833809338103381133812338133381433815338163381733818338193382033821338223382333824338253382633827338283382933830338313383233833338343383533836338373383833839338403384133842338433384433845338463384733848338493385033851338523385333854338553385633857338583385933860338613386233863338643386533866338673386833869338703387133872338733387433875338763387733878338793388033881338823388333884338853388633887338883388933890338913389233893338943389533896338973389833899339003390133902339033390433905339063390733908339093391033911339123391333914339153391633917339183391933920339213392233923339243392533926339273392833929339303393133932339333393433935339363393733938339393394033941339423394333944339453394633947339483394933950339513395233953339543395533956339573395833959339603396133962339633396433965339663396733968339693397033971339723397333974339753397633977339783397933980339813398233983339843398533986339873398833989339903399133992339933399433995339963399733998339993400034001340023400334004340053400634007340083400934010340113401234013340143401534016340173401834019340203402134022340233402434025340263402734028340293403034031340323403334034340353403634037340383403934040340413404234043340443404534046340473404834049340503405134052340533405434055340563405734058340593406034061340623406334064340653406634067340683406934070340713407234073340743407534076340773407834079340803408134082340833408434085340863408734088340893409034091340923409334094340953409634097340983409934100341013410234103341043410534106341073410834109341103411134112341133411434115341163411734118341193412034121341223412334124341253412634127341283412934130341313413234133341343413534136341373413834139341403414134142341433414434145341463414734148341493415034151341523415334154341553415634157341583415934160341613416234163341643416534166341673416834169341703417134172341733417434175341763417734178341793418034181341823418334184341853418634187341883418934190341913419234193341943419534196341973419834199342003420134202342033420434205342063420734208342093421034211342123421334214342153421634217342183421934220342213422234223342243422534226342273422834229342303423134232342333423434235342363423734238342393424034241342423424334244342453424634247342483424934250342513425234253342543425534256342573425834259342603426134262342633426434265342663426734268342693427034271342723427334274342753427634277342783427934280342813428234283342843428534286342873428834289342903429134292342933429434295342963429734298342993430034301343023430334304343053430634307343083430934310343113431234313343143431534316343173431834319343203432134322343233432434325343263432734328343293433034331343323433334334343353433634337343383433934340343413434234343343443434534346343473434834349343503435134352343533435434355343563435734358343593436034361343623436334364343653436634367343683436934370343713437234373343743437534376343773437834379343803438134382343833438434385343863438734388343893439034391343923439334394343953439634397343983439934400344013440234403344043440534406344073440834409344103441134412344133441434415344163441734418344193442034421344223442334424344253442634427344283442934430344313443234433344343443534436344373443834439344403444134442344433444434445344463444734448344493445034451344523445334454344553445634457344583445934460344613446234463344643446534466344673446834469344703447134472344733447434475344763447734478344793448034481344823448334484344853448634487344883448934490344913449234493344943449534496344973449834499345003450134502345033450434505345063450734508345093451034511345123451334514345153451634517345183451934520345213452234523345243452534526345273452834529345303453134532345333453434535345363453734538345393454034541345423454334544345453454634547345483454934550345513455234553345543455534556345573455834559345603456134562345633456434565345663456734568345693457034571345723457334574345753457634577345783457934580345813458234583345843458534586345873458834589345903459134592345933459434595345963459734598345993460034601346023460334604346053460634607346083460934610346113461234613346143461534616346173461834619346203462134622346233462434625346263462734628346293463034631346323463334634346353463634637346383463934640346413464234643346443464534646346473464834649346503465134652346533465434655346563465734658346593466034661346623466334664346653466634667346683466934670346713467234673346743467534676346773467834679346803468134682346833468434685346863468734688346893469034691346923469334694346953469634697346983469934700347013470234703347043470534706347073470834709347103471134712347133471434715347163471734718347193472034721347223472334724347253472634727347283472934730347313473234733347343473534736347373473834739347403474134742347433474434745347463474734748347493475034751347523475334754347553475634757347583475934760347613476234763347643476534766347673476834769347703477134772347733477434775347763477734778347793478034781347823478334784347853478634787347883478934790347913479234793347943479534796347973479834799348003480134802348033480434805348063480734808348093481034811348123481334814348153481634817348183481934820348213482234823348243482534826348273482834829348303483134832348333483434835348363483734838348393484034841348423484334844348453484634847348483484934850348513485234853348543485534856348573485834859348603486134862348633486434865348663486734868348693487034871348723487334874348753487634877348783487934880348813488234883348843488534886348873488834889348903489134892348933489434895348963489734898348993490034901349023490334904349053490634907349083490934910349113491234913349143491534916349173491834919349203492134922349233492434925349263492734928349293493034931349323493334934349353493634937349383493934940349413494234943349443494534946349473494834949349503495134952349533495434955349563495734958349593496034961349623496334964349653496634967349683496934970349713497234973349743497534976349773497834979349803498134982349833498434985349863498734988349893499034991349923499334994349953499634997349983499935000350013500235003350043500535006350073500835009350103501135012350133501435015350163501735018350193502035021350223502335024350253502635027350283502935030350313503235033350343503535036350373503835039350403504135042350433504435045350463504735048350493505035051350523505335054350553505635057350583505935060350613506235063350643506535066350673506835069350703507135072350733507435075350763507735078350793508035081350823508335084350853508635087350883508935090350913509235093350943509535096350973509835099351003510135102351033510435105351063510735108351093511035111351123511335114351153511635117351183511935120351213512235123351243512535126351273512835129351303513135132351333513435135351363513735138351393514035141351423514335144351453514635147351483514935150351513515235153351543515535156351573515835159351603516135162351633516435165351663516735168351693517035171351723517335174351753517635177351783517935180351813518235183351843518535186351873518835189351903519135192351933519435195351963519735198351993520035201352023520335204352053520635207352083520935210352113521235213352143521535216352173521835219352203522135222352233522435225352263522735228352293523035231352323523335234352353523635237352383523935240352413524235243352443524535246352473524835249352503525135252352533525435255352563525735258352593526035261352623526335264352653526635267352683526935270352713527235273352743527535276352773527835279352803528135282352833528435285352863528735288352893529035291352923529335294352953529635297352983529935300353013530235303353043530535306353073530835309353103531135312353133531435315353163531735318353193532035321353223532335324353253532635327353283532935330353313533235333353343533535336353373533835339353403534135342353433534435345353463534735348353493535035351353523535335354353553535635357353583535935360353613536235363353643536535366353673536835369353703537135372353733537435375353763537735378353793538035381353823538335384353853538635387353883538935390353913539235393353943539535396353973539835399354003540135402354033540435405354063540735408354093541035411354123541335414354153541635417354183541935420354213542235423354243542535426354273542835429354303543135432354333543435435354363543735438354393544035441354423544335444354453544635447354483544935450354513545235453354543545535456354573545835459354603546135462354633546435465354663546735468354693547035471354723547335474354753547635477354783547935480354813548235483354843548535486354873548835489354903549135492354933549435495354963549735498354993550035501355023550335504355053550635507355083550935510355113551235513355143551535516355173551835519355203552135522355233552435525355263552735528355293553035531355323553335534355353553635537355383553935540355413554235543355443554535546355473554835549355503555135552355533555435555355563555735558355593556035561355623556335564355653556635567355683556935570355713557235573355743557535576355773557835579355803558135582355833558435585355863558735588355893559035591355923559335594355953559635597355983559935600356013560235603356043560535606356073560835609356103561135612356133561435615356163561735618356193562035621356223562335624356253562635627356283562935630356313563235633356343563535636356373563835639356403564135642356433564435645356463564735648356493565035651356523565335654356553565635657356583565935660356613566235663356643566535666356673566835669356703567135672356733567435675356763567735678356793568035681356823568335684356853568635687356883568935690356913569235693356943569535696356973569835699357003570135702357033570435705357063570735708357093571035711357123571335714357153571635717357183571935720357213572235723357243572535726357273572835729357303573135732357333573435735357363573735738357393574035741357423574335744357453574635747357483574935750357513575235753357543575535756357573575835759357603576135762357633576435765357663576735768357693577035771357723577335774357753577635777357783577935780357813578235783357843578535786357873578835789357903579135792357933579435795357963579735798357993580035801358023580335804358053580635807358083580935810358113581235813358143581535816358173581835819358203582135822358233582435825358263582735828358293583035831358323583335834358353583635837358383583935840358413584235843358443584535846358473584835849358503585135852358533585435855358563585735858358593586035861358623586335864358653586635867358683586935870358713587235873358743587535876358773587835879358803588135882358833588435885358863588735888358893589035891358923589335894358953589635897358983589935900359013590235903359043590535906359073590835909359103591135912359133591435915359163591735918359193592035921359223592335924359253592635927359283592935930359313593235933359343593535936359373593835939359403594135942359433594435945359463594735948359493595035951359523595335954359553595635957359583595935960359613596235963359643596535966359673596835969359703597135972359733597435975359763597735978359793598035981359823598335984359853598635987359883598935990359913599235993359943599535996359973599835999360003600136002360033600436005360063600736008360093601036011360123601336014360153601636017360183601936020360213602236023360243602536026360273602836029360303603136032360333603436035360363603736038360393604036041360423604336044360453604636047360483604936050360513605236053360543605536056360573605836059360603606136062360633606436065360663606736068360693607036071360723607336074360753607636077360783607936080360813608236083360843608536086360873608836089360903609136092360933609436095360963609736098360993610036101361023610336104361053610636107361083610936110361113611236113361143611536116361173611836119361203612136122361233612436125361263612736128361293613036131361323613336134361353613636137361383613936140361413614236143361443614536146361473614836149361503615136152361533615436155361563615736158361593616036161361623616336164361653616636167361683616936170361713617236173361743617536176361773617836179361803618136182361833618436185361863618736188361893619036191361923619336194361953619636197361983619936200362013620236203362043620536206362073620836209362103621136212362133621436215362163621736218362193622036221362223622336224362253622636227362283622936230362313623236233362343623536236362373623836239362403624136242362433624436245362463624736248362493625036251362523625336254362553625636257362583625936260362613626236263362643626536266362673626836269362703627136272362733627436275362763627736278362793628036281362823628336284362853628636287362883628936290362913629236293362943629536296362973629836299363003630136302363033630436305363063630736308363093631036311363123631336314363153631636317363183631936320363213632236323363243632536326363273632836329363303633136332363333633436335363363633736338363393634036341363423634336344363453634636347363483634936350363513635236353363543635536356363573635836359363603636136362363633636436365363663636736368363693637036371363723637336374363753637636377363783637936380363813638236383363843638536386363873638836389363903639136392363933639436395363963639736398363993640036401364023640336404364053640636407364083640936410364113641236413364143641536416364173641836419364203642136422364233642436425364263642736428364293643036431364323643336434364353643636437364383643936440364413644236443364443644536446364473644836449364503645136452364533645436455364563645736458364593646036461364623646336464364653646636467364683646936470364713647236473364743647536476364773647836479364803648136482364833648436485364863648736488364893649036491364923649336494364953649636497364983649936500365013650236503365043650536506365073650836509365103651136512365133651436515365163651736518365193652036521365223652336524365253652636527365283652936530365313653236533365343653536536365373653836539365403654136542365433654436545365463654736548365493655036551365523655336554365553655636557365583655936560365613656236563365643656536566365673656836569365703657136572365733657436575365763657736578365793658036581365823658336584365853658636587365883658936590365913659236593365943659536596365973659836599366003660136602366033660436605366063660736608366093661036611366123661336614366153661636617366183661936620366213662236623366243662536626366273662836629366303663136632366333663436635366363663736638366393664036641366423664336644366453664636647366483664936650366513665236653366543665536656366573665836659366603666136662366633666436665366663666736668366693667036671366723667336674366753667636677366783667936680366813668236683366843668536686366873668836689366903669136692366933669436695366963669736698366993670036701367023670336704367053670636707367083670936710367113671236713367143671536716367173671836719367203672136722367233672436725367263672736728367293673036731367323673336734367353673636737367383673936740367413674236743367443674536746367473674836749367503675136752367533675436755367563675736758367593676036761367623676336764367653676636767367683676936770367713677236773367743677536776367773677836779367803678136782367833678436785367863678736788367893679036791367923679336794367953679636797367983679936800368013680236803368043680536806368073680836809368103681136812368133681436815368163681736818368193682036821368223682336824368253682636827368283682936830368313683236833368343683536836368373683836839368403684136842368433684436845368463684736848368493685036851368523685336854368553685636857368583685936860368613686236863368643686536866368673686836869368703687136872368733687436875368763687736878368793688036881368823688336884368853688636887368883688936890368913689236893368943689536896368973689836899369003690136902369033690436905369063690736908369093691036911369123691336914369153691636917369183691936920369213692236923369243692536926369273692836929369303693136932369333693436935369363693736938369393694036941369423694336944369453694636947369483694936950369513695236953369543695536956369573695836959369603696136962369633696436965369663696736968369693697036971369723697336974369753697636977369783697936980369813698236983369843698536986369873698836989369903699136992369933699436995369963699736998369993700037001370023700337004370053700637007370083700937010370113701237013370143701537016370173701837019370203702137022370233702437025370263702737028370293703037031370323703337034370353703637037370383703937040370413704237043370443704537046370473704837049370503705137052370533705437055370563705737058370593706037061370623706337064370653706637067370683706937070370713707237073370743707537076370773707837079370803708137082370833708437085370863708737088370893709037091370923709337094370953709637097370983709937100371013710237103371043710537106371073710837109371103711137112371133711437115371163711737118371193712037121371223712337124371253712637127371283712937130371313713237133371343713537136371373713837139371403714137142371433714437145371463714737148371493715037151371523715337154371553715637157371583715937160371613716237163371643716537166371673716837169371703717137172371733717437175371763717737178371793718037181371823718337184371853718637187371883718937190371913719237193371943719537196371973719837199372003720137202372033720437205372063720737208372093721037211372123721337214372153721637217372183721937220372213722237223372243722537226372273722837229372303723137232372333723437235372363723737238372393724037241372423724337244372453724637247372483724937250372513725237253372543725537256372573725837259372603726137262372633726437265372663726737268372693727037271372723727337274372753727637277372783727937280372813728237283372843728537286372873728837289372903729137292372933729437295372963729737298372993730037301373023730337304373053730637307373083730937310373113731237313373143731537316373173731837319373203732137322373233732437325373263732737328373293733037331373323733337334373353733637337373383733937340373413734237343373443734537346373473734837349373503735137352373533735437355373563735737358373593736037361373623736337364373653736637367373683736937370373713737237373373743737537376373773737837379373803738137382373833738437385373863738737388373893739037391373923739337394373953739637397373983739937400374013740237403374043740537406374073740837409374103741137412374133741437415374163741737418374193742037421374223742337424374253742637427374283742937430374313743237433374343743537436374373743837439374403744137442374433744437445374463744737448374493745037451374523745337454374553745637457374583745937460374613746237463374643746537466374673746837469374703747137472374733747437475374763747737478374793748037481374823748337484374853748637487374883748937490374913749237493374943749537496374973749837499375003750137502375033750437505375063750737508375093751037511375123751337514375153751637517375183751937520375213752237523375243752537526375273752837529375303753137532375333753437535375363753737538375393754037541375423754337544375453754637547375483754937550375513755237553375543755537556375573755837559375603756137562375633756437565375663756737568375693757037571375723757337574375753757637577375783757937580375813758237583375843758537586375873758837589375903759137592375933759437595375963759737598375993760037601376023760337604376053760637607376083760937610376113761237613376143761537616376173761837619376203762137622376233762437625376263762737628376293763037631376323763337634376353763637637376383763937640376413764237643376443764537646376473764837649376503765137652376533765437655376563765737658376593766037661376623766337664376653766637667376683766937670376713767237673376743767537676376773767837679376803768137682376833768437685376863768737688376893769037691376923769337694376953769637697376983769937700377013770237703377043770537706377073770837709377103771137712377133771437715377163771737718377193772037721377223772337724377253772637727377283772937730377313773237733377343773537736377373773837739377403774137742377433774437745377463774737748377493775037751377523775337754377553775637757377583775937760377613776237763377643776537766377673776837769377703777137772377733777437775377763777737778377793778037781377823778337784377853778637787377883778937790377913779237793377943779537796377973779837799378003780137802378033780437805378063780737808378093781037811378123781337814378153781637817378183781937820378213782237823378243782537826378273782837829378303783137832378333783437835378363783737838378393784037841378423784337844378453784637847378483784937850378513785237853378543785537856378573785837859378603786137862378633786437865378663786737868378693787037871378723787337874378753787637877378783787937880378813788237883378843788537886378873788837889378903789137892378933789437895378963789737898378993790037901379023790337904379053790637907379083790937910379113791237913379143791537916379173791837919379203792137922379233792437925379263792737928379293793037931379323793337934379353793637937379383793937940379413794237943379443794537946379473794837949379503795137952379533795437955379563795737958379593796037961379623796337964379653796637967379683796937970379713797237973379743797537976379773797837979379803798137982379833798437985379863798737988379893799037991379923799337994379953799637997379983799938000380013800238003380043800538006380073800838009380103801138012380133801438015380163801738018380193802038021380223802338024380253802638027380283802938030380313803238033380343803538036380373803838039380403804138042380433804438045380463804738048380493805038051380523805338054380553805638057380583805938060380613806238063380643806538066380673806838069380703807138072380733807438075380763807738078380793808038081380823808338084380853808638087380883808938090380913809238093380943809538096380973809838099381003810138102381033810438105381063810738108381093811038111381123811338114381153811638117381183811938120381213812238123381243812538126381273812838129381303813138132381333813438135381363813738138381393814038141381423814338144381453814638147381483814938150381513815238153381543815538156381573815838159381603816138162381633816438165381663816738168381693817038171381723817338174381753817638177381783817938180381813818238183381843818538186381873818838189381903819138192381933819438195381963819738198381993820038201382023820338204382053820638207382083820938210382113821238213382143821538216382173821838219382203822138222382233822438225382263822738228382293823038231382323823338234382353823638237382383823938240382413824238243382443824538246382473824838249382503825138252382533825438255382563825738258382593826038261382623826338264382653826638267382683826938270382713827238273382743827538276382773827838279382803828138282382833828438285382863828738288382893829038291382923829338294382953829638297382983829938300383013830238303383043830538306383073830838309383103831138312383133831438315383163831738318383193832038321383223832338324383253832638327383283832938330383313833238333383343833538336383373833838339383403834138342383433834438345383463834738348383493835038351383523835338354383553835638357383583835938360383613836238363383643836538366383673836838369383703837138372383733837438375383763837738378383793838038381383823838338384383853838638387383883838938390383913839238393383943839538396383973839838399384003840138402384033840438405384063840738408384093841038411384123841338414384153841638417384183841938420384213842238423384243842538426384273842838429384303843138432384333843438435384363843738438384393844038441384423844338444384453844638447384483844938450384513845238453384543845538456384573845838459384603846138462384633846438465384663846738468384693847038471384723847338474384753847638477384783847938480384813848238483384843848538486384873848838489384903849138492384933849438495384963849738498384993850038501385023850338504385053850638507385083850938510385113851238513385143851538516385173851838519385203852138522385233852438525385263852738528385293853038531385323853338534385353853638537385383853938540385413854238543385443854538546385473854838549385503855138552385533855438555385563855738558385593856038561385623856338564385653856638567385683856938570385713857238573385743857538576385773857838579385803858138582385833858438585385863858738588385893859038591385923859338594385953859638597385983859938600386013860238603386043860538606386073860838609386103861138612386133861438615386163861738618386193862038621386223862338624386253862638627386283862938630386313863238633386343863538636386373863838639386403864138642386433864438645386463864738648386493865038651386523865338654386553865638657386583865938660386613866238663386643866538666386673866838669386703867138672386733867438675386763867738678386793868038681386823868338684386853868638687386883868938690386913869238693386943869538696386973869838699387003870138702387033870438705387063870738708387093871038711387123871338714387153871638717387183871938720387213872238723387243872538726387273872838729387303873138732387333873438735387363873738738387393874038741387423874338744387453874638747387483874938750387513875238753387543875538756387573875838759387603876138762387633876438765387663876738768387693877038771387723877338774387753877638777387783877938780387813878238783387843878538786387873878838789387903879138792387933879438795387963879738798387993880038801388023880338804388053880638807388083880938810388113881238813388143881538816388173881838819388203882138822388233882438825388263882738828388293883038831388323883338834388353883638837388383883938840388413884238843388443884538846388473884838849388503885138852388533885438855388563885738858388593886038861388623886338864388653886638867388683886938870388713887238873388743887538876388773887838879388803888138882388833888438885388863888738888388893889038891388923889338894388953889638897388983889938900389013890238903389043890538906389073890838909389103891138912389133891438915389163891738918389193892038921389223892338924389253892638927389283892938930389313893238933389343893538936389373893838939389403894138942389433894438945389463894738948389493895038951389523895338954389553895638957389583895938960389613896238963389643896538966389673896838969389703897138972389733897438975389763897738978389793898038981389823898338984389853898638987389883898938990389913899238993389943899538996389973899838999390003900139002390033900439005390063900739008390093901039011390123901339014390153901639017390183901939020390213902239023390243902539026390273902839029390303903139032390333903439035390363903739038390393904039041390423904339044390453904639047390483904939050390513905239053390543905539056390573905839059390603906139062390633906439065390663906739068390693907039071390723907339074390753907639077390783907939080390813908239083390843908539086390873908839089390903909139092390933909439095390963909739098390993910039101391023910339104391053910639107391083910939110391113911239113391143911539116391173911839119391203912139122391233912439125391263912739128391293913039131391323913339134391353913639137391383913939140391413914239143391443914539146391473914839149391503915139152391533915439155391563915739158391593916039161391623916339164391653916639167391683916939170391713917239173391743917539176391773917839179391803918139182391833918439185391863918739188391893919039191391923919339194391953919639197391983919939200392013920239203392043920539206392073920839209392103921139212392133921439215392163921739218392193922039221392223922339224392253922639227392283922939230392313923239233392343923539236392373923839239392403924139242392433924439245392463924739248392493925039251392523925339254392553925639257392583925939260392613926239263392643926539266392673926839269392703927139272392733927439275392763927739278392793928039281392823928339284392853928639287392883928939290392913929239293392943929539296392973929839299393003930139302393033930439305393063930739308393093931039311393123931339314393153931639317393183931939320393213932239323393243932539326393273932839329393303933139332393333933439335393363933739338393393934039341393423934339344393453934639347393483934939350393513935239353393543935539356393573935839359393603936139362393633936439365393663936739368393693937039371393723937339374393753937639377393783937939380393813938239383393843938539386393873938839389393903939139392393933939439395393963939739398393993940039401394023940339404394053940639407394083940939410394113941239413394143941539416394173941839419394203942139422394233942439425394263942739428394293943039431394323943339434394353943639437394383943939440394413944239443394443944539446394473944839449394503945139452394533945439455394563945739458394593946039461394623946339464394653946639467394683946939470394713947239473394743947539476394773947839479394803948139482394833948439485394863948739488394893949039491394923949339494394953949639497394983949939500395013950239503395043950539506395073950839509395103951139512395133951439515395163951739518395193952039521395223952339524395253952639527395283952939530395313953239533395343953539536395373953839539395403954139542395433954439545395463954739548395493955039551395523955339554395553955639557395583955939560395613956239563395643956539566395673956839569395703957139572395733957439575395763957739578395793958039581395823958339584395853958639587395883958939590395913959239593395943959539596395973959839599396003960139602396033960439605396063960739608396093961039611396123961339614396153961639617396183961939620396213962239623396243962539626396273962839629396303963139632396333963439635396363963739638396393964039641396423964339644396453964639647396483964939650396513965239653396543965539656396573965839659396603966139662396633966439665396663966739668396693967039671396723967339674396753967639677396783967939680396813968239683396843968539686396873968839689396903969139692396933969439695396963969739698396993970039701397023970339704397053970639707397083970939710397113971239713397143971539716397173971839719397203972139722397233972439725397263972739728397293973039731397323973339734397353973639737397383973939740397413974239743397443974539746397473974839749397503975139752397533975439755397563975739758397593976039761397623976339764397653976639767397683976939770397713977239773397743977539776397773977839779397803978139782397833978439785397863978739788397893979039791397923979339794397953979639797397983979939800398013980239803398043980539806398073980839809398103981139812398133981439815398163981739818398193982039821398223982339824398253982639827398283982939830398313983239833398343983539836398373983839839398403984139842398433984439845398463984739848398493985039851398523985339854398553985639857398583985939860398613986239863398643986539866398673986839869398703987139872398733987439875398763987739878398793988039881398823988339884398853988639887398883988939890398913989239893398943989539896398973989839899399003990139902399033990439905399063990739908399093991039911399123991339914399153991639917399183991939920399213992239923399243992539926399273992839929399303993139932399333993439935399363993739938399393994039941399423994339944399453994639947399483994939950399513995239953399543995539956399573995839959399603996139962399633996439965399663996739968399693997039971399723997339974399753997639977399783997939980399813998239983399843998539986399873998839989399903999139992399933999439995399963999739998399994000040001400024000340004400054000640007400084000940010400114001240013400144001540016400174001840019400204002140022400234002440025400264002740028400294003040031400324003340034400354003640037400384003940040400414004240043400444004540046400474004840049400504005140052400534005440055400564005740058400594006040061400624006340064400654006640067400684006940070400714007240073400744007540076400774007840079400804008140082400834008440085400864008740088400894009040091400924009340094400954009640097400984009940100401014010240103401044010540106401074010840109401104011140112401134011440115401164011740118401194012040121401224012340124401254012640127401284012940130401314013240133401344013540136401374013840139401404014140142401434014440145401464014740148401494015040151401524015340154401554015640157401584015940160401614016240163401644016540166401674016840169401704017140172401734017440175401764017740178401794018040181401824018340184401854018640187401884018940190401914019240193401944019540196401974019840199402004020140202402034020440205402064020740208402094021040211402124021340214402154021640217402184021940220402214022240223402244022540226402274022840229402304023140232402334023440235402364023740238402394024040241402424024340244402454024640247402484024940250402514025240253402544025540256402574025840259402604026140262402634026440265402664026740268402694027040271402724027340274402754027640277402784027940280402814028240283402844028540286402874028840289402904029140292402934029440295402964029740298402994030040301403024030340304403054030640307403084030940310403114031240313403144031540316403174031840319403204032140322403234032440325403264032740328403294033040331403324033340334403354033640337403384033940340403414034240343403444034540346403474034840349403504035140352403534035440355403564035740358403594036040361403624036340364403654036640367403684036940370403714037240373403744037540376403774037840379403804038140382403834038440385403864038740388403894039040391403924039340394403954039640397403984039940400404014040240403404044040540406404074040840409404104041140412404134041440415404164041740418404194042040421404224042340424404254042640427404284042940430404314043240433404344043540436404374043840439404404044140442404434044440445404464044740448404494045040451404524045340454404554045640457404584045940460404614046240463404644046540466404674046840469404704047140472404734047440475404764047740478404794048040481404824048340484404854048640487404884048940490404914049240493404944049540496404974049840499405004050140502405034050440505405064050740508405094051040511405124051340514405154051640517405184051940520405214052240523405244052540526405274052840529405304053140532405334053440535405364053740538405394054040541405424054340544405454054640547405484054940550405514055240553405544055540556405574055840559405604056140562405634056440565405664056740568405694057040571405724057340574405754057640577405784057940580405814058240583405844058540586405874058840589405904059140592405934059440595405964059740598405994060040601406024060340604406054060640607406084060940610406114061240613406144061540616406174061840619406204062140622406234062440625406264062740628406294063040631406324063340634406354063640637406384063940640406414064240643406444064540646406474064840649406504065140652406534065440655406564065740658406594066040661406624066340664406654066640667406684066940670406714067240673406744067540676406774067840679406804068140682406834068440685406864068740688406894069040691406924069340694406954069640697406984069940700407014070240703407044070540706407074070840709407104071140712407134071440715407164071740718407194072040721407224072340724407254072640727407284072940730407314073240733407344073540736407374073840739407404074140742407434074440745407464074740748407494075040751407524075340754407554075640757407584075940760407614076240763407644076540766407674076840769407704077140772407734077440775407764077740778407794078040781407824078340784407854078640787407884078940790407914079240793407944079540796407974079840799408004080140802408034080440805408064080740808408094081040811408124081340814408154081640817408184081940820408214082240823408244082540826408274082840829408304083140832408334083440835408364083740838408394084040841408424084340844408454084640847408484084940850408514085240853408544085540856408574085840859408604086140862408634086440865408664086740868408694087040871408724087340874408754087640877408784087940880408814088240883408844088540886408874088840889408904089140892408934089440895408964089740898408994090040901409024090340904409054090640907409084090940910409114091240913409144091540916409174091840919409204092140922409234092440925409264092740928409294093040931409324093340934409354093640937409384093940940409414094240943409444094540946409474094840949409504095140952409534095440955409564095740958409594096040961409624096340964409654096640967409684096940970409714097240973409744097540976409774097840979409804098140982409834098440985409864098740988409894099040991409924099340994409954099640997409984099941000410014100241003410044100541006410074100841009410104101141012410134101441015410164101741018410194102041021410224102341024410254102641027410284102941030410314103241033410344103541036410374103841039410404104141042410434104441045410464104741048410494105041051410524105341054410554105641057410584105941060410614106241063410644106541066410674106841069410704107141072410734107441075410764107741078410794108041081410824108341084410854108641087410884108941090410914109241093410944109541096410974109841099411004110141102411034110441105411064110741108411094111041111411124111341114411154111641117411184111941120411214112241123411244112541126411274112841129411304113141132411334113441135411364113741138411394114041141411424114341144411454114641147411484114941150411514115241153411544115541156411574115841159411604116141162411634116441165411664116741168411694117041171411724117341174411754117641177411784117941180411814118241183411844118541186411874118841189411904119141192411934119441195411964119741198411994120041201412024120341204412054120641207412084120941210412114121241213412144121541216412174121841219412204122141222412234122441225412264122741228412294123041231412324123341234412354123641237412384123941240412414124241243412444124541246412474124841249412504125141252412534125441255412564125741258412594126041261412624126341264412654126641267412684126941270412714127241273412744127541276412774127841279412804128141282412834128441285412864128741288412894129041291412924129341294412954129641297412984129941300413014130241303413044130541306413074130841309413104131141312413134131441315413164131741318413194132041321413224132341324413254132641327413284132941330413314133241333413344133541336413374133841339413404134141342413434134441345413464134741348413494135041351413524135341354413554135641357413584135941360413614136241363413644136541366413674136841369413704137141372413734137441375413764137741378413794138041381413824138341384413854138641387413884138941390413914139241393413944139541396413974139841399414004140141402414034140441405414064140741408414094141041411414124141341414414154141641417414184141941420414214142241423414244142541426414274142841429414304143141432414334143441435414364143741438414394144041441414424144341444414454144641447414484144941450414514145241453414544145541456414574145841459414604146141462414634146441465414664146741468414694147041471414724147341474414754147641477414784147941480414814148241483414844148541486414874148841489414904149141492414934149441495414964149741498414994150041501415024150341504415054150641507415084150941510415114151241513415144151541516415174151841519415204152141522415234152441525415264152741528415294153041531415324153341534415354153641537415384153941540415414154241543415444154541546415474154841549415504155141552415534155441555415564155741558415594156041561415624156341564415654156641567415684156941570415714157241573415744157541576415774157841579415804158141582415834158441585415864158741588415894159041591415924159341594415954159641597415984159941600416014160241603416044160541606416074160841609416104161141612416134161441615416164161741618416194162041621416224162341624416254162641627416284162941630416314163241633416344163541636416374163841639416404164141642416434164441645416464164741648416494165041651416524165341654416554165641657416584165941660416614166241663416644166541666416674166841669416704167141672416734167441675416764167741678416794168041681416824168341684416854168641687416884168941690416914169241693416944169541696416974169841699417004170141702417034170441705417064170741708417094171041711417124171341714417154171641717417184171941720417214172241723417244172541726417274172841729417304173141732417334173441735417364173741738417394174041741417424174341744417454174641747417484174941750417514175241753417544175541756417574175841759417604176141762417634176441765417664176741768417694177041771417724177341774417754177641777417784177941780417814178241783417844178541786417874178841789417904179141792417934179441795417964179741798417994180041801418024180341804418054180641807418084180941810418114181241813418144181541816418174181841819418204182141822418234182441825418264182741828418294183041831418324183341834418354183641837418384183941840418414184241843418444184541846418474184841849418504185141852418534185441855418564185741858418594186041861418624186341864418654186641867418684186941870418714187241873418744187541876418774187841879418804188141882418834188441885418864188741888418894189041891418924189341894418954189641897418984189941900419014190241903419044190541906419074190841909419104191141912419134191441915419164191741918419194192041921419224192341924419254192641927419284192941930419314193241933419344193541936419374193841939419404194141942419434194441945419464194741948419494195041951419524195341954419554195641957419584195941960419614196241963419644196541966419674196841969419704197141972419734197441975419764197741978419794198041981419824198341984419854198641987419884198941990419914199241993419944199541996419974199841999420004200142002420034200442005420064200742008420094201042011420124201342014420154201642017420184201942020420214202242023420244202542026420274202842029420304203142032420334203442035420364203742038420394204042041420424204342044420454204642047420484204942050420514205242053420544205542056420574205842059420604206142062420634206442065420664206742068420694207042071420724207342074420754207642077420784207942080420814208242083420844208542086420874208842089420904209142092420934209442095420964209742098420994210042101421024210342104421054210642107421084210942110421114211242113421144211542116421174211842119421204212142122421234212442125421264212742128421294213042131421324213342134421354213642137421384213942140421414214242143421444214542146421474214842149421504215142152421534215442155421564215742158421594216042161421624216342164421654216642167421684216942170421714217242173421744217542176421774217842179421804218142182421834218442185421864218742188421894219042191421924219342194421954219642197421984219942200422014220242203422044220542206422074220842209422104221142212422134221442215422164221742218422194222042221422224222342224422254222642227422284222942230422314223242233422344223542236422374223842239422404224142242422434224442245422464224742248422494225042251422524225342254422554225642257422584225942260422614226242263422644226542266422674226842269422704227142272422734227442275422764227742278422794228042281422824228342284422854228642287422884228942290422914229242293422944229542296422974229842299423004230142302423034230442305423064230742308423094231042311423124231342314423154231642317423184231942320423214232242323423244232542326423274232842329423304233142332423334233442335423364233742338423394234042341423424234342344423454234642347423484234942350423514235242353423544235542356423574235842359423604236142362423634236442365423664236742368423694237042371423724237342374423754237642377423784237942380423814238242383423844238542386423874238842389423904239142392423934239442395423964239742398423994240042401424024240342404424054240642407424084240942410424114241242413424144241542416424174241842419424204242142422424234242442425424264242742428424294243042431424324243342434424354243642437424384243942440424414244242443424444244542446424474244842449424504245142452424534245442455424564245742458424594246042461424624246342464424654246642467424684246942470424714247242473424744247542476424774247842479424804248142482424834248442485424864248742488424894249042491424924249342494424954249642497424984249942500425014250242503425044250542506425074250842509425104251142512425134251442515425164251742518425194252042521425224252342524425254252642527425284252942530425314253242533425344253542536425374253842539425404254142542425434254442545425464254742548425494255042551425524255342554425554255642557425584255942560425614256242563425644256542566425674256842569425704257142572425734257442575425764257742578425794258042581425824258342584425854258642587425884258942590425914259242593425944259542596425974259842599426004260142602426034260442605426064260742608426094261042611426124261342614426154261642617426184261942620426214262242623426244262542626426274262842629426304263142632426334263442635426364263742638426394264042641426424264342644426454264642647426484264942650426514265242653426544265542656426574265842659426604266142662426634266442665426664266742668426694267042671426724267342674426754267642677426784267942680426814268242683426844268542686426874268842689426904269142692426934269442695426964269742698426994270042701427024270342704427054270642707427084270942710427114271242713427144271542716427174271842719427204272142722427234272442725427264272742728427294273042731427324273342734427354273642737427384273942740427414274242743427444274542746427474274842749427504275142752427534275442755427564275742758427594276042761427624276342764427654276642767427684276942770427714277242773427744277542776427774277842779427804278142782427834278442785427864278742788427894279042791427924279342794427954279642797427984279942800428014280242803428044280542806428074280842809428104281142812428134281442815428164281742818428194282042821428224282342824428254282642827428284282942830428314283242833428344283542836428374283842839428404284142842428434284442845428464284742848428494285042851428524285342854428554285642857428584285942860428614286242863428644286542866428674286842869428704287142872428734287442875428764287742878428794288042881428824288342884428854288642887428884288942890428914289242893428944289542896428974289842899429004290142902429034290442905429064290742908429094291042911429124291342914429154291642917429184291942920429214292242923429244292542926429274292842929429304293142932429334293442935429364293742938429394294042941429424294342944429454294642947429484294942950429514295242953429544295542956429574295842959429604296142962429634296442965429664296742968429694297042971429724297342974429754297642977429784297942980429814298242983429844298542986429874298842989429904299142992429934299442995429964299742998429994300043001430024300343004430054300643007430084300943010430114301243013430144301543016430174301843019430204302143022430234302443025430264302743028430294303043031430324303343034430354303643037430384303943040430414304243043430444304543046430474304843049430504305143052430534305443055430564305743058430594306043061430624306343064430654306643067430684306943070430714307243073430744307543076430774307843079430804308143082430834308443085430864308743088430894309043091430924309343094430954309643097430984309943100431014310243103431044310543106431074310843109431104311143112431134311443115431164311743118431194312043121431224312343124431254312643127431284312943130431314313243133431344313543136431374313843139431404314143142431434314443145431464314743148431494315043151431524315343154431554315643157431584315943160431614316243163431644316543166431674316843169431704317143172431734317443175431764317743178431794318043181431824318343184431854318643187431884318943190431914319243193431944319543196431974319843199432004320143202432034320443205432064320743208432094321043211432124321343214432154321643217432184321943220432214322243223432244322543226432274322843229432304323143232432334323443235432364323743238432394324043241432424324343244432454324643247432484324943250432514325243253432544325543256432574325843259432604326143262432634326443265432664326743268432694327043271432724327343274432754327643277432784327943280432814328243283432844328543286432874328843289432904329143292432934329443295432964329743298432994330043301433024330343304433054330643307433084330943310433114331243313433144331543316433174331843319433204332143322433234332443325433264332743328433294333043331433324333343334433354333643337433384333943340433414334243343433444334543346433474334843349433504335143352433534335443355433564335743358433594336043361433624336343364433654336643367433684336943370433714337243373433744337543376433774337843379433804338143382433834338443385433864338743388433894339043391433924339343394433954339643397433984339943400434014340243403434044340543406434074340843409434104341143412434134341443415434164341743418434194342043421434224342343424434254342643427434284342943430434314343243433434344343543436434374343843439434404344143442434434344443445434464344743448434494345043451434524345343454434554345643457434584345943460434614346243463434644346543466434674346843469434704347143472434734347443475434764347743478434794348043481434824348343484434854348643487434884348943490434914349243493434944349543496434974349843499435004350143502435034350443505435064350743508435094351043511435124351343514435154351643517435184351943520435214352243523435244352543526435274352843529435304353143532435334353443535435364353743538435394354043541435424354343544435454354643547435484354943550435514355243553435544355543556435574355843559435604356143562435634356443565435664356743568435694357043571435724357343574435754357643577435784357943580435814358243583435844358543586435874358843589435904359143592435934359443595435964359743598435994360043601436024360343604436054360643607436084360943610436114361243613436144361543616436174361843619436204362143622436234362443625436264362743628436294363043631436324363343634436354363643637436384363943640436414364243643436444364543646436474364843649436504365143652436534365443655436564365743658436594366043661436624366343664436654366643667436684366943670436714367243673436744367543676436774367843679436804368143682436834368443685436864368743688436894369043691436924369343694436954369643697436984369943700437014370243703437044370543706437074370843709437104371143712437134371443715437164371743718437194372043721437224372343724437254372643727437284372943730437314373243733437344373543736437374373843739437404374143742437434374443745437464374743748437494375043751437524375343754437554375643757437584375943760437614376243763437644376543766437674376843769437704377143772437734377443775437764377743778437794378043781437824378343784437854378643787437884378943790437914379243793437944379543796437974379843799438004380143802438034380443805438064380743808438094381043811438124381343814438154381643817438184381943820438214382243823438244382543826438274382843829438304383143832438334383443835438364383743838438394384043841438424384343844438454384643847438484384943850438514385243853438544385543856438574385843859438604386143862438634386443865438664386743868438694387043871438724387343874438754387643877438784387943880438814388243883438844388543886438874388843889438904389143892438934389443895438964389743898438994390043901439024390343904439054390643907439084390943910439114391243913439144391543916439174391843919439204392143922439234392443925439264392743928439294393043931439324393343934439354393643937439384393943940439414394243943439444394543946439474394843949439504395143952439534395443955439564395743958439594396043961439624396343964439654396643967439684396943970439714397243973439744397543976439774397843979439804398143982439834398443985439864398743988439894399043991439924399343994439954399643997439984399944000440014400244003440044400544006440074400844009440104401144012440134401444015440164401744018440194402044021440224402344024440254402644027440284402944030440314403244033440344403544036440374403844039440404404144042440434404444045440464404744048440494405044051440524405344054440554405644057440584405944060440614406244063440644406544066440674406844069440704407144072440734407444075440764407744078440794408044081440824408344084440854408644087440884408944090440914409244093440944409544096440974409844099441004410144102441034410444105441064410744108441094411044111441124411344114441154411644117441184411944120441214412244123441244412544126441274412844129441304413144132441334413444135441364413744138441394414044141441424414344144441454414644147441484414944150441514415244153441544415544156441574415844159441604416144162441634416444165441664416744168441694417044171441724417344174441754417644177441784417944180441814418244183441844418544186441874418844189441904419144192441934419444195441964419744198441994420044201442024420344204442054420644207442084420944210442114421244213442144421544216442174421844219442204422144222442234422444225442264422744228442294423044231442324423344234442354423644237442384423944240442414424244243442444424544246442474424844249442504425144252442534425444255442564425744258442594426044261442624426344264442654426644267442684426944270442714427244273442744427544276442774427844279442804428144282442834428444285442864428744288442894429044291442924429344294442954429644297442984429944300443014430244303443044430544306443074430844309443104431144312443134431444315443164431744318443194432044321443224432344324443254432644327443284432944330443314433244333443344433544336443374433844339443404434144342443434434444345443464434744348443494435044351443524435344354443554435644357443584435944360443614436244363443644436544366443674436844369443704437144372443734437444375443764437744378443794438044381443824438344384443854438644387443884438944390443914439244393443944439544396443974439844399444004440144402444034440444405444064440744408444094441044411444124441344414444154441644417444184441944420444214442244423444244442544426444274442844429444304443144432444334443444435444364443744438444394444044441444424444344444444454444644447444484444944450444514445244453444544445544456444574445844459444604446144462444634446444465444664446744468444694447044471444724447344474444754447644477444784447944480444814448244483444844448544486444874448844489444904449144492444934449444495444964449744498444994450044501445024450344504445054450644507445084450944510445114451244513445144451544516445174451844519445204452144522445234452444525445264452744528445294453044531445324453344534445354453644537445384453944540445414454244543445444454544546445474454844549445504455144552445534455444555445564455744558445594456044561445624456344564445654456644567445684456944570445714457244573445744457544576445774457844579445804458144582445834458444585445864458744588445894459044591445924459344594445954459644597445984459944600446014460244603446044460544606446074460844609446104461144612446134461444615446164461744618446194462044621446224462344624446254462644627446284462944630446314463244633446344463544636446374463844639446404464144642446434464444645446464464744648446494465044651446524465344654446554465644657446584465944660446614466244663446644466544666446674466844669446704467144672446734467444675446764467744678446794468044681446824468344684446854468644687446884468944690446914469244693446944469544696446974469844699447004470144702447034470444705447064470744708447094471044711447124471344714447154471644717447184471944720447214472244723447244472544726447274472844729447304473144732447334473444735447364473744738447394474044741447424474344744447454474644747447484474944750447514475244753447544475544756447574475844759447604476144762447634476444765447664476744768447694477044771447724477344774447754477644777447784477944780447814478244783447844478544786447874478844789447904479144792447934479444795447964479744798447994480044801448024480344804448054480644807448084480944810448114481244813448144481544816448174481844819448204482144822448234482444825448264482744828448294483044831448324483344834448354483644837448384483944840448414484244843448444484544846448474484844849448504485144852448534485444855448564485744858448594486044861448624486344864448654486644867448684486944870448714487244873448744487544876448774487844879448804488144882448834488444885448864488744888448894489044891448924489344894448954489644897448984489944900449014490244903449044490544906449074490844909449104491144912449134491444915449164491744918449194492044921449224492344924449254492644927449284492944930449314493244933449344493544936449374493844939449404494144942449434494444945449464494744948449494495044951449524495344954449554495644957449584495944960449614496244963449644496544966449674496844969449704497144972449734497444975449764497744978449794498044981449824498344984449854498644987449884498944990449914499244993449944499544996449974499844999450004500145002450034500445005450064500745008450094501045011450124501345014450154501645017450184501945020450214502245023450244502545026450274502845029450304503145032450334503445035450364503745038450394504045041450424504345044450454504645047450484504945050450514505245053450544505545056450574505845059450604506145062450634506445065450664506745068450694507045071450724507345074450754507645077450784507945080450814508245083450844508545086450874508845089450904509145092450934509445095450964509745098450994510045101451024510345104451054510645107451084510945110451114511245113451144511545116451174511845119451204512145122451234512445125451264512745128451294513045131451324513345134451354513645137451384513945140451414514245143451444514545146451474514845149451504515145152451534515445155451564515745158451594516045161451624516345164451654516645167451684516945170451714517245173451744517545176451774517845179451804518145182451834518445185451864518745188451894519045191451924519345194451954519645197451984519945200452014520245203452044520545206452074520845209452104521145212452134521445215452164521745218452194522045221452224522345224452254522645227452284522945230452314523245233452344523545236452374523845239452404524145242452434524445245452464524745248452494525045251452524525345254452554525645257452584525945260452614526245263452644526545266452674526845269452704527145272452734527445275452764527745278452794528045281452824528345284452854528645287452884528945290452914529245293452944529545296452974529845299453004530145302453034530445305453064530745308453094531045311453124531345314453154531645317453184531945320453214532245323453244532545326453274532845329453304533145332453334533445335453364533745338453394534045341453424534345344453454534645347453484534945350453514535245353453544535545356453574535845359453604536145362453634536445365453664536745368453694537045371453724537345374453754537645377453784537945380453814538245383453844538545386453874538845389453904539145392453934539445395453964539745398453994540045401454024540345404454054540645407454084540945410454114541245413454144541545416454174541845419454204542145422454234542445425454264542745428454294543045431454324543345434454354543645437454384543945440454414544245443454444544545446454474544845449454504545145452454534545445455454564545745458454594546045461454624546345464454654546645467454684546945470454714547245473454744547545476454774547845479454804548145482454834548445485454864548745488454894549045491454924549345494454954549645497454984549945500455014550245503455044550545506455074550845509455104551145512455134551445515455164551745518455194552045521455224552345524455254552645527455284552945530455314553245533455344553545536455374553845539455404554145542455434554445545455464554745548455494555045551455524555345554455554555645557455584555945560455614556245563455644556545566455674556845569455704557145572455734557445575455764557745578455794558045581455824558345584455854558645587455884558945590455914559245593455944559545596455974559845599456004560145602456034560445605456064560745608456094561045611456124561345614456154561645617456184561945620456214562245623456244562545626456274562845629456304563145632456334563445635456364563745638456394564045641456424564345644456454564645647456484564945650456514565245653456544565545656456574565845659456604566145662456634566445665456664566745668456694567045671456724567345674456754567645677456784567945680456814568245683456844568545686456874568845689456904569145692456934569445695456964569745698456994570045701457024570345704457054570645707457084570945710457114571245713457144571545716457174571845719457204572145722457234572445725457264572745728457294573045731457324573345734457354573645737457384573945740457414574245743457444574545746457474574845749457504575145752457534575445755457564575745758457594576045761457624576345764457654576645767457684576945770457714577245773457744577545776457774577845779457804578145782457834578445785457864578745788457894579045791457924579345794457954579645797457984579945800458014580245803458044580545806458074580845809458104581145812458134581445815458164581745818458194582045821458224582345824458254582645827458284582945830458314583245833458344583545836458374583845839458404584145842458434584445845458464584745848458494585045851458524585345854458554585645857458584585945860458614586245863458644586545866458674586845869458704587145872458734587445875458764587745878458794588045881458824588345884458854588645887458884588945890458914589245893458944589545896458974589845899459004590145902459034590445905459064590745908459094591045911459124591345914459154591645917459184591945920459214592245923459244592545926459274592845929459304593145932459334593445935459364593745938459394594045941459424594345944459454594645947459484594945950459514595245953459544595545956459574595845959459604596145962459634596445965459664596745968459694597045971459724597345974459754597645977459784597945980459814598245983459844598545986459874598845989459904599145992459934599445995459964599745998459994600046001460024600346004460054600646007460084600946010460114601246013460144601546016460174601846019460204602146022460234602446025460264602746028460294603046031460324603346034460354603646037460384603946040460414604246043460444604546046460474604846049460504605146052460534605446055460564605746058460594606046061460624606346064460654606646067460684606946070460714607246073460744607546076460774607846079460804608146082460834608446085460864608746088460894609046091460924609346094460954609646097460984609946100461014610246103461044610546106461074610846109461104611146112461134611446115461164611746118461194612046121461224612346124461254612646127461284612946130461314613246133461344613546136461374613846139461404614146142461434614446145461464614746148461494615046151461524615346154461554615646157461584615946160461614616246163461644616546166461674616846169461704617146172461734617446175461764617746178461794618046181461824618346184461854618646187461884618946190461914619246193461944619546196461974619846199462004620146202462034620446205462064620746208462094621046211462124621346214462154621646217462184621946220462214622246223462244622546226462274622846229462304623146232462334623446235462364623746238462394624046241462424624346244462454624646247462484624946250462514625246253462544625546256462574625846259462604626146262462634626446265462664626746268462694627046271462724627346274462754627646277462784627946280462814628246283462844628546286462874628846289462904629146292462934629446295462964629746298462994630046301463024630346304463054630646307463084630946310463114631246313463144631546316463174631846319463204632146322463234632446325463264632746328463294633046331463324633346334463354633646337463384633946340463414634246343463444634546346463474634846349463504635146352463534635446355463564635746358463594636046361463624636346364463654636646367463684636946370463714637246373463744637546376463774637846379463804638146382463834638446385463864638746388463894639046391463924639346394463954639646397463984639946400464014640246403464044640546406464074640846409464104641146412464134641446415464164641746418464194642046421464224642346424464254642646427464284642946430464314643246433464344643546436464374643846439464404644146442464434644446445464464644746448464494645046451464524645346454464554645646457464584645946460464614646246463464644646546466464674646846469464704647146472464734647446475464764647746478464794648046481464824648346484464854648646487464884648946490464914649246493464944649546496464974649846499465004650146502465034650446505465064650746508465094651046511465124651346514465154651646517465184651946520465214652246523465244652546526465274652846529465304653146532465334653446535465364653746538465394654046541465424654346544465454654646547465484654946550465514655246553465544655546556465574655846559465604656146562465634656446565465664656746568465694657046571465724657346574465754657646577465784657946580465814658246583465844658546586465874658846589465904659146592465934659446595465964659746598465994660046601466024660346604466054660646607466084660946610466114661246613466144661546616466174661846619466204662146622466234662446625466264662746628466294663046631466324663346634466354663646637466384663946640466414664246643466444664546646466474664846649466504665146652466534665446655466564665746658466594666046661466624666346664466654666646667466684666946670466714667246673466744667546676466774667846679466804668146682466834668446685466864668746688466894669046691466924669346694466954669646697466984669946700467014670246703467044670546706467074670846709467104671146712467134671446715467164671746718467194672046721467224672346724467254672646727467284672946730467314673246733467344673546736467374673846739467404674146742467434674446745467464674746748467494675046751467524675346754467554675646757467584675946760467614676246763467644676546766467674676846769467704677146772467734677446775467764677746778467794678046781467824678346784467854678646787467884678946790467914679246793467944679546796467974679846799468004680146802468034680446805468064680746808468094681046811468124681346814468154681646817468184681946820468214682246823468244682546826468274682846829468304683146832468334683446835468364683746838468394684046841468424684346844468454684646847468484684946850468514685246853468544685546856468574685846859468604686146862468634686446865468664686746868468694687046871468724687346874468754687646877468784687946880468814688246883468844688546886468874688846889468904689146892468934689446895468964689746898468994690046901469024690346904469054690646907469084690946910469114691246913469144691546916469174691846919469204692146922469234692446925469264692746928469294693046931469324693346934469354693646937469384693946940469414694246943469444694546946469474694846949469504695146952469534695446955469564695746958469594696046961469624696346964469654696646967469684696946970469714697246973469744697546976469774697846979469804698146982469834698446985469864698746988469894699046991469924699346994469954699646997469984699947000470014700247003470044700547006470074700847009470104701147012470134701447015470164701747018470194702047021470224702347024470254702647027470284702947030470314703247033470344703547036470374703847039470404704147042470434704447045470464704747048470494705047051470524705347054470554705647057470584705947060470614706247063470644706547066470674706847069470704707147072470734707447075470764707747078470794708047081470824708347084470854708647087470884708947090470914709247093470944709547096470974709847099471004710147102471034710447105471064710747108471094711047111471124711347114471154711647117471184711947120471214712247123471244712547126471274712847129471304713147132471334713447135471364713747138471394714047141471424714347144471454714647147471484714947150471514715247153471544715547156471574715847159471604716147162471634716447165471664716747168471694717047171471724717347174471754717647177471784717947180471814718247183471844718547186471874718847189471904719147192471934719447195471964719747198471994720047201472024720347204472054720647207472084720947210472114721247213472144721547216472174721847219472204722147222472234722447225472264722747228472294723047231472324723347234472354723647237472384723947240472414724247243472444724547246472474724847249472504725147252472534725447255472564725747258472594726047261472624726347264472654726647267472684726947270472714727247273472744727547276472774727847279472804728147282472834728447285472864728747288472894729047291472924729347294472954729647297472984729947300473014730247303473044730547306473074730847309473104731147312473134731447315473164731747318473194732047321473224732347324473254732647327473284732947330473314733247333473344733547336473374733847339473404734147342473434734447345473464734747348473494735047351473524735347354473554735647357473584735947360473614736247363473644736547366473674736847369473704737147372473734737447375473764737747378473794738047381473824738347384473854738647387473884738947390473914739247393473944739547396473974739847399474004740147402474034740447405474064740747408474094741047411474124741347414474154741647417474184741947420474214742247423474244742547426474274742847429474304743147432474334743447435474364743747438474394744047441474424744347444474454744647447474484744947450474514745247453474544745547456474574745847459474604746147462474634746447465474664746747468474694747047471474724747347474474754747647477474784747947480474814748247483474844748547486474874748847489474904749147492474934749447495474964749747498474994750047501475024750347504475054750647507475084750947510475114751247513475144751547516475174751847519475204752147522475234752447525475264752747528475294753047531475324753347534475354753647537475384753947540475414754247543475444754547546475474754847549475504755147552475534755447555475564755747558475594756047561475624756347564475654756647567475684756947570475714757247573475744757547576475774757847579475804758147582475834758447585475864758747588475894759047591475924759347594475954759647597475984759947600476014760247603476044760547606476074760847609476104761147612476134761447615476164761747618476194762047621476224762347624476254762647627476284762947630476314763247633476344763547636476374763847639476404764147642476434764447645476464764747648476494765047651476524765347654476554765647657476584765947660476614766247663476644766547666476674766847669476704767147672476734767447675476764767747678476794768047681476824768347684476854768647687476884768947690476914769247693476944769547696476974769847699477004770147702477034770447705477064770747708477094771047711477124771347714477154771647717477184771947720477214772247723477244772547726477274772847729477304773147732477334773447735477364773747738477394774047741477424774347744477454774647747477484774947750477514775247753477544775547756477574775847759477604776147762477634776447765477664776747768477694777047771477724777347774477754777647777477784777947780477814778247783477844778547786477874778847789477904779147792477934779447795477964779747798477994780047801478024780347804478054780647807478084780947810478114781247813478144781547816478174781847819478204782147822478234782447825478264782747828478294783047831478324783347834478354783647837478384783947840478414784247843478444784547846478474784847849478504785147852478534785447855478564785747858478594786047861478624786347864478654786647867478684786947870478714787247873478744787547876478774787847879478804788147882478834788447885478864788747888478894789047891478924789347894478954789647897478984789947900479014790247903479044790547906479074790847909479104791147912479134791447915479164791747918479194792047921479224792347924479254792647927479284792947930479314793247933479344793547936479374793847939479404794147942479434794447945479464794747948479494795047951479524795347954479554795647957479584795947960479614796247963479644796547966479674796847969479704797147972479734797447975479764797747978479794798047981479824798347984479854798647987479884798947990479914799247993479944799547996479974799847999480004800148002480034800448005480064800748008480094801048011480124801348014480154801648017480184801948020480214802248023480244802548026480274802848029480304803148032480334803448035480364803748038480394804048041480424804348044480454804648047480484804948050480514805248053480544805548056480574805848059480604806148062480634806448065480664806748068480694807048071480724807348074480754807648077480784807948080480814808248083480844808548086480874808848089480904809148092480934809448095480964809748098480994810048101481024810348104481054810648107481084810948110481114811248113481144811548116481174811848119481204812148122481234812448125481264812748128481294813048131481324813348134481354813648137481384813948140481414814248143481444814548146481474814848149481504815148152481534815448155481564815748158481594816048161481624816348164481654816648167481684816948170481714817248173481744817548176481774817848179481804818148182481834818448185481864818748188481894819048191481924819348194481954819648197481984819948200482014820248203482044820548206482074820848209482104821148212482134821448215482164821748218482194822048221482224822348224482254822648227482284822948230482314823248233482344823548236482374823848239482404824148242482434824448245482464824748248482494825048251482524825348254482554825648257482584825948260482614826248263482644826548266482674826848269482704827148272482734827448275482764827748278482794828048281482824828348284482854828648287482884828948290482914829248293482944829548296482974829848299483004830148302483034830448305483064830748308483094831048311483124831348314483154831648317483184831948320483214832248323483244832548326483274832848329483304833148332483334833448335483364833748338483394834048341483424834348344483454834648347483484834948350483514835248353483544835548356483574835848359483604836148362483634836448365483664836748368483694837048371483724837348374483754837648377483784837948380483814838248383483844838548386483874838848389483904839148392483934839448395483964839748398483994840048401484024840348404484054840648407484084840948410484114841248413484144841548416484174841848419484204842148422484234842448425484264842748428484294843048431484324843348434484354843648437484384843948440484414844248443484444844548446484474844848449484504845148452484534845448455484564845748458484594846048461484624846348464484654846648467484684846948470484714847248473484744847548476484774847848479484804848148482484834848448485484864848748488484894849048491484924849348494484954849648497484984849948500485014850248503485044850548506485074850848509485104851148512485134851448515485164851748518485194852048521485224852348524485254852648527485284852948530485314853248533485344853548536485374853848539485404854148542485434854448545485464854748548485494855048551485524855348554485554855648557485584855948560485614856248563485644856548566485674856848569485704857148572485734857448575485764857748578485794858048581485824858348584485854858648587485884858948590485914859248593485944859548596485974859848599486004860148602486034860448605486064860748608486094861048611486124861348614486154861648617486184861948620486214862248623486244862548626486274862848629486304863148632486334863448635486364863748638486394864048641486424864348644486454864648647486484864948650486514865248653486544865548656486574865848659486604866148662486634866448665486664866748668486694867048671486724867348674486754867648677486784867948680486814868248683486844868548686486874868848689486904869148692486934869448695486964869748698486994870048701487024870348704487054870648707487084870948710487114871248713487144871548716487174871848719487204872148722487234872448725487264872748728487294873048731487324873348734487354873648737487384873948740487414874248743487444874548746487474874848749487504875148752487534875448755487564875748758487594876048761487624876348764487654876648767487684876948770487714877248773487744877548776487774877848779487804878148782487834878448785487864878748788487894879048791487924879348794487954879648797487984879948800488014880248803488044880548806488074880848809488104881148812488134881448815488164881748818488194882048821488224882348824488254882648827488284882948830488314883248833488344883548836488374883848839488404884148842488434884448845488464884748848488494885048851488524885348854488554885648857488584885948860488614886248863488644886548866488674886848869488704887148872488734887448875488764887748878488794888048881488824888348884488854888648887488884888948890488914889248893488944889548896488974889848899489004890148902489034890448905489064890748908489094891048911489124891348914489154891648917489184891948920489214892248923489244892548926489274892848929489304893148932489334893448935489364893748938489394894048941489424894348944489454894648947489484894948950489514895248953489544895548956489574895848959489604896148962489634896448965489664896748968489694897048971489724897348974489754897648977489784897948980489814898248983489844898548986489874898848989489904899148992489934899448995489964899748998489994900049001490024900349004490054900649007490084900949010490114901249013490144901549016490174901849019490204902149022490234902449025490264902749028490294903049031490324903349034490354903649037490384903949040490414904249043490444904549046490474904849049490504905149052490534905449055490564905749058490594906049061490624906349064490654906649067490684906949070490714907249073490744907549076490774907849079490804908149082490834908449085490864908749088490894909049091490924909349094490954909649097490984909949100491014910249103491044910549106491074910849109491104911149112491134911449115491164911749118491194912049121491224912349124491254912649127491284912949130491314913249133491344913549136491374913849139491404914149142491434914449145491464914749148491494915049151491524915349154491554915649157491584915949160491614916249163491644916549166491674916849169491704917149172491734917449175491764917749178491794918049181491824918349184491854918649187491884918949190491914919249193491944919549196491974919849199492004920149202492034920449205492064920749208492094921049211492124921349214492154921649217492184921949220492214922249223492244922549226492274922849229492304923149232492334923449235492364923749238492394924049241492424924349244492454924649247492484924949250492514925249253492544925549256492574925849259492604926149262492634926449265492664926749268492694927049271492724927349274492754927649277492784927949280492814928249283492844928549286492874928849289492904929149292492934929449295492964929749298492994930049301493024930349304493054930649307493084930949310493114931249313493144931549316493174931849319493204932149322493234932449325493264932749328493294933049331493324933349334493354933649337493384933949340493414934249343493444934549346493474934849349493504935149352493534935449355493564935749358493594936049361493624936349364493654936649367493684936949370493714937249373493744937549376493774937849379493804938149382493834938449385493864938749388493894939049391493924939349394493954939649397493984939949400494014940249403494044940549406494074940849409494104941149412494134941449415494164941749418494194942049421494224942349424494254942649427494284942949430494314943249433494344943549436494374943849439494404944149442494434944449445494464944749448494494945049451494524945349454494554945649457494584945949460494614946249463494644946549466494674946849469494704947149472494734947449475494764947749478494794948049481494824948349484494854948649487494884948949490494914949249493494944949549496494974949849499495004950149502495034950449505495064950749508495094951049511495124951349514495154951649517495184951949520495214952249523495244952549526495274952849529495304953149532495334953449535495364953749538495394954049541495424954349544495454954649547495484954949550495514955249553495544955549556495574955849559495604956149562495634956449565495664956749568495694957049571495724957349574495754957649577495784957949580495814958249583495844958549586495874958849589495904959149592495934959449595495964959749598495994960049601496024960349604496054960649607496084960949610496114961249613496144961549616496174961849619496204962149622496234962449625496264962749628496294963049631496324963349634496354963649637496384963949640496414964249643496444964549646496474964849649496504965149652496534965449655496564965749658496594966049661496624966349664496654966649667496684966949670496714967249673496744967549676496774967849679496804968149682496834968449685496864968749688496894969049691496924969349694496954969649697496984969949700497014970249703497044970549706497074970849709497104971149712497134971449715497164971749718497194972049721497224972349724497254972649727497284972949730497314973249733497344973549736497374973849739497404974149742497434974449745497464974749748497494975049751497524975349754497554975649757497584975949760497614976249763497644976549766497674976849769497704977149772497734977449775497764977749778497794978049781497824978349784497854978649787497884978949790497914979249793497944979549796497974979849799498004980149802498034980449805498064980749808498094981049811498124981349814498154981649817498184981949820498214982249823498244982549826498274982849829498304983149832498334983449835498364983749838498394984049841498424984349844498454984649847498484984949850498514985249853498544985549856498574985849859498604986149862498634986449865498664986749868498694987049871498724987349874498754987649877498784987949880498814988249883498844988549886498874988849889498904989149892498934989449895498964989749898498994990049901499024990349904499054990649907499084990949910499114991249913499144991549916499174991849919499204992149922499234992449925499264992749928499294993049931499324993349934499354993649937499384993949940499414994249943499444994549946499474994849949499504995149952499534995449955499564995749958499594996049961499624996349964499654996649967499684996949970499714997249973499744997549976499774997849979499804998149982499834998449985499864998749988499894999049991499924999349994499954999649997499984999950000500015000250003500045000550006500075000850009500105001150012500135001450015500165001750018500195002050021500225002350024500255002650027500285002950030500315003250033500345003550036500375003850039500405004150042500435004450045500465004750048500495005050051500525005350054500555005650057500585005950060500615006250063500645006550066500675006850069500705007150072500735007450075500765007750078500795008050081500825008350084500855008650087500885008950090500915009250093500945009550096500975009850099501005010150102501035010450105501065010750108501095011050111501125011350114501155011650117501185011950120501215012250123501245012550126501275012850129501305013150132501335013450135501365013750138501395014050141501425014350144501455014650147501485014950150501515015250153501545015550156501575015850159501605016150162501635016450165501665016750168501695017050171501725017350174501755017650177501785017950180501815018250183501845018550186501875018850189501905019150192501935019450195501965019750198501995020050201502025020350204502055020650207502085020950210502115021250213502145021550216502175021850219502205022150222502235022450225502265022750228502295023050231502325023350234502355023650237502385023950240502415024250243502445024550246502475024850249502505025150252502535025450255502565025750258502595026050261502625026350264502655026650267502685026950270502715027250273502745027550276502775027850279502805028150282502835028450285502865028750288502895029050291502925029350294502955029650297502985029950300503015030250303503045030550306503075030850309503105031150312503135031450315503165031750318503195032050321503225032350324503255032650327503285032950330503315033250333503345033550336503375033850339503405034150342503435034450345503465034750348503495035050351503525035350354503555035650357503585035950360503615036250363503645036550366503675036850369503705037150372503735037450375503765037750378503795038050381503825038350384503855038650387503885038950390503915039250393503945039550396503975039850399504005040150402504035040450405504065040750408504095041050411504125041350414504155041650417504185041950420504215042250423504245042550426504275042850429504305043150432504335043450435504365043750438504395044050441504425044350444504455044650447504485044950450504515045250453504545045550456504575045850459504605046150462504635046450465504665046750468504695047050471504725047350474504755047650477504785047950480504815048250483504845048550486504875048850489504905049150492504935049450495504965049750498504995050050501505025050350504505055050650507505085050950510505115051250513505145051550516505175051850519505205052150522505235052450525505265052750528505295053050531505325053350534505355053650537505385053950540505415054250543505445054550546505475054850549505505055150552505535055450555505565055750558505595056050561505625056350564505655056650567505685056950570505715057250573505745057550576505775057850579505805058150582505835058450585505865058750588505895059050591505925059350594505955059650597505985059950600506015060250603506045060550606506075060850609506105061150612506135061450615506165061750618506195062050621506225062350624506255062650627506285062950630506315063250633506345063550636506375063850639506405064150642506435064450645506465064750648506495065050651506525065350654506555065650657506585065950660506615066250663506645066550666506675066850669506705067150672506735067450675506765067750678506795068050681506825068350684506855068650687506885068950690506915069250693506945069550696506975069850699507005070150702507035070450705507065070750708507095071050711507125071350714507155071650717507185071950720507215072250723507245072550726507275072850729507305073150732507335073450735507365073750738507395074050741507425074350744507455074650747507485074950750507515075250753507545075550756507575075850759507605076150762507635076450765507665076750768507695077050771507725077350774507755077650777507785077950780507815078250783507845078550786507875078850789507905079150792507935079450795507965079750798507995080050801508025080350804508055080650807508085080950810508115081250813508145081550816508175081850819508205082150822508235082450825508265082750828508295083050831508325083350834508355083650837508385083950840508415084250843508445084550846508475084850849508505085150852508535085450855508565085750858508595086050861508625086350864508655086650867508685086950870508715087250873508745087550876508775087850879508805088150882508835088450885508865088750888508895089050891508925089350894508955089650897508985089950900509015090250903509045090550906509075090850909509105091150912509135091450915509165091750918509195092050921509225092350924509255092650927509285092950930509315093250933509345093550936509375093850939509405094150942509435094450945509465094750948509495095050951509525095350954509555095650957509585095950960509615096250963509645096550966509675096850969509705097150972509735097450975509765097750978509795098050981509825098350984509855098650987509885098950990509915099250993509945099550996509975099850999510005100151002510035100451005510065100751008510095101051011510125101351014510155101651017510185101951020510215102251023510245102551026510275102851029510305103151032510335103451035510365103751038510395104051041510425104351044510455104651047510485104951050510515105251053510545105551056510575105851059510605106151062510635106451065510665106751068510695107051071510725107351074510755107651077510785107951080510815108251083510845108551086510875108851089510905109151092510935109451095510965109751098510995110051101511025110351104511055110651107511085110951110511115111251113511145111551116511175111851119511205112151122511235112451125511265112751128511295113051131511325113351134511355113651137511385113951140511415114251143511445114551146511475114851149511505115151152511535115451155511565115751158511595116051161511625116351164511655116651167511685116951170511715117251173511745117551176511775117851179511805118151182511835118451185511865118751188511895119051191511925119351194511955119651197511985119951200512015120251203512045120551206512075120851209512105121151212512135121451215512165121751218512195122051221512225122351224512255122651227512285122951230512315123251233512345123551236512375123851239512405124151242512435124451245512465124751248512495125051251512525125351254512555125651257512585125951260512615126251263512645126551266512675126851269512705127151272512735127451275512765127751278512795128051281512825128351284512855128651287512885128951290512915129251293512945129551296512975129851299513005130151302513035130451305513065130751308513095131051311513125131351314513155131651317513185131951320513215132251323513245132551326513275132851329513305133151332513335133451335513365133751338513395134051341513425134351344513455134651347513485134951350513515135251353513545135551356513575135851359513605136151362513635136451365513665136751368513695137051371513725137351374513755137651377513785137951380513815138251383513845138551386513875138851389513905139151392513935139451395513965139751398513995140051401514025140351404514055140651407514085140951410514115141251413514145141551416514175141851419514205142151422514235142451425514265142751428514295143051431514325143351434514355143651437514385143951440514415144251443514445144551446514475144851449514505145151452514535145451455514565145751458514595146051461514625146351464514655146651467514685146951470514715147251473514745147551476514775147851479514805148151482514835148451485514865148751488514895149051491514925149351494514955149651497514985149951500515015150251503515045150551506515075150851509515105151151512515135151451515515165151751518515195152051521515225152351524515255152651527515285152951530515315153251533515345153551536515375153851539515405154151542515435154451545515465154751548515495155051551515525155351554515555155651557515585155951560515615156251563515645156551566515675156851569515705157151572515735157451575515765157751578515795158051581515825158351584515855158651587515885158951590515915159251593515945159551596515975159851599516005160151602516035160451605516065160751608516095161051611516125161351614516155161651617516185161951620516215162251623516245162551626516275162851629516305163151632516335163451635516365163751638516395164051641516425164351644516455164651647516485164951650516515165251653516545165551656516575165851659516605166151662516635166451665516665166751668516695167051671516725167351674516755167651677516785167951680516815168251683516845168551686516875168851689516905169151692516935169451695516965169751698516995170051701517025170351704517055170651707517085170951710517115171251713517145171551716517175171851719517205172151722517235172451725517265172751728517295173051731517325173351734517355173651737517385173951740517415174251743517445174551746517475174851749517505175151752517535175451755517565175751758517595176051761517625176351764517655176651767517685176951770517715177251773517745177551776517775177851779517805178151782517835178451785517865178751788517895179051791517925179351794517955179651797517985179951800518015180251803518045180551806518075180851809518105181151812518135181451815518165181751818518195182051821518225182351824518255182651827518285182951830518315183251833518345183551836518375183851839518405184151842518435184451845518465184751848518495185051851518525185351854518555185651857518585185951860518615186251863518645186551866518675186851869518705187151872518735187451875518765187751878518795188051881518825188351884518855188651887518885188951890518915189251893518945189551896518975189851899519005190151902519035190451905519065190751908519095191051911519125191351914519155191651917519185191951920519215192251923519245192551926519275192851929519305193151932519335193451935519365193751938519395194051941519425194351944519455194651947519485194951950519515195251953519545195551956519575195851959519605196151962519635196451965519665196751968519695197051971519725197351974519755197651977519785197951980519815198251983519845198551986519875198851989519905199151992519935199451995519965199751998519995200052001520025200352004520055200652007520085200952010520115201252013520145201552016520175201852019520205202152022520235202452025520265202752028520295203052031520325203352034520355203652037520385203952040520415204252043520445204552046520475204852049520505205152052520535205452055520565205752058520595206052061520625206352064520655206652067520685206952070520715207252073520745207552076520775207852079520805208152082520835208452085520865208752088520895209052091520925209352094520955209652097520985209952100521015210252103521045210552106521075210852109521105211152112521135211452115521165211752118521195212052121521225212352124521255212652127521285212952130521315213252133521345213552136521375213852139521405214152142521435214452145521465214752148521495215052151521525215352154521555215652157521585215952160521615216252163521645216552166521675216852169521705217152172521735217452175521765217752178521795218052181521825218352184521855218652187521885218952190521915219252193521945219552196521975219852199522005220152202522035220452205522065220752208522095221052211522125221352214522155221652217522185221952220522215222252223522245222552226522275222852229522305223152232522335223452235522365223752238522395224052241522425224352244522455224652247522485224952250522515225252253522545225552256522575225852259522605226152262522635226452265522665226752268522695227052271522725227352274522755227652277522785227952280522815228252283522845228552286522875228852289522905229152292522935229452295522965229752298522995230052301523025230352304523055230652307523085230952310523115231252313523145231552316523175231852319523205232152322523235232452325523265232752328523295233052331523325233352334523355233652337523385233952340523415234252343523445234552346523475234852349523505235152352523535235452355523565235752358523595236052361523625236352364523655236652367523685236952370523715237252373523745237552376523775237852379523805238152382523835238452385523865238752388523895239052391523925239352394523955239652397523985239952400524015240252403524045240552406524075240852409524105241152412524135241452415524165241752418524195242052421524225242352424524255242652427524285242952430524315243252433524345243552436524375243852439524405244152442524435244452445524465244752448524495245052451524525245352454524555245652457524585245952460524615246252463524645246552466524675246852469524705247152472524735247452475524765247752478524795248052481524825248352484524855248652487524885248952490524915249252493524945249552496524975249852499525005250152502525035250452505525065250752508525095251052511525125251352514525155251652517525185251952520525215252252523525245252552526525275252852529525305253152532525335253452535525365253752538525395254052541525425254352544525455254652547525485254952550525515255252553525545255552556525575255852559525605256152562525635256452565525665256752568525695257052571525725257352574525755257652577525785257952580525815258252583525845258552586525875258852589525905259152592525935259452595525965259752598525995260052601526025260352604526055260652607526085260952610526115261252613526145261552616526175261852619526205262152622526235262452625526265262752628526295263052631526325263352634526355263652637526385263952640526415264252643526445264552646526475264852649526505265152652526535265452655526565265752658526595266052661526625266352664526655266652667526685266952670526715267252673526745267552676526775267852679526805268152682526835268452685526865268752688526895269052691526925269352694526955269652697526985269952700527015270252703527045270552706527075270852709527105271152712527135271452715527165271752718527195272052721527225272352724527255272652727527285272952730527315273252733527345273552736527375273852739527405274152742527435274452745527465274752748527495275052751527525275352754527555275652757527585275952760527615276252763527645276552766527675276852769527705277152772527735277452775527765277752778527795278052781527825278352784527855278652787527885278952790527915279252793527945279552796527975279852799528005280152802528035280452805528065280752808528095281052811528125281352814528155281652817528185281952820528215282252823528245282552826528275282852829528305283152832528335283452835528365283752838528395284052841528425284352844528455284652847528485284952850528515285252853528545285552856528575285852859528605286152862528635286452865528665286752868528695287052871528725287352874528755287652877528785287952880528815288252883528845288552886528875288852889528905289152892528935289452895528965289752898528995290052901529025290352904529055290652907529085290952910529115291252913529145291552916529175291852919529205292152922529235292452925529265292752928529295293052931529325293352934529355293652937529385293952940529415294252943529445294552946529475294852949529505295152952529535295452955529565295752958529595296052961529625296352964529655296652967529685296952970529715297252973529745297552976529775297852979529805298152982529835298452985529865298752988529895299052991529925299352994529955299652997529985299953000530015300253003530045300553006530075300853009530105301153012530135301453015530165301753018530195302053021530225302353024530255302653027530285302953030530315303253033530345303553036530375303853039530405304153042530435304453045530465304753048530495305053051530525305353054530555305653057530585305953060530615306253063530645306553066530675306853069530705307153072530735307453075530765307753078530795308053081530825308353084530855308653087530885308953090530915309253093530945309553096530975309853099531005310153102531035310453105531065310753108531095311053111531125311353114531155311653117531185311953120531215312253123531245312553126531275312853129531305313153132531335313453135531365313753138531395314053141531425314353144531455314653147531485314953150531515315253153531545315553156531575315853159531605316153162531635316453165531665316753168531695317053171531725317353174531755317653177531785317953180531815318253183531845318553186531875318853189531905319153192531935319453195531965319753198531995320053201532025320353204532055320653207532085320953210532115321253213532145321553216532175321853219532205322153222532235322453225532265322753228532295323053231532325323353234532355323653237532385323953240532415324253243532445324553246532475324853249532505325153252532535325453255532565325753258532595326053261532625326353264532655326653267532685326953270532715327253273532745327553276532775327853279532805328153282532835328453285532865328753288532895329053291532925329353294532955329653297532985329953300533015330253303533045330553306533075330853309533105331153312533135331453315533165331753318533195332053321533225332353324533255332653327533285332953330533315333253333533345333553336533375333853339533405334153342533435334453345533465334753348533495335053351533525335353354533555335653357533585335953360533615336253363533645336553366533675336853369533705337153372533735337453375533765337753378533795338053381533825338353384533855338653387533885338953390533915339253393533945339553396533975339853399534005340153402534035340453405534065340753408534095341053411534125341353414534155341653417534185341953420534215342253423534245342553426534275342853429534305343153432534335343453435534365343753438534395344053441534425344353444534455344653447534485344953450534515345253453534545345553456534575345853459534605346153462534635346453465534665346753468534695347053471534725347353474534755347653477534785347953480534815348253483534845348553486534875348853489534905349153492534935349453495534965349753498534995350053501535025350353504535055350653507535085350953510535115351253513535145351553516535175351853519535205352153522535235352453525535265352753528535295353053531535325353353534535355353653537535385353953540535415354253543535445354553546535475354853549535505355153552535535355453555535565355753558535595356053561535625356353564535655356653567535685356953570535715357253573535745357553576535775357853579535805358153582535835358453585535865358753588535895359053591535925359353594535955359653597535985359953600536015360253603536045360553606536075360853609536105361153612536135361453615536165361753618536195362053621536225362353624536255362653627536285362953630536315363253633536345363553636536375363853639536405364153642536435364453645536465364753648536495365053651536525365353654536555365653657536585365953660536615366253663536645366553666536675366853669536705367153672536735367453675536765367753678536795368053681536825368353684536855368653687536885368953690536915369253693536945369553696536975369853699537005370153702537035370453705537065370753708537095371053711537125371353714537155371653717537185371953720537215372253723537245372553726537275372853729537305373153732537335373453735537365373753738537395374053741537425374353744537455374653747537485374953750537515375253753537545375553756537575375853759537605376153762537635376453765537665376753768537695377053771537725377353774537755377653777537785377953780537815378253783537845378553786537875378853789537905379153792537935379453795537965379753798537995380053801538025380353804538055380653807538085380953810538115381253813538145381553816538175381853819538205382153822538235382453825538265382753828538295383053831538325383353834538355383653837538385383953840538415384253843538445384553846538475384853849538505385153852538535385453855538565385753858538595386053861538625386353864538655386653867538685386953870538715387253873538745387553876538775387853879538805388153882538835388453885538865388753888538895389053891538925389353894538955389653897538985389953900539015390253903539045390553906539075390853909539105391153912539135391453915539165391753918539195392053921539225392353924539255392653927539285392953930539315393253933539345393553936539375393853939539405394153942539435394453945539465394753948539495395053951539525395353954539555395653957539585395953960539615396253963539645396553966539675396853969539705397153972539735397453975539765397753978539795398053981539825398353984539855398653987539885398953990539915399253993539945399553996539975399853999540005400154002540035400454005540065400754008540095401054011540125401354014540155401654017540185401954020540215402254023540245402554026540275402854029540305403154032540335403454035540365403754038540395404054041540425404354044540455404654047540485404954050540515405254053540545405554056540575405854059540605406154062540635406454065540665406754068540695407054071540725407354074540755407654077540785407954080540815408254083540845408554086540875408854089540905409154092540935409454095540965409754098540995410054101541025410354104541055410654107541085410954110541115411254113541145411554116541175411854119541205412154122541235412454125541265412754128541295413054131541325413354134541355413654137541385413954140541415414254143541445414554146541475414854149541505415154152541535415454155541565415754158541595416054161541625416354164541655416654167541685416954170541715417254173541745417554176541775417854179541805418154182541835418454185541865418754188541895419054191541925419354194541955419654197541985419954200542015420254203542045420554206542075420854209542105421154212542135421454215542165421754218542195422054221542225422354224542255422654227542285422954230542315423254233542345423554236542375423854239542405424154242542435424454245542465424754248542495425054251542525425354254542555425654257542585425954260542615426254263542645426554266542675426854269542705427154272542735427454275542765427754278542795428054281542825428354284542855428654287542885428954290542915429254293542945429554296542975429854299543005430154302543035430454305543065430754308543095431054311543125431354314543155431654317543185431954320543215432254323543245432554326543275432854329543305433154332543335433454335543365433754338543395434054341543425434354344543455434654347543485434954350543515435254353543545435554356543575435854359543605436154362543635436454365543665436754368543695437054371543725437354374543755437654377543785437954380543815438254383543845438554386543875438854389543905439154392543935439454395543965439754398543995440054401544025440354404544055440654407544085440954410544115441254413544145441554416544175441854419544205442154422544235442454425544265442754428544295443054431544325443354434544355443654437544385443954440544415444254443544445444554446544475444854449544505445154452544535445454455544565445754458544595446054461544625446354464544655446654467544685446954470544715447254473544745447554476544775447854479544805448154482544835448454485544865448754488544895449054491544925449354494544955449654497544985449954500545015450254503545045450554506545075450854509545105451154512545135451454515545165451754518545195452054521545225452354524545255452654527545285452954530545315453254533545345453554536545375453854539545405454154542545435454454545545465454754548545495455054551545525455354554545555455654557545585455954560545615456254563545645456554566545675456854569545705457154572545735457454575545765457754578545795458054581545825458354584545855458654587545885458954590545915459254593545945459554596545975459854599546005460154602546035460454605546065460754608546095461054611546125461354614546155461654617546185461954620546215462254623546245462554626546275462854629546305463154632546335463454635546365463754638546395464054641546425464354644546455464654647546485464954650546515465254653546545465554656546575465854659546605466154662546635466454665546665466754668546695467054671546725467354674546755467654677546785467954680546815468254683546845468554686546875468854689546905469154692546935469454695546965469754698546995470054701547025470354704547055470654707547085470954710547115471254713547145471554716547175471854719547205472154722547235472454725547265472754728547295473054731547325473354734547355473654737547385473954740547415474254743547445474554746547475474854749547505475154752547535475454755547565475754758547595476054761547625476354764547655476654767547685476954770547715477254773547745477554776547775477854779547805478154782547835478454785547865478754788547895479054791547925479354794547955479654797547985479954800548015480254803548045480554806548075480854809548105481154812548135481454815548165481754818548195482054821548225482354824548255482654827548285482954830548315483254833548345483554836548375483854839548405484154842548435484454845548465484754848548495485054851548525485354854548555485654857548585485954860548615486254863548645486554866548675486854869548705487154872548735487454875548765487754878548795488054881548825488354884548855488654887548885488954890548915489254893548945489554896548975489854899549005490154902549035490454905549065490754908549095491054911549125491354914549155491654917549185491954920549215492254923549245492554926549275492854929549305493154932549335493454935549365493754938549395494054941549425494354944549455494654947549485494954950549515495254953549545495554956549575495854959549605496154962549635496454965549665496754968549695497054971549725497354974549755497654977549785497954980549815498254983549845498554986549875498854989549905499154992549935499454995549965499754998549995500055001550025500355004550055500655007550085500955010550115501255013550145501555016550175501855019550205502155022550235502455025550265502755028550295503055031550325503355034550355503655037550385503955040550415504255043550445504555046550475504855049550505505155052550535505455055550565505755058550595506055061550625506355064550655506655067550685506955070550715507255073550745507555076550775507855079550805508155082550835508455085550865508755088550895509055091550925509355094550955509655097550985509955100551015510255103551045510555106551075510855109551105511155112551135511455115551165511755118551195512055121551225512355124551255512655127551285512955130551315513255133551345513555136551375513855139551405514155142551435514455145551465514755148551495515055151551525515355154551555515655157551585515955160551615516255163551645516555166551675516855169551705517155172551735517455175551765517755178551795518055181551825518355184551855518655187551885518955190551915519255193551945519555196551975519855199552005520155202552035520455205552065520755208552095521055211552125521355214552155521655217552185521955220552215522255223552245522555226552275522855229552305523155232552335523455235552365523755238552395524055241552425524355244552455524655247552485524955250552515525255253552545525555256552575525855259552605526155262552635526455265552665526755268552695527055271552725527355274552755527655277552785527955280552815528255283552845528555286552875528855289552905529155292552935529455295552965529755298552995530055301553025530355304553055530655307553085530955310553115531255313553145531555316553175531855319553205532155322553235532455325553265532755328553295533055331553325533355334553355533655337553385533955340553415534255343553445534555346553475534855349553505535155352553535535455355553565535755358553595536055361553625536355364553655536655367553685536955370553715537255373553745537555376553775537855379553805538155382553835538455385553865538755388553895539055391553925539355394553955539655397553985539955400554015540255403554045540555406554075540855409554105541155412554135541455415554165541755418554195542055421554225542355424554255542655427554285542955430554315543255433554345543555436554375543855439554405544155442554435544455445554465544755448554495545055451554525545355454554555545655457554585545955460554615546255463554645546555466554675546855469554705547155472554735547455475554765547755478554795548055481554825548355484554855548655487554885548955490554915549255493554945549555496554975549855499555005550155502555035550455505555065550755508555095551055511555125551355514555155551655517555185551955520555215552255523555245552555526555275552855529555305553155532555335553455535555365553755538555395554055541555425554355544555455554655547555485554955550555515555255553555545555555556555575555855559555605556155562555635556455565555665556755568555695557055571555725557355574555755557655577555785557955580555815558255583555845558555586555875558855589555905559155592555935559455595555965559755598555995560055601556025560355604556055560655607556085560955610556115561255613556145561555616556175561855619556205562155622556235562455625556265562755628556295563055631556325563355634556355563655637556385563955640556415564255643556445564555646556475564855649556505565155652556535565455655556565565755658556595566055661556625566355664556655566655667556685566955670556715567255673556745567555676556775567855679556805568155682556835568455685556865568755688556895569055691556925569355694556955569655697556985569955700557015570255703557045570555706557075570855709557105571155712557135571455715557165571755718557195572055721557225572355724557255572655727557285572955730557315573255733557345573555736557375573855739557405574155742557435574455745557465574755748557495575055751557525575355754557555575655757557585575955760557615576255763557645576555766557675576855769557705577155772557735577455775557765577755778557795578055781557825578355784557855578655787557885578955790557915579255793557945579555796557975579855799558005580155802558035580455805558065580755808558095581055811558125581355814558155581655817558185581955820558215582255823558245582555826558275582855829558305583155832558335583455835558365583755838558395584055841558425584355844558455584655847558485584955850558515585255853558545585555856558575585855859558605586155862558635586455865558665586755868558695587055871558725587355874558755587655877558785587955880558815588255883558845588555886558875588855889558905589155892558935589455895558965589755898558995590055901559025590355904559055590655907559085590955910559115591255913559145591555916559175591855919559205592155922559235592455925559265592755928559295593055931559325593355934559355593655937559385593955940559415594255943559445594555946559475594855949559505595155952559535595455955559565595755958559595596055961559625596355964559655596655967559685596955970559715597255973559745597555976559775597855979559805598155982559835598455985559865598755988559895599055991559925599355994559955599655997559985599956000560015600256003560045600556006560075600856009560105601156012560135601456015560165601756018560195602056021560225602356024560255602656027560285602956030560315603256033560345603556036560375603856039560405604156042560435604456045560465604756048560495605056051560525605356054560555605656057560585605956060560615606256063560645606556066560675606856069560705607156072560735607456075560765607756078560795608056081560825608356084560855608656087560885608956090560915609256093560945609556096560975609856099561005610156102561035610456105561065610756108561095611056111561125611356114561155611656117561185611956120561215612256123561245612556126561275612856129561305613156132561335613456135561365613756138561395614056141561425614356144561455614656147561485614956150561515615256153561545615556156561575615856159561605616156162561635616456165561665616756168561695617056171561725617356174561755617656177561785617956180561815618256183561845618556186561875618856189561905619156192561935619456195561965619756198561995620056201562025620356204562055620656207562085620956210562115621256213562145621556216562175621856219562205622156222562235622456225562265622756228562295623056231562325623356234562355623656237562385623956240562415624256243562445624556246562475624856249562505625156252562535625456255562565625756258562595626056261562625626356264562655626656267562685626956270562715627256273562745627556276562775627856279562805628156282562835628456285562865628756288562895629056291562925629356294562955629656297562985629956300563015630256303563045630556306563075630856309563105631156312563135631456315563165631756318563195632056321563225632356324563255632656327563285632956330563315633256333563345633556336563375633856339563405634156342563435634456345563465634756348563495635056351563525635356354563555635656357563585635956360563615636256363563645636556366563675636856369563705637156372563735637456375563765637756378563795638056381563825638356384563855638656387563885638956390563915639256393563945639556396563975639856399564005640156402564035640456405564065640756408564095641056411564125641356414564155641656417564185641956420564215642256423564245642556426564275642856429564305643156432564335643456435564365643756438564395644056441564425644356444564455644656447564485644956450564515645256453564545645556456564575645856459564605646156462564635646456465564665646756468564695647056471564725647356474564755647656477564785647956480564815648256483564845648556486564875648856489564905649156492564935649456495564965649756498564995650056501565025650356504565055650656507565085650956510565115651256513565145651556516565175651856519565205652156522565235652456525565265652756528565295653056531565325653356534565355653656537565385653956540565415654256543565445654556546565475654856549565505655156552565535655456555565565655756558565595656056561565625656356564565655656656567565685656956570565715657256573565745657556576565775657856579565805658156582565835658456585565865658756588565895659056591565925659356594565955659656597565985659956600566015660256603566045660556606566075660856609566105661156612566135661456615566165661756618566195662056621566225662356624566255662656627566285662956630566315663256633566345663556636566375663856639566405664156642566435664456645566465664756648566495665056651566525665356654566555665656657566585665956660566615666256663566645666556666566675666856669566705667156672566735667456675566765667756678566795668056681566825668356684566855668656687566885668956690566915669256693566945669556696566975669856699567005670156702567035670456705567065670756708567095671056711567125671356714567155671656717567185671956720567215672256723567245672556726567275672856729567305673156732567335673456735567365673756738567395674056741567425674356744567455674656747567485674956750567515675256753567545675556756567575675856759567605676156762567635676456765567665676756768567695677056771567725677356774567755677656777567785677956780567815678256783567845678556786567875678856789567905679156792567935679456795567965679756798567995680056801568025680356804568055680656807568085680956810568115681256813568145681556816568175681856819568205682156822568235682456825568265682756828568295683056831568325683356834568355683656837568385683956840568415684256843568445684556846568475684856849568505685156852568535685456855568565685756858568595686056861568625686356864568655686656867568685686956870568715687256873568745687556876568775687856879568805688156882568835688456885568865688756888568895689056891568925689356894568955689656897568985689956900569015690256903569045690556906569075690856909569105691156912569135691456915569165691756918569195692056921569225692356924569255692656927569285692956930569315693256933569345693556936569375693856939569405694156942569435694456945569465694756948569495695056951569525695356954569555695656957569585695956960569615696256963569645696556966569675696856969569705697156972569735697456975569765697756978569795698056981569825698356984569855698656987569885698956990569915699256993569945699556996569975699856999570005700157002570035700457005570065700757008570095701057011570125701357014570155701657017570185701957020570215702257023570245702557026570275702857029570305703157032570335703457035570365703757038570395704057041570425704357044570455704657047570485704957050570515705257053570545705557056570575705857059570605706157062570635706457065570665706757068570695707057071570725707357074570755707657077570785707957080570815708257083570845708557086570875708857089570905709157092570935709457095570965709757098570995710057101571025710357104571055710657107571085710957110571115711257113571145711557116571175711857119571205712157122571235712457125571265712757128571295713057131571325713357134571355713657137571385713957140571415714257143571445714557146571475714857149571505715157152571535715457155571565715757158571595716057161571625716357164571655716657167571685716957170571715717257173571745717557176571775717857179571805718157182571835718457185571865718757188571895719057191571925719357194571955719657197571985719957200572015720257203572045720557206572075720857209572105721157212572135721457215572165721757218572195722057221572225722357224572255722657227572285722957230572315723257233572345723557236572375723857239572405724157242572435724457245572465724757248572495725057251572525725357254572555725657257572585725957260572615726257263572645726557266572675726857269572705727157272572735727457275572765727757278572795728057281572825728357284572855728657287572885728957290572915729257293572945729557296572975729857299573005730157302573035730457305573065730757308573095731057311573125731357314573155731657317573185731957320573215732257323573245732557326573275732857329573305733157332573335733457335573365733757338573395734057341573425734357344573455734657347573485734957350573515735257353573545735557356573575735857359573605736157362573635736457365573665736757368573695737057371573725737357374573755737657377573785737957380573815738257383573845738557386573875738857389573905739157392573935739457395573965739757398573995740057401574025740357404574055740657407574085740957410574115741257413574145741557416574175741857419574205742157422574235742457425574265742757428574295743057431574325743357434574355743657437574385743957440574415744257443574445744557446574475744857449574505745157452574535745457455574565745757458574595746057461574625746357464574655746657467574685746957470574715747257473574745747557476574775747857479574805748157482574835748457485574865748757488574895749057491574925749357494574955749657497574985749957500575015750257503575045750557506575075750857509575105751157512575135751457515575165751757518575195752057521575225752357524575255752657527575285752957530575315753257533575345753557536575375753857539575405754157542575435754457545575465754757548575495755057551575525755357554575555755657557575585755957560575615756257563575645756557566575675756857569575705757157572575735757457575575765757757578575795758057581575825758357584575855758657587575885758957590575915759257593575945759557596575975759857599576005760157602576035760457605576065760757608576095761057611576125761357614576155761657617576185761957620576215762257623576245762557626576275762857629576305763157632576335763457635576365763757638576395764057641576425764357644576455764657647576485764957650576515765257653576545765557656576575765857659576605766157662576635766457665576665766757668576695767057671576725767357674576755767657677576785767957680576815768257683576845768557686576875768857689576905769157692576935769457695576965769757698576995770057701577025770357704577055770657707577085770957710577115771257713577145771557716577175771857719577205772157722577235772457725577265772757728577295773057731577325773357734577355773657737577385773957740577415774257743577445774557746577475774857749577505775157752577535775457755577565775757758577595776057761577625776357764577655776657767577685776957770577715777257773577745777557776577775777857779577805778157782577835778457785577865778757788577895779057791577925779357794577955779657797577985779957800578015780257803578045780557806578075780857809578105781157812578135781457815578165781757818578195782057821578225782357824578255782657827578285782957830578315783257833578345783557836578375783857839578405784157842578435784457845578465784757848578495785057851578525785357854578555785657857578585785957860578615786257863578645786557866578675786857869578705787157872578735787457875578765787757878578795788057881578825788357884578855788657887578885788957890578915789257893578945789557896578975789857899579005790157902579035790457905579065790757908579095791057911579125791357914579155791657917579185791957920579215792257923579245792557926579275792857929579305793157932579335793457935579365793757938579395794057941579425794357944579455794657947579485794957950579515795257953579545795557956579575795857959579605796157962579635796457965579665796757968579695797057971579725797357974579755797657977579785797957980579815798257983579845798557986579875798857989579905799157992579935799457995579965799757998579995800058001580025800358004580055800658007580085800958010580115801258013580145801558016580175801858019580205802158022580235802458025580265802758028580295803058031580325803358034580355803658037580385803958040580415804258043580445804558046580475804858049580505805158052580535805458055580565805758058580595806058061580625806358064580655806658067580685806958070580715807258073580745807558076580775807858079580805808158082580835808458085580865808758088580895809058091580925809358094580955809658097580985809958100581015810258103581045810558106581075810858109581105811158112581135811458115581165811758118581195812058121581225812358124581255812658127581285812958130581315813258133581345813558136581375813858139581405814158142581435814458145581465814758148581495815058151581525815358154581555815658157581585815958160581615816258163581645816558166581675816858169581705817158172581735817458175581765817758178581795818058181581825818358184581855818658187581885818958190581915819258193581945819558196581975819858199582005820158202582035820458205582065820758208582095821058211582125821358214582155821658217582185821958220582215822258223582245822558226582275822858229582305823158232582335823458235582365823758238582395824058241582425824358244582455824658247582485824958250582515825258253582545825558256582575825858259582605826158262582635826458265582665826758268582695827058271582725827358274582755827658277582785827958280582815828258283582845828558286582875828858289582905829158292582935829458295582965829758298582995830058301583025830358304583055830658307583085830958310583115831258313583145831558316583175831858319583205832158322583235832458325583265832758328583295833058331583325833358334583355833658337583385833958340583415834258343583445834558346583475834858349583505835158352583535835458355583565835758358583595836058361583625836358364583655836658367583685836958370583715837258373583745837558376583775837858379583805838158382583835838458385583865838758388583895839058391583925839358394583955839658397583985839958400584015840258403584045840558406584075840858409584105841158412584135841458415584165841758418584195842058421584225842358424584255842658427584285842958430584315843258433584345843558436584375843858439584405844158442584435844458445584465844758448584495845058451584525845358454584555845658457584585845958460584615846258463584645846558466584675846858469584705847158472584735847458475584765847758478584795848058481584825848358484584855848658487584885848958490584915849258493584945849558496584975849858499585005850158502585035850458505585065850758508585095851058511585125851358514585155851658517585185851958520585215852258523585245852558526585275852858529585305853158532585335853458535585365853758538585395854058541585425854358544585455854658547585485854958550585515855258553585545855558556585575855858559585605856158562585635856458565585665856758568585695857058571585725857358574585755857658577585785857958580585815858258583585845858558586585875858858589585905859158592585935859458595585965859758598585995860058601586025860358604586055860658607586085860958610586115861258613586145861558616586175861858619586205862158622586235862458625586265862758628586295863058631586325863358634586355863658637586385863958640586415864258643586445864558646586475864858649586505865158652586535865458655586565865758658586595866058661586625866358664586655866658667586685866958670586715867258673586745867558676586775867858679586805868158682586835868458685586865868758688586895869058691586925869358694586955869658697586985869958700587015870258703587045870558706587075870858709587105871158712587135871458715587165871758718587195872058721587225872358724587255872658727587285872958730587315873258733587345873558736587375873858739587405874158742587435874458745587465874758748587495875058751587525875358754587555875658757587585875958760587615876258763587645876558766587675876858769587705877158772587735877458775587765877758778587795878058781587825878358784587855878658787587885878958790587915879258793587945879558796587975879858799588005880158802588035880458805588065880758808588095881058811588125881358814588155881658817588185881958820588215882258823588245882558826588275882858829588305883158832588335883458835588365883758838588395884058841588425884358844588455884658847588485884958850588515885258853588545885558856588575885858859588605886158862588635886458865588665886758868588695887058871588725887358874588755887658877588785887958880588815888258883588845888558886588875888858889588905889158892588935889458895588965889758898588995890058901589025890358904589055890658907589085890958910589115891258913589145891558916589175891858919589205892158922589235892458925589265892758928589295893058931589325893358934589355893658937589385893958940589415894258943589445894558946589475894858949589505895158952589535895458955589565895758958589595896058961589625896358964589655896658967589685896958970589715897258973589745897558976589775897858979589805898158982589835898458985589865898758988589895899058991589925899358994589955899658997589985899959000590015900259003590045900559006590075900859009590105901159012590135901459015590165901759018590195902059021590225902359024590255902659027590285902959030590315903259033590345903559036590375903859039590405904159042590435904459045590465904759048590495905059051590525905359054590555905659057590585905959060590615906259063590645906559066590675906859069590705907159072590735907459075590765907759078590795908059081590825908359084590855908659087590885908959090590915909259093590945909559096590975909859099591005910159102591035910459105591065910759108591095911059111591125911359114591155911659117591185911959120591215912259123591245912559126591275912859129591305913159132591335913459135591365913759138591395914059141591425914359144591455914659147591485914959150591515915259153591545915559156591575915859159591605916159162591635916459165591665916759168591695917059171591725917359174591755917659177591785917959180591815918259183591845918559186591875918859189591905919159192591935919459195591965919759198591995920059201592025920359204592055920659207592085920959210592115921259213592145921559216592175921859219592205922159222592235922459225592265922759228592295923059231592325923359234592355923659237592385923959240592415924259243592445924559246592475924859249592505925159252592535925459255592565925759258592595926059261592625926359264592655926659267592685926959270592715927259273592745927559276592775927859279592805928159282592835928459285592865928759288592895929059291592925929359294592955929659297592985929959300593015930259303593045930559306593075930859309593105931159312593135931459315593165931759318593195932059321593225932359324593255932659327593285932959330593315933259333593345933559336593375933859339593405934159342593435934459345593465934759348593495935059351593525935359354593555935659357593585935959360593615936259363593645936559366593675936859369593705937159372593735937459375593765937759378593795938059381593825938359384593855938659387593885938959390593915939259393593945939559396593975939859399594005940159402594035940459405594065940759408594095941059411594125941359414594155941659417594185941959420594215942259423594245942559426594275942859429594305943159432594335943459435594365943759438594395944059441594425944359444594455944659447594485944959450594515945259453594545945559456594575945859459594605946159462594635946459465594665946759468594695947059471594725947359474594755947659477594785947959480594815948259483594845948559486594875948859489594905949159492594935949459495594965949759498594995950059501595025950359504595055950659507595085950959510595115951259513595145951559516595175951859519595205952159522595235952459525595265952759528595295953059531595325953359534595355953659537595385953959540595415954259543595445954559546595475954859549595505955159552595535955459555595565955759558595595956059561595625956359564595655956659567595685956959570595715957259573595745957559576595775957859579595805958159582595835958459585595865958759588595895959059591595925959359594595955959659597595985959959600596015960259603596045960559606596075960859609596105961159612596135961459615596165961759618596195962059621596225962359624596255962659627596285962959630596315963259633596345963559636596375963859639596405964159642596435964459645596465964759648596495965059651596525965359654596555965659657596585965959660596615966259663596645966559666596675966859669596705967159672596735967459675596765967759678596795968059681596825968359684596855968659687596885968959690596915969259693596945969559696596975969859699597005970159702597035970459705597065970759708597095971059711597125971359714597155971659717597185971959720597215972259723597245972559726597275972859729597305973159732597335973459735597365973759738597395974059741597425974359744597455974659747597485974959750597515975259753597545975559756597575975859759597605976159762597635976459765597665976759768597695977059771597725977359774597755977659777597785977959780597815978259783597845978559786597875978859789597905979159792597935979459795597965979759798597995980059801598025980359804598055980659807598085980959810598115981259813598145981559816598175981859819598205982159822598235982459825598265982759828598295983059831598325983359834598355983659837598385983959840598415984259843598445984559846598475984859849598505985159852598535985459855598565985759858598595986059861598625986359864598655986659867598685986959870598715987259873598745987559876598775987859879598805988159882598835988459885598865988759888598895989059891598925989359894598955989659897598985989959900599015990259903599045990559906599075990859909599105991159912599135991459915599165991759918599195992059921599225992359924599255992659927599285992959930599315993259933599345993559936599375993859939599405994159942599435994459945599465994759948599495995059951599525995359954599555995659957599585995959960599615996259963599645996559966599675996859969599705997159972599735997459975599765997759978599795998059981599825998359984599855998659987599885998959990599915999259993599945999559996599975999859999600006000160002600036000460005600066000760008600096001060011600126001360014600156001660017600186001960020600216002260023600246002560026600276002860029600306003160032600336003460035600366003760038600396004060041600426004360044600456004660047600486004960050600516005260053600546005560056600576005860059600606006160062600636006460065600666006760068600696007060071600726007360074600756007660077600786007960080600816008260083600846008560086600876008860089600906009160092600936009460095600966009760098600996010060101601026010360104601056010660107601086010960110601116011260113601146011560116601176011860119601206012160122601236012460125601266012760128601296013060131601326013360134601356013660137601386013960140601416014260143601446014560146601476014860149601506015160152601536015460155601566015760158601596016060161601626016360164601656016660167601686016960170601716017260173601746017560176601776017860179601806018160182601836018460185601866018760188601896019060191601926019360194601956019660197601986019960200602016020260203602046020560206602076020860209602106021160212602136021460215602166021760218602196022060221602226022360224602256022660227602286022960230602316023260233602346023560236602376023860239602406024160242602436024460245602466024760248602496025060251602526025360254602556025660257602586025960260602616026260263602646026560266602676026860269602706027160272602736027460275602766027760278602796028060281602826028360284602856028660287602886028960290602916029260293602946029560296602976029860299603006030160302603036030460305603066030760308603096031060311603126031360314603156031660317603186031960320603216032260323603246032560326603276032860329603306033160332603336033460335603366033760338603396034060341603426034360344603456034660347603486034960350603516035260353603546035560356603576035860359603606036160362603636036460365603666036760368603696037060371603726037360374603756037660377603786037960380603816038260383603846038560386603876038860389603906039160392603936039460395603966039760398603996040060401604026040360404604056040660407604086040960410604116041260413604146041560416604176041860419604206042160422604236042460425604266042760428604296043060431604326043360434604356043660437604386043960440604416044260443604446044560446604476044860449604506045160452604536045460455604566045760458604596046060461604626046360464604656046660467604686046960470604716047260473604746047560476604776047860479604806048160482604836048460485604866048760488604896049060491604926049360494604956049660497604986049960500605016050260503605046050560506605076050860509605106051160512605136051460515605166051760518605196052060521605226052360524605256052660527605286052960530605316053260533605346053560536605376053860539605406054160542605436054460545605466054760548605496055060551605526055360554605556055660557605586055960560605616056260563605646056560566605676056860569605706057160572605736057460575605766057760578605796058060581605826058360584605856058660587605886058960590605916059260593605946059560596605976059860599606006060160602606036060460605606066060760608606096061060611606126061360614606156061660617606186061960620606216062260623606246062560626606276062860629606306063160632606336063460635606366063760638606396064060641606426064360644606456064660647606486064960650606516065260653606546065560656606576065860659606606066160662606636066460665606666066760668606696067060671606726067360674606756067660677606786067960680606816068260683606846068560686606876068860689606906069160692606936069460695606966069760698606996070060701607026070360704607056070660707607086070960710607116071260713607146071560716607176071860719607206072160722607236072460725607266072760728607296073060731607326073360734607356073660737607386073960740607416074260743607446074560746607476074860749607506075160752607536075460755607566075760758607596076060761607626076360764607656076660767607686076960770607716077260773607746077560776607776077860779607806078160782607836078460785607866078760788607896079060791607926079360794607956079660797607986079960800608016080260803608046080560806608076080860809608106081160812608136081460815608166081760818608196082060821608226082360824608256082660827608286082960830608316083260833608346083560836608376083860839608406084160842608436084460845608466084760848608496085060851608526085360854608556085660857608586085960860608616086260863608646086560866608676086860869608706087160872608736087460875608766087760878608796088060881608826088360884608856088660887608886088960890608916089260893608946089560896608976089860899609006090160902609036090460905609066090760908609096091060911609126091360914609156091660917609186091960920609216092260923609246092560926609276092860929609306093160932609336093460935609366093760938609396094060941609426094360944609456094660947609486094960950609516095260953609546095560956609576095860959609606096160962609636096460965609666096760968609696097060971609726097360974609756097660977609786097960980609816098260983609846098560986609876098860989609906099160992609936099460995609966099760998609996100061001610026100361004610056100661007610086100961010610116101261013610146101561016610176101861019610206102161022610236102461025610266102761028610296103061031610326103361034610356103661037610386103961040610416104261043610446104561046610476104861049610506105161052610536105461055610566105761058610596106061061610626106361064610656106661067610686106961070610716107261073610746107561076610776107861079610806108161082610836108461085610866108761088610896109061091610926109361094610956109661097610986109961100611016110261103611046110561106611076110861109611106111161112611136111461115611166111761118611196112061121611226112361124611256112661127611286112961130611316113261133611346113561136611376113861139611406114161142611436114461145611466114761148611496115061151611526115361154611556115661157611586115961160611616116261163611646116561166611676116861169611706117161172611736117461175611766117761178611796118061181611826118361184611856118661187611886118961190611916119261193611946119561196611976119861199612006120161202612036120461205612066120761208612096121061211612126121361214612156121661217612186121961220612216122261223612246122561226612276122861229612306123161232612336123461235612366123761238612396124061241612426124361244612456124661247612486124961250612516125261253612546125561256612576125861259612606126161262612636126461265612666126761268612696127061271612726127361274612756127661277612786127961280612816128261283612846128561286612876128861289612906129161292612936129461295612966129761298612996130061301613026130361304613056130661307613086130961310613116131261313613146131561316613176131861319613206132161322613236132461325613266132761328613296133061331613326133361334613356133661337613386133961340613416134261343613446134561346613476134861349613506135161352613536135461355613566135761358613596136061361613626136361364613656136661367613686136961370613716137261373613746137561376613776137861379613806138161382613836138461385613866138761388613896139061391613926139361394613956139661397613986139961400614016140261403614046140561406614076140861409614106141161412614136141461415614166141761418614196142061421614226142361424614256142661427614286142961430614316143261433614346143561436614376143861439614406144161442614436144461445614466144761448614496145061451614526145361454614556145661457614586145961460614616146261463614646146561466614676146861469614706147161472614736147461475614766147761478614796148061481614826148361484614856148661487614886148961490614916149261493614946149561496614976149861499615006150161502615036150461505615066150761508615096151061511615126151361514615156151661517615186151961520615216152261523615246152561526615276152861529615306153161532615336153461535615366153761538615396154061541615426154361544615456154661547615486154961550615516155261553615546155561556615576155861559615606156161562615636156461565615666156761568615696157061571615726157361574615756157661577615786157961580615816158261583615846158561586615876158861589615906159161592615936159461595615966159761598615996160061601616026160361604616056160661607616086160961610616116161261613616146161561616616176161861619616206162161622616236162461625616266162761628616296163061631616326163361634616356163661637616386163961640616416164261643616446164561646616476164861649616506165161652616536165461655616566165761658616596166061661616626166361664616656166661667616686166961670616716167261673616746167561676616776167861679616806168161682616836168461685616866168761688616896169061691616926169361694616956169661697616986169961700617016170261703617046170561706617076170861709617106171161712617136171461715617166171761718617196172061721617226172361724617256172661727617286172961730617316173261733617346173561736617376173861739617406174161742617436174461745617466174761748617496175061751617526175361754617556175661757617586175961760617616176261763617646176561766617676176861769617706177161772617736177461775617766177761778617796178061781617826178361784617856178661787617886178961790617916179261793617946179561796617976179861799618006180161802618036180461805618066180761808618096181061811618126181361814618156181661817618186181961820618216182261823618246182561826618276182861829618306183161832618336183461835618366183761838618396184061841618426184361844618456184661847618486184961850618516185261853618546185561856618576185861859618606186161862618636186461865618666186761868618696187061871618726187361874618756187661877618786187961880618816188261883618846188561886618876188861889618906189161892618936189461895618966189761898618996190061901619026190361904619056190661907619086190961910619116191261913619146191561916619176191861919619206192161922619236192461925619266192761928619296193061931619326193361934619356193661937619386193961940619416194261943619446194561946619476194861949619506195161952619536195461955619566195761958619596196061961619626196361964619656196661967619686196961970619716197261973619746197561976619776197861979619806198161982619836198461985619866198761988619896199061991619926199361994619956199661997619986199962000620016200262003620046200562006620076200862009620106201162012620136201462015620166201762018620196202062021620226202362024620256202662027620286202962030620316203262033620346203562036620376203862039620406204162042620436204462045620466204762048620496205062051620526205362054620556205662057620586205962060620616206262063620646206562066620676206862069620706207162072620736207462075620766207762078620796208062081620826208362084620856208662087620886208962090620916209262093620946209562096620976209862099621006210162102621036210462105621066210762108621096211062111621126211362114621156211662117621186211962120621216212262123621246212562126621276212862129621306213162132621336213462135621366213762138621396214062141621426214362144621456214662147621486214962150621516215262153621546215562156621576215862159621606216162162621636216462165621666216762168621696217062171621726217362174621756217662177621786217962180621816218262183621846218562186621876218862189621906219162192621936219462195621966219762198621996220062201622026220362204622056220662207622086220962210622116221262213622146221562216622176221862219622206222162222622236222462225622266222762228622296223062231622326223362234622356223662237622386223962240622416224262243622446224562246622476224862249622506225162252622536225462255622566225762258622596226062261622626226362264622656226662267622686226962270622716227262273622746227562276622776227862279622806228162282622836228462285622866228762288622896229062291622926229362294622956229662297622986229962300623016230262303623046230562306623076230862309623106231162312623136231462315623166231762318623196232062321623226232362324623256232662327623286232962330623316233262333623346233562336623376233862339623406234162342623436234462345623466234762348623496235062351623526235362354623556235662357623586235962360623616236262363623646236562366623676236862369623706237162372623736237462375623766237762378623796238062381623826238362384623856238662387623886238962390623916239262393623946239562396623976239862399624006240162402624036240462405624066240762408624096241062411624126241362414624156241662417624186241962420624216242262423624246242562426624276242862429624306243162432624336243462435624366243762438624396244062441624426244362444624456244662447624486244962450624516245262453624546245562456624576245862459624606246162462624636246462465624666246762468624696247062471624726247362474624756247662477624786247962480624816248262483624846248562486624876248862489624906249162492624936249462495624966249762498624996250062501625026250362504625056250662507625086250962510625116251262513625146251562516625176251862519625206252162522625236252462525625266252762528625296253062531625326253362534625356253662537625386253962540625416254262543625446254562546625476254862549625506255162552625536255462555625566255762558625596256062561625626256362564625656256662567625686256962570625716257262573625746257562576625776257862579625806258162582625836258462585625866258762588625896259062591625926259362594625956259662597625986259962600626016260262603626046260562606626076260862609626106261162612626136261462615626166261762618626196262062621626226262362624626256262662627626286262962630626316263262633626346263562636626376263862639626406264162642626436264462645626466264762648626496265062651626526265362654626556265662657626586265962660626616266262663626646266562666626676266862669626706267162672626736267462675626766267762678626796268062681626826268362684626856268662687626886268962690626916269262693626946269562696626976269862699627006270162702627036270462705627066270762708627096271062711627126271362714627156271662717627186271962720627216272262723627246272562726627276272862729627306273162732627336273462735627366273762738627396274062741627426274362744627456274662747627486274962750627516275262753627546275562756627576275862759627606276162762627636276462765627666276762768627696277062771627726277362774627756277662777627786277962780627816278262783627846278562786627876278862789627906279162792627936279462795627966279762798627996280062801628026280362804628056280662807628086280962810628116281262813628146281562816628176281862819628206282162822628236282462825628266282762828628296283062831628326283362834628356283662837628386283962840628416284262843628446284562846628476284862849628506285162852628536285462855628566285762858628596286062861628626286362864628656286662867628686286962870628716287262873628746287562876628776287862879628806288162882628836288462885628866288762888628896289062891628926289362894628956289662897628986289962900629016290262903629046290562906629076290862909629106291162912629136291462915629166291762918629196292062921629226292362924629256292662927629286292962930629316293262933629346293562936629376293862939629406294162942629436294462945629466294762948629496295062951629526295362954629556295662957629586295962960629616296262963629646296562966629676296862969629706297162972629736297462975629766297762978629796298062981629826298362984629856298662987629886298962990629916299262993629946299562996629976299862999630006300163002630036300463005630066300763008630096301063011630126301363014630156301663017630186301963020630216302263023630246302563026630276302863029630306303163032630336303463035630366303763038630396304063041630426304363044630456304663047630486304963050630516305263053630546305563056630576305863059630606306163062630636306463065630666306763068630696307063071630726307363074630756307663077630786307963080630816308263083630846308563086630876308863089630906309163092630936309463095630966309763098630996310063101631026310363104631056310663107631086310963110631116311263113631146311563116631176311863119631206312163122631236312463125631266312763128631296313063131631326313363134631356313663137631386313963140631416314263143631446314563146631476314863149631506315163152631536315463155631566315763158631596316063161631626316363164631656316663167631686316963170631716317263173631746317563176631776317863179631806318163182631836318463185631866318763188631896319063191631926319363194631956319663197631986319963200632016320263203632046320563206632076320863209632106321163212632136321463215632166321763218632196322063221632226322363224632256322663227632286322963230632316323263233632346323563236632376323863239632406324163242632436324463245632466324763248632496325063251632526325363254632556325663257632586325963260632616326263263632646326563266632676326863269632706327163272632736327463275632766327763278632796328063281632826328363284632856328663287632886328963290632916329263293632946329563296632976329863299633006330163302633036330463305633066330763308633096331063311633126331363314633156331663317633186331963320633216332263323633246332563326633276332863329633306333163332633336333463335633366333763338633396334063341633426334363344633456334663347633486334963350633516335263353633546335563356633576335863359633606336163362633636336463365633666336763368633696337063371633726337363374633756337663377633786337963380633816338263383633846338563386633876338863389633906339163392633936339463395633966339763398633996340063401634026340363404634056340663407634086340963410634116341263413634146341563416634176341863419634206342163422634236342463425634266342763428634296343063431634326343363434634356343663437634386343963440634416344263443634446344563446634476344863449634506345163452634536345463455634566345763458634596346063461634626346363464634656346663467634686346963470634716347263473634746347563476634776347863479634806348163482634836348463485634866348763488634896349063491634926349363494634956349663497634986349963500635016350263503635046350563506635076350863509635106351163512635136351463515635166351763518635196352063521635226352363524635256352663527635286352963530635316353263533635346353563536635376353863539635406354163542635436354463545635466354763548635496355063551635526355363554635556355663557635586355963560635616356263563635646356563566635676356863569635706357163572635736357463575635766357763578635796358063581635826358363584635856358663587635886358963590635916359263593635946359563596635976359863599636006360163602636036360463605636066360763608636096361063611636126361363614636156361663617636186361963620636216362263623636246362563626636276362863629636306363163632636336363463635636366363763638636396364063641636426364363644636456364663647636486364963650636516365263653636546365563656636576365863659636606366163662636636366463665636666366763668636696367063671636726367363674636756367663677636786367963680636816368263683636846368563686636876368863689636906369163692636936369463695636966369763698636996370063701637026370363704637056370663707637086370963710637116371263713637146371563716637176371863719637206372163722637236372463725637266372763728637296373063731637326373363734637356373663737637386373963740637416374263743637446374563746637476374863749637506375163752637536375463755637566375763758637596376063761637626376363764637656376663767637686376963770637716377263773637746377563776637776377863779637806378163782637836378463785637866378763788637896379063791637926379363794637956379663797637986379963800638016380263803638046380563806638076380863809638106381163812638136381463815638166381763818638196382063821638226382363824638256382663827638286382963830638316383263833638346383563836638376383863839638406384163842638436384463845638466384763848638496385063851638526385363854638556385663857638586385963860638616386263863638646386563866638676386863869638706387163872638736387463875638766387763878638796388063881638826388363884638856388663887638886388963890638916389263893638946389563896638976389863899639006390163902639036390463905639066390763908639096391063911639126391363914639156391663917639186391963920639216392263923639246392563926639276392863929639306393163932639336393463935639366393763938639396394063941639426394363944639456394663947639486394963950639516395263953639546395563956639576395863959639606396163962639636396463965639666396763968639696397063971639726397363974639756397663977639786397963980639816398263983639846398563986639876398863989639906399163992639936399463995639966399763998639996400064001640026400364004640056400664007640086400964010640116401264013640146401564016640176401864019640206402164022640236402464025640266402764028640296403064031640326403364034640356403664037640386403964040640416404264043640446404564046640476404864049640506405164052640536405464055640566405764058640596406064061640626406364064640656406664067640686406964070640716407264073640746407564076640776407864079640806408164082640836408464085640866408764088640896409064091640926409364094640956409664097640986409964100641016410264103641046410564106641076410864109641106411164112641136411464115641166411764118641196412064121641226412364124641256412664127641286412964130641316413264133641346413564136641376413864139641406414164142641436414464145641466414764148641496415064151641526415364154641556415664157641586415964160641616416264163641646416564166641676416864169641706417164172641736417464175641766417764178641796418064181641826418364184641856418664187641886418964190641916419264193641946419564196641976419864199642006420164202642036420464205642066420764208642096421064211642126421364214642156421664217642186421964220642216422264223642246422564226642276422864229642306423164232642336423464235642366423764238642396424064241642426424364244642456424664247642486424964250642516425264253642546425564256642576425864259642606426164262642636426464265642666426764268642696427064271642726427364274642756427664277642786427964280642816428264283642846428564286642876428864289642906429164292642936429464295642966429764298642996430064301643026430364304643056430664307643086430964310643116431264313643146431564316643176431864319643206432164322643236432464325643266432764328643296433064331643326433364334643356433664337643386433964340643416434264343643446434564346643476434864349643506435164352643536435464355643566435764358643596436064361643626436364364643656436664367643686436964370643716437264373643746437564376643776437864379643806438164382643836438464385643866438764388643896439064391643926439364394643956439664397643986439964400644016440264403644046440564406644076440864409644106441164412644136441464415644166441764418644196442064421644226442364424644256442664427644286442964430644316443264433644346443564436644376443864439644406444164442644436444464445644466444764448644496445064451644526445364454644556445664457644586445964460644616446264463644646446564466644676446864469644706447164472644736447464475644766447764478644796448064481644826448364484644856448664487644886448964490644916449264493644946449564496644976449864499645006450164502645036450464505645066450764508645096451064511645126451364514645156451664517645186451964520645216452264523645246452564526645276452864529645306453164532645336453464535645366453764538645396454064541645426454364544645456454664547645486454964550645516455264553645546455564556645576455864559645606456164562645636456464565645666456764568645696457064571645726457364574645756457664577645786457964580645816458264583645846458564586645876458864589645906459164592645936459464595645966459764598645996460064601646026460364604646056460664607646086460964610646116461264613646146461564616646176461864619646206462164622646236462464625646266462764628646296463064631646326463364634646356463664637646386463964640646416464264643646446464564646646476464864649646506465164652646536465464655646566465764658646596466064661646626466364664646656466664667646686466964670646716467264673646746467564676646776467864679646806468164682646836468464685646866468764688646896469064691646926469364694646956469664697646986469964700647016470264703647046470564706647076470864709647106471164712647136471464715647166471764718647196472064721647226472364724647256472664727647286472964730647316473264733647346473564736647376473864739647406474164742647436474464745647466474764748647496475064751647526475364754647556475664757647586475964760647616476264763647646476564766647676476864769647706477164772647736477464775647766477764778647796478064781647826478364784647856478664787647886478964790647916479264793647946479564796647976479864799648006480164802648036480464805648066480764808648096481064811648126481364814648156481664817648186481964820648216482264823648246482564826648276482864829648306483164832648336483464835648366483764838648396484064841648426484364844648456484664847648486484964850648516485264853648546485564856648576485864859648606486164862648636486464865648666486764868648696487064871648726487364874648756487664877648786487964880648816488264883648846488564886648876488864889648906489164892648936489464895648966489764898648996490064901649026490364904649056490664907649086490964910649116491264913649146491564916649176491864919649206492164922649236492464925649266492764928649296493064931649326493364934649356493664937649386493964940649416494264943649446494564946649476494864949649506495164952649536495464955649566495764958649596496064961649626496364964649656496664967649686496964970649716497264973649746497564976649776497864979649806498164982649836498464985649866498764988649896499064991649926499364994649956499664997649986499965000650016500265003650046500565006650076500865009650106501165012650136501465015650166501765018650196502065021650226502365024650256502665027650286502965030650316503265033650346503565036650376503865039650406504165042650436504465045650466504765048650496505065051650526505365054650556505665057650586505965060650616506265063650646506565066650676506865069650706507165072650736507465075650766507765078650796508065081650826508365084650856508665087650886508965090650916509265093650946509565096650976509865099651006510165102651036510465105651066510765108651096511065111651126511365114651156511665117651186511965120651216512265123651246512565126651276512865129651306513165132651336513465135651366513765138651396514065141651426514365144651456514665147651486514965150651516515265153651546515565156651576515865159651606516165162651636516465165651666516765168651696517065171651726517365174651756517665177651786517965180651816518265183651846518565186651876518865189651906519165192651936519465195651966519765198651996520065201652026520365204652056520665207652086520965210652116521265213652146521565216652176521865219652206522165222652236522465225652266522765228652296523065231652326523365234652356523665237652386523965240652416524265243652446524565246652476524865249652506525165252652536525465255652566525765258652596526065261652626526365264652656526665267652686526965270652716527265273652746527565276652776527865279652806528165282652836528465285652866528765288652896529065291652926529365294652956529665297652986529965300653016530265303653046530565306653076530865309653106531165312653136531465315653166531765318653196532065321653226532365324653256532665327653286532965330653316533265333653346533565336653376533865339653406534165342653436534465345653466534765348653496535065351653526535365354653556535665357653586535965360653616536265363653646536565366653676536865369653706537165372653736537465375653766537765378653796538065381653826538365384653856538665387653886538965390653916539265393653946539565396653976539865399654006540165402654036540465405654066540765408654096541065411654126541365414654156541665417654186541965420654216542265423654246542565426654276542865429654306543165432654336543465435654366543765438654396544065441654426544365444654456544665447654486544965450654516545265453654546545565456654576545865459654606546165462654636546465465654666546765468654696547065471654726547365474654756547665477654786547965480654816548265483654846548565486654876548865489654906549165492654936549465495654966549765498654996550065501655026550365504655056550665507655086550965510655116551265513655146551565516655176551865519655206552165522655236552465525655266552765528655296553065531655326553365534655356553665537655386553965540655416554265543655446554565546655476554865549655506555165552655536555465555655566555765558655596556065561655626556365564655656556665567655686556965570655716557265573655746557565576655776557865579655806558165582655836558465585655866558765588655896559065591655926559365594655956559665597655986559965600656016560265603656046560565606656076560865609656106561165612656136561465615656166561765618656196562065621656226562365624656256562665627656286562965630656316563265633656346563565636656376563865639656406564165642656436564465645656466564765648656496565065651656526565365654656556565665657656586565965660656616566265663656646566565666656676566865669656706567165672656736567465675656766567765678656796568065681656826568365684656856568665687656886568965690656916569265693656946569565696656976569865699657006570165702657036570465705657066570765708657096571065711657126571365714657156571665717657186571965720657216572265723657246572565726657276572865729657306573165732657336573465735657366573765738657396574065741657426574365744657456574665747657486574965750657516575265753657546575565756657576575865759657606576165762657636576465765657666576765768657696577065771657726577365774657756577665777657786577965780657816578265783657846578565786657876578865789657906579165792657936579465795657966579765798657996580065801658026580365804658056580665807658086580965810658116581265813658146581565816658176581865819658206582165822658236582465825658266582765828658296583065831658326583365834658356583665837658386583965840658416584265843658446584565846658476584865849658506585165852658536585465855658566585765858658596586065861658626586365864658656586665867658686586965870658716587265873658746587565876658776587865879658806588165882658836588465885658866588765888658896589065891658926589365894658956589665897658986589965900659016590265903659046590565906659076590865909659106591165912659136591465915659166591765918659196592065921659226592365924659256592665927659286592965930659316593265933659346593565936659376593865939659406594165942659436594465945659466594765948659496595065951659526595365954659556595665957659586595965960659616596265963659646596565966659676596865969659706597165972659736597465975659766597765978659796598065981659826598365984659856598665987659886598965990659916599265993659946599565996659976599865999660006600166002660036600466005660066600766008660096601066011660126601366014660156601666017660186601966020660216602266023660246602566026660276602866029660306603166032660336603466035660366603766038660396604066041660426604366044660456604666047660486604966050660516605266053660546605566056660576605866059660606606166062660636606466065660666606766068660696607066071660726607366074660756607666077660786607966080660816608266083660846608566086660876608866089660906609166092660936609466095660966609766098660996610066101661026610366104661056610666107661086610966110661116611266113661146611566116661176611866119661206612166122661236612466125661266612766128661296613066131661326613366134661356613666137661386613966140661416614266143661446614566146661476614866149661506615166152661536615466155661566615766158661596616066161661626616366164661656616666167661686616966170661716617266173661746617566176661776617866179661806618166182661836618466185661866618766188661896619066191661926619366194661956619666197661986619966200662016620266203662046620566206662076620866209662106621166212662136621466215662166621766218662196622066221662226622366224662256622666227662286622966230662316623266233662346623566236662376623866239662406624166242662436624466245662466624766248662496625066251662526625366254662556625666257662586625966260662616626266263662646626566266662676626866269662706627166272662736627466275662766627766278662796628066281662826628366284662856628666287662886628966290662916629266293662946629566296662976629866299663006630166302663036630466305663066630766308663096631066311663126631366314663156631666317663186631966320663216632266323663246632566326663276632866329663306633166332663336633466335663366633766338663396634066341663426634366344663456634666347663486634966350663516635266353663546635566356663576635866359663606636166362663636636466365663666636766368663696637066371663726637366374663756637666377663786637966380663816638266383663846638566386663876638866389663906639166392663936639466395663966639766398663996640066401664026640366404664056640666407664086640966410664116641266413664146641566416664176641866419664206642166422664236642466425664266642766428664296643066431664326643366434664356643666437664386643966440664416644266443664446644566446664476644866449664506645166452664536645466455664566645766458664596646066461664626646366464664656646666467664686646966470664716647266473664746647566476664776647866479664806648166482664836648466485664866648766488664896649066491664926649366494664956649666497664986649966500665016650266503665046650566506665076650866509665106651166512665136651466515665166651766518665196652066521665226652366524665256652666527665286652966530665316653266533665346653566536665376653866539665406654166542665436654466545665466654766548665496655066551665526655366554665556655666557665586655966560665616656266563665646656566566665676656866569665706657166572665736657466575665766657766578665796658066581665826658366584665856658666587665886658966590665916659266593665946659566596665976659866599666006660166602666036660466605666066660766608666096661066611666126661366614666156661666617666186661966620666216662266623666246662566626666276662866629666306663166632666336663466635666366663766638666396664066641666426664366644666456664666647666486664966650666516665266653666546665566656666576665866659666606666166662666636666466665666666666766668666696667066671666726667366674666756667666677666786667966680666816668266683666846668566686666876668866689666906669166692666936669466695666966669766698666996670066701667026670366704667056670666707667086670966710667116671266713667146671566716667176671866719667206672166722667236672466725667266672766728667296673066731667326673366734667356673666737667386673966740667416674266743667446674566746667476674866749667506675166752667536675466755667566675766758667596676066761667626676366764667656676666767667686676966770667716677266773667746677566776667776677866779667806678166782667836678466785667866678766788667896679066791667926679366794667956679666797667986679966800668016680266803668046680566806668076680866809668106681166812668136681466815668166681766818668196682066821668226682366824668256682666827668286682966830668316683266833668346683566836668376683866839668406684166842668436684466845668466684766848668496685066851668526685366854668556685666857668586685966860668616686266863668646686566866668676686866869668706687166872668736687466875668766687766878668796688066881668826688366884668856688666887668886688966890668916689266893668946689566896668976689866899669006690166902669036690466905669066690766908669096691066911669126691366914669156691666917669186691966920669216692266923669246692566926669276692866929669306693166932669336693466935669366693766938669396694066941669426694366944669456694666947669486694966950669516695266953669546695566956669576695866959669606696166962669636696466965669666696766968669696697066971669726697366974669756697666977669786697966980669816698266983669846698566986669876698866989669906699166992669936699466995669966699766998669996700067001670026700367004670056700667007670086700967010670116701267013670146701567016670176701867019670206702167022670236702467025670266702767028670296703067031670326703367034670356703667037670386703967040670416704267043670446704567046670476704867049670506705167052670536705467055670566705767058670596706067061670626706367064670656706667067670686706967070670716707267073670746707567076670776707867079670806708167082670836708467085670866708767088670896709067091670926709367094670956709667097670986709967100671016710267103671046710567106671076710867109671106711167112671136711467115671166711767118671196712067121671226712367124671256712667127671286712967130671316713267133671346713567136671376713867139671406714167142671436714467145671466714767148671496715067151671526715367154671556715667157671586715967160671616716267163671646716567166671676716867169671706717167172671736717467175671766717767178671796718067181671826718367184671856718667187671886718967190671916719267193671946719567196671976719867199672006720167202672036720467205672066720767208672096721067211672126721367214672156721667217672186721967220672216722267223672246722567226672276722867229672306723167232672336723467235672366723767238672396724067241672426724367244672456724667247672486724967250672516725267253672546725567256672576725867259672606726167262672636726467265672666726767268672696727067271672726727367274672756727667277672786727967280672816728267283672846728567286672876728867289672906729167292672936729467295672966729767298672996730067301673026730367304673056730667307673086730967310673116731267313673146731567316673176731867319673206732167322673236732467325673266732767328673296733067331673326733367334673356733667337673386733967340673416734267343673446734567346673476734867349673506735167352673536735467355673566735767358673596736067361673626736367364673656736667367673686736967370673716737267373673746737567376673776737867379673806738167382673836738467385673866738767388673896739067391673926739367394673956739667397673986739967400674016740267403674046740567406674076740867409674106741167412674136741467415674166741767418674196742067421674226742367424674256742667427674286742967430674316743267433674346743567436674376743867439674406744167442674436744467445674466744767448674496745067451674526745367454674556745667457674586745967460674616746267463674646746567466674676746867469674706747167472674736747467475674766747767478674796748067481674826748367484674856748667487674886748967490674916749267493674946749567496674976749867499675006750167502675036750467505675066750767508675096751067511675126751367514675156751667517675186751967520675216752267523675246752567526675276752867529675306753167532675336753467535675366753767538675396754067541675426754367544675456754667547675486754967550675516755267553675546755567556675576755867559675606756167562675636756467565675666756767568675696757067571675726757367574675756757667577675786757967580675816758267583675846758567586675876758867589675906759167592675936759467595675966759767598675996760067601676026760367604676056760667607676086760967610676116761267613676146761567616676176761867619676206762167622676236762467625676266762767628676296763067631676326763367634676356763667637676386763967640676416764267643676446764567646676476764867649676506765167652676536765467655676566765767658676596766067661676626766367664676656766667667676686766967670676716767267673676746767567676676776767867679676806768167682676836768467685676866768767688676896769067691676926769367694676956769667697676986769967700677016770267703677046770567706677076770867709677106771167712677136771467715677166771767718677196772067721677226772367724677256772667727677286772967730677316773267733677346773567736677376773867739677406774167742677436774467745677466774767748677496775067751677526775367754677556775667757677586775967760677616776267763677646776567766677676776867769677706777167772677736777467775677766777767778677796778067781677826778367784677856778667787677886778967790677916779267793677946779567796677976779867799678006780167802678036780467805678066780767808678096781067811678126781367814678156781667817678186781967820678216782267823678246782567826678276782867829678306783167832678336783467835678366783767838678396784067841678426784367844678456784667847678486784967850678516785267853678546785567856678576785867859678606786167862678636786467865678666786767868678696787067871678726787367874678756787667877678786787967880678816788267883678846788567886678876788867889678906789167892678936789467895678966789767898678996790067901679026790367904679056790667907679086790967910679116791267913679146791567916679176791867919679206792167922679236792467925679266792767928679296793067931679326793367934679356793667937679386793967940679416794267943679446794567946679476794867949679506795167952679536795467955679566795767958679596796067961679626796367964679656796667967679686796967970679716797267973679746797567976679776797867979679806798167982679836798467985679866798767988679896799067991679926799367994679956799667997679986799968000680016800268003680046800568006680076800868009680106801168012680136801468015680166801768018680196802068021680226802368024680256802668027680286802968030680316803268033680346803568036680376803868039680406804168042680436804468045680466804768048680496805068051680526805368054680556805668057680586805968060680616806268063680646806568066680676806868069680706807168072680736807468075680766807768078680796808068081680826808368084680856808668087680886808968090680916809268093680946809568096680976809868099681006810168102681036810468105681066810768108681096811068111681126811368114681156811668117681186811968120681216812268123681246812568126681276812868129681306813168132681336813468135681366813768138681396814068141681426814368144681456814668147681486814968150681516815268153681546815568156681576815868159681606816168162681636816468165681666816768168681696817068171681726817368174681756817668177681786817968180681816818268183681846818568186681876818868189681906819168192681936819468195681966819768198681996820068201682026820368204682056820668207682086820968210682116821268213682146821568216682176821868219682206822168222682236822468225682266822768228682296823068231682326823368234682356823668237682386823968240682416824268243682446824568246682476824868249682506825168252682536825468255682566825768258682596826068261682626826368264682656826668267682686826968270682716827268273682746827568276682776827868279682806828168282682836828468285682866828768288682896829068291682926829368294682956829668297682986829968300683016830268303683046830568306683076830868309683106831168312683136831468315683166831768318683196832068321683226832368324683256832668327683286832968330683316833268333683346833568336683376833868339683406834168342683436834468345683466834768348683496835068351683526835368354683556835668357683586835968360683616836268363683646836568366683676836868369683706837168372683736837468375683766837768378683796838068381683826838368384683856838668387683886838968390683916839268393683946839568396683976839868399684006840168402684036840468405684066840768408684096841068411684126841368414684156841668417684186841968420684216842268423684246842568426684276842868429684306843168432684336843468435684366843768438684396844068441684426844368444684456844668447684486844968450684516845268453684546845568456684576845868459684606846168462684636846468465684666846768468684696847068471684726847368474684756847668477684786847968480684816848268483684846848568486684876848868489684906849168492684936849468495684966849768498684996850068501685026850368504685056850668507685086850968510685116851268513685146851568516685176851868519685206852168522685236852468525685266852768528685296853068531685326853368534685356853668537685386853968540685416854268543685446854568546685476854868549685506855168552685536855468555685566855768558685596856068561685626856368564685656856668567685686856968570685716857268573685746857568576685776857868579685806858168582685836858468585685866858768588685896859068591685926859368594685956859668597685986859968600686016860268603686046860568606686076860868609686106861168612686136861468615686166861768618686196862068621686226862368624686256862668627686286862968630686316863268633686346863568636686376863868639686406864168642686436864468645686466864768648686496865068651686526865368654686556865668657686586865968660686616866268663686646866568666686676866868669686706867168672686736867468675686766867768678686796868068681686826868368684686856868668687686886868968690686916869268693686946869568696686976869868699687006870168702687036870468705687066870768708687096871068711687126871368714687156871668717687186871968720687216872268723687246872568726687276872868729687306873168732687336873468735687366873768738687396874068741687426874368744687456874668747687486874968750687516875268753687546875568756687576875868759687606876168762687636876468765687666876768768687696877068771687726877368774687756877668777687786877968780687816878268783687846878568786687876878868789687906879168792687936879468795687966879768798687996880068801688026880368804688056880668807688086880968810688116881268813688146881568816688176881868819688206882168822688236882468825688266882768828688296883068831688326883368834688356883668837688386883968840688416884268843688446884568846688476884868849688506885168852688536885468855688566885768858688596886068861688626886368864688656886668867688686886968870688716887268873688746887568876688776887868879688806888168882688836888468885688866888768888688896889068891688926889368894688956889668897688986889968900689016890268903689046890568906689076890868909689106891168912689136891468915689166891768918689196892068921689226892368924689256892668927689286892968930689316893268933689346893568936689376893868939689406894168942689436894468945689466894768948689496895068951689526895368954689556895668957689586895968960689616896268963689646896568966689676896868969689706897168972689736897468975689766897768978689796898068981689826898368984689856898668987689886898968990689916899268993689946899568996689976899868999690006900169002690036900469005690066900769008690096901069011690126901369014690156901669017690186901969020690216902269023690246902569026690276902869029690306903169032690336903469035690366903769038690396904069041690426904369044690456904669047690486904969050690516905269053690546905569056690576905869059690606906169062690636906469065690666906769068690696907069071690726907369074690756907669077690786907969080690816908269083690846908569086690876908869089690906909169092690936909469095690966909769098690996910069101691026910369104691056910669107691086910969110691116911269113691146911569116691176911869119691206912169122691236912469125691266912769128691296913069131691326913369134691356913669137691386913969140691416914269143691446914569146691476914869149691506915169152691536915469155691566915769158691596916069161691626916369164691656916669167691686916969170691716917269173691746917569176691776917869179691806918169182691836918469185691866918769188691896919069191691926919369194691956919669197691986919969200692016920269203692046920569206692076920869209692106921169212692136921469215692166921769218692196922069221692226922369224692256922669227692286922969230692316923269233692346923569236692376923869239692406924169242692436924469245692466924769248692496925069251692526925369254692556925669257692586925969260692616926269263692646926569266692676926869269692706927169272692736927469275692766927769278692796928069281692826928369284692856928669287692886928969290692916929269293692946929569296692976929869299693006930169302693036930469305693066930769308693096931069311693126931369314693156931669317693186931969320693216932269323693246932569326693276932869329693306933169332693336933469335693366933769338693396934069341693426934369344693456934669347693486934969350693516935269353693546935569356693576935869359693606936169362693636936469365693666936769368693696937069371693726937369374693756937669377693786937969380693816938269383693846938569386693876938869389693906939169392693936939469395693966939769398693996940069401694026940369404694056940669407694086940969410694116941269413694146941569416694176941869419694206942169422694236942469425694266942769428694296943069431694326943369434694356943669437694386943969440694416944269443694446944569446694476944869449694506945169452694536945469455694566945769458694596946069461694626946369464694656946669467694686946969470694716947269473694746947569476694776947869479694806948169482694836948469485694866948769488694896949069491694926949369494694956949669497694986949969500695016950269503695046950569506695076950869509695106951169512695136951469515695166951769518695196952069521695226952369524695256952669527695286952969530695316953269533695346953569536695376953869539695406954169542695436954469545695466954769548695496955069551695526955369554695556955669557695586955969560695616956269563695646956569566695676956869569695706957169572695736957469575695766957769578695796958069581695826958369584695856958669587695886958969590695916959269593695946959569596695976959869599696006960169602696036960469605696066960769608696096961069611696126961369614696156961669617696186961969620696216962269623696246962569626696276962869629696306963169632696336963469635696366963769638696396964069641696426964369644696456964669647696486964969650696516965269653696546965569656696576965869659696606966169662696636966469665696666966769668696696967069671696726967369674696756967669677696786967969680696816968269683696846968569686696876968869689696906969169692696936969469695696966969769698696996970069701697026970369704697056970669707697086970969710697116971269713697146971569716697176971869719697206972169722697236972469725697266972769728697296973069731697326973369734697356973669737697386973969740697416974269743697446974569746697476974869749697506975169752697536975469755697566975769758697596976069761697626976369764697656976669767697686976969770697716977269773697746977569776697776977869779697806978169782697836978469785697866978769788697896979069791697926979369794697956979669797697986979969800698016980269803698046980569806698076980869809698106981169812698136981469815698166981769818698196982069821698226982369824698256982669827698286982969830698316983269833698346983569836698376983869839698406984169842698436984469845698466984769848698496985069851698526985369854698556985669857698586985969860698616986269863698646986569866698676986869869698706987169872698736987469875698766987769878698796988069881698826988369884698856988669887698886988969890698916989269893698946989569896698976989869899699006990169902699036990469905699066990769908699096991069911699126991369914699156991669917699186991969920699216992269923699246992569926699276992869929699306993169932699336993469935699366993769938699396994069941699426994369944699456994669947699486994969950699516995269953699546995569956699576995869959699606996169962699636996469965699666996769968699696997069971699726997369974699756997669977699786997969980699816998269983699846998569986699876998869989699906999169992699936999469995699966999769998699997000070001700027000370004700057000670007700087000970010700117001270013700147001570016700177001870019700207002170022700237002470025700267002770028700297003070031700327003370034700357003670037700387003970040700417004270043700447004570046700477004870049700507005170052700537005470055700567005770058700597006070061700627006370064700657006670067700687006970070700717007270073700747007570076700777007870079700807008170082700837008470085700867008770088700897009070091700927009370094700957009670097700987009970100701017010270103701047010570106701077010870109701107011170112701137011470115701167011770118701197012070121701227012370124701257012670127701287012970130701317013270133701347013570136701377013870139701407014170142701437014470145701467014770148701497015070151701527015370154701557015670157701587015970160701617016270163701647016570166701677016870169701707017170172701737017470175701767017770178701797018070181701827018370184701857018670187701887018970190701917019270193701947019570196701977019870199702007020170202702037020470205702067020770208702097021070211702127021370214702157021670217702187021970220702217022270223702247022570226702277022870229702307023170232702337023470235702367023770238702397024070241702427024370244702457024670247702487024970250702517025270253702547025570256702577025870259702607026170262702637026470265702667026770268702697027070271702727027370274702757027670277702787027970280702817028270283702847028570286702877028870289702907029170292702937029470295702967029770298702997030070301703027030370304703057030670307703087030970310703117031270313703147031570316703177031870319703207032170322703237032470325703267032770328703297033070331703327033370334703357033670337703387033970340703417034270343703447034570346703477034870349703507035170352703537035470355703567035770358703597036070361703627036370364703657036670367703687036970370703717037270373703747037570376703777037870379703807038170382703837038470385703867038770388703897039070391703927039370394703957039670397703987039970400704017040270403704047040570406704077040870409704107041170412704137041470415704167041770418704197042070421704227042370424704257042670427704287042970430704317043270433704347043570436704377043870439704407044170442704437044470445704467044770448704497045070451704527045370454704557045670457704587045970460704617046270463704647046570466704677046870469704707047170472704737047470475704767047770478704797048070481704827048370484704857048670487704887048970490704917049270493704947049570496704977049870499705007050170502705037050470505705067050770508705097051070511705127051370514705157051670517705187051970520705217052270523705247052570526705277052870529705307053170532705337053470535705367053770538705397054070541705427054370544705457054670547705487054970550705517055270553705547055570556705577055870559705607056170562705637056470565705667056770568705697057070571705727057370574705757057670577705787057970580705817058270583705847058570586705877058870589705907059170592705937059470595705967059770598705997060070601706027060370604706057060670607706087060970610706117061270613706147061570616706177061870619706207062170622706237062470625706267062770628706297063070631706327063370634706357063670637706387063970640706417064270643706447064570646706477064870649706507065170652706537065470655706567065770658706597066070661706627066370664706657066670667706687066970670706717067270673706747067570676706777067870679706807068170682706837068470685706867068770688706897069070691706927069370694706957069670697706987069970700707017070270703707047070570706707077070870709707107071170712707137071470715707167071770718707197072070721707227072370724707257072670727707287072970730707317073270733707347073570736707377073870739707407074170742707437074470745707467074770748707497075070751707527075370754707557075670757707587075970760707617076270763707647076570766707677076870769707707077170772707737077470775707767077770778707797078070781707827078370784707857078670787707887078970790707917079270793707947079570796707977079870799708007080170802708037080470805708067080770808708097081070811708127081370814708157081670817708187081970820708217082270823708247082570826708277082870829708307083170832708337083470835708367083770838708397084070841708427084370844708457084670847708487084970850708517085270853708547085570856708577085870859708607086170862708637086470865708667086770868708697087070871708727087370874708757087670877708787087970880708817088270883708847088570886708877088870889708907089170892708937089470895708967089770898708997090070901709027090370904709057090670907709087090970910709117091270913709147091570916709177091870919709207092170922709237092470925709267092770928709297093070931709327093370934709357093670937709387093970940709417094270943709447094570946709477094870949709507095170952709537095470955709567095770958709597096070961709627096370964709657096670967709687096970970709717097270973709747097570976709777097870979709807098170982709837098470985709867098770988709897099070991709927099370994709957099670997709987099971000710017100271003710047100571006710077100871009710107101171012710137101471015710167101771018710197102071021710227102371024710257102671027710287102971030710317103271033710347103571036710377103871039710407104171042710437104471045710467104771048710497105071051710527105371054710557105671057710587105971060710617106271063710647106571066710677106871069710707107171072710737107471075710767107771078710797108071081710827108371084710857108671087710887108971090710917109271093710947109571096710977109871099711007110171102711037110471105711067110771108711097111071111711127111371114711157111671117711187111971120711217112271123711247112571126711277112871129711307113171132711337113471135711367113771138711397114071141711427114371144711457114671147711487114971150711517115271153711547115571156711577115871159711607116171162711637116471165711667116771168711697117071171711727117371174711757117671177711787117971180711817118271183711847118571186711877118871189711907119171192711937119471195711967119771198711997120071201712027120371204712057120671207712087120971210712117121271213712147121571216712177121871219712207122171222712237122471225712267122771228712297123071231712327123371234712357123671237712387123971240712417124271243712447124571246712477124871249712507125171252712537125471255712567125771258712597126071261712627126371264712657126671267712687126971270712717127271273712747127571276712777127871279712807128171282712837128471285712867128771288712897129071291712927129371294712957129671297712987129971300713017130271303713047130571306713077130871309713107131171312713137131471315713167131771318713197132071321713227132371324713257132671327713287132971330713317133271333713347133571336713377133871339713407134171342713437134471345713467134771348713497135071351713527135371354713557135671357713587135971360713617136271363713647136571366713677136871369713707137171372713737137471375713767137771378713797138071381713827138371384713857138671387713887138971390713917139271393713947139571396713977139871399714007140171402714037140471405714067140771408714097141071411714127141371414714157141671417714187141971420714217142271423714247142571426714277142871429714307143171432714337143471435714367143771438714397144071441714427144371444714457144671447714487144971450714517145271453714547145571456714577145871459714607146171462714637146471465714667146771468714697147071471714727147371474714757147671477714787147971480714817148271483714847148571486714877148871489714907149171492714937149471495714967149771498714997150071501715027150371504715057150671507715087150971510715117151271513715147151571516715177151871519715207152171522715237152471525715267152771528715297153071531715327153371534715357153671537715387153971540715417154271543715447154571546715477154871549715507155171552715537155471555715567155771558715597156071561715627156371564715657156671567715687156971570715717157271573715747157571576715777157871579715807158171582715837158471585715867158771588715897159071591715927159371594715957159671597715987159971600716017160271603716047160571606716077160871609716107161171612716137161471615716167161771618716197162071621716227162371624716257162671627716287162971630716317163271633716347163571636716377163871639716407164171642716437164471645716467164771648716497165071651716527165371654716557165671657716587165971660716617166271663716647166571666716677166871669716707167171672716737167471675716767167771678716797168071681716827168371684716857168671687716887168971690716917169271693716947169571696716977169871699717007170171702717037170471705717067170771708717097171071711717127171371714717157171671717717187171971720717217172271723717247172571726717277172871729717307173171732717337173471735717367173771738717397174071741717427174371744717457174671747717487174971750717517175271753717547175571756717577175871759717607176171762717637176471765717667176771768717697177071771717727177371774717757177671777717787177971780717817178271783717847178571786717877178871789717907179171792717937179471795717967179771798717997180071801718027180371804718057180671807718087180971810718117181271813718147181571816718177181871819718207182171822718237182471825718267182771828718297183071831718327183371834718357183671837718387183971840718417184271843718447184571846718477184871849718507185171852718537185471855718567185771858718597186071861718627186371864718657186671867718687186971870718717187271873718747187571876718777187871879718807188171882718837188471885718867188771888718897189071891718927189371894718957189671897718987189971900719017190271903719047190571906719077190871909719107191171912719137191471915719167191771918719197192071921719227192371924719257192671927719287192971930719317193271933719347193571936719377193871939719407194171942719437194471945719467194771948719497195071951719527195371954719557195671957719587195971960719617196271963719647196571966719677196871969719707197171972719737197471975719767197771978719797198071981719827198371984719857198671987719887198971990719917199271993719947199571996719977199871999720007200172002720037200472005720067200772008720097201072011720127201372014720157201672017720187201972020720217202272023720247202572026720277202872029720307203172032720337203472035720367203772038720397204072041720427204372044720457204672047720487204972050720517205272053720547205572056720577205872059720607206172062720637206472065720667206772068720697207072071720727207372074720757207672077720787207972080720817208272083720847208572086720877208872089720907209172092720937209472095720967209772098720997210072101721027210372104721057210672107721087210972110721117211272113721147211572116721177211872119721207212172122721237212472125721267212772128721297213072131721327213372134721357213672137721387213972140721417214272143721447214572146721477214872149721507215172152721537215472155721567215772158721597216072161721627216372164721657216672167721687216972170721717217272173721747217572176721777217872179721807218172182721837218472185721867218772188721897219072191721927219372194721957219672197721987219972200722017220272203722047220572206722077220872209722107221172212722137221472215722167221772218722197222072221722227222372224722257222672227722287222972230722317223272233722347223572236722377223872239722407224172242722437224472245722467224772248722497225072251722527225372254722557225672257722587225972260722617226272263722647226572266722677226872269722707227172272722737227472275722767227772278722797228072281722827228372284722857228672287722887228972290722917229272293722947229572296722977229872299723007230172302723037230472305723067230772308723097231072311723127231372314723157231672317723187231972320723217232272323723247232572326723277232872329723307233172332723337233472335723367233772338723397234072341723427234372344723457234672347723487234972350723517235272353723547235572356723577235872359723607236172362723637236472365723667236772368723697237072371723727237372374723757237672377723787237972380723817238272383723847238572386723877238872389723907239172392723937239472395723967239772398723997240072401724027240372404724057240672407724087240972410724117241272413724147241572416724177241872419724207242172422724237242472425724267242772428724297243072431724327243372434724357243672437724387243972440724417244272443724447244572446724477244872449724507245172452724537245472455724567245772458724597246072461724627246372464724657246672467724687246972470724717247272473724747247572476724777247872479724807248172482724837248472485724867248772488724897249072491724927249372494724957249672497724987249972500725017250272503725047250572506725077250872509725107251172512725137251472515725167251772518725197252072521725227252372524725257252672527725287252972530725317253272533725347253572536725377253872539725407254172542725437254472545725467254772548725497255072551725527255372554725557255672557725587255972560725617256272563725647256572566725677256872569725707257172572725737257472575725767257772578725797258072581725827258372584725857258672587725887258972590725917259272593725947259572596725977259872599726007260172602726037260472605726067260772608726097261072611726127261372614726157261672617726187261972620726217262272623726247262572626726277262872629726307263172632726337263472635726367263772638726397264072641726427264372644726457264672647726487264972650726517265272653726547265572656726577265872659726607266172662726637266472665726667266772668726697267072671726727267372674726757267672677726787267972680726817268272683726847268572686726877268872689726907269172692726937269472695726967269772698726997270072701727027270372704727057270672707727087270972710727117271272713727147271572716727177271872719727207272172722727237272472725727267272772728727297273072731727327273372734727357273672737727387273972740727417274272743727447274572746727477274872749727507275172752727537275472755727567275772758727597276072761727627276372764727657276672767727687276972770727717277272773727747277572776727777277872779727807278172782727837278472785727867278772788727897279072791727927279372794727957279672797727987279972800728017280272803728047280572806728077280872809728107281172812728137281472815728167281772818728197282072821728227282372824728257282672827728287282972830728317283272833728347283572836728377283872839728407284172842728437284472845728467284772848728497285072851728527285372854728557285672857728587285972860728617286272863728647286572866728677286872869728707287172872728737287472875728767287772878728797288072881728827288372884728857288672887728887288972890728917289272893728947289572896728977289872899729007290172902729037290472905729067290772908729097291072911729127291372914729157291672917729187291972920729217292272923729247292572926729277292872929729307293172932729337293472935729367293772938729397294072941729427294372944729457294672947729487294972950729517295272953729547295572956729577295872959729607296172962729637296472965729667296772968729697297072971729727297372974729757297672977729787297972980729817298272983729847298572986729877298872989729907299172992729937299472995729967299772998729997300073001730027300373004730057300673007730087300973010730117301273013730147301573016730177301873019730207302173022730237302473025730267302773028730297303073031730327303373034730357303673037730387303973040730417304273043730447304573046730477304873049730507305173052730537305473055730567305773058730597306073061730627306373064730657306673067730687306973070730717307273073730747307573076730777307873079730807308173082730837308473085730867308773088730897309073091730927309373094730957309673097730987309973100731017310273103731047310573106731077310873109731107311173112731137311473115731167311773118731197312073121731227312373124731257312673127731287312973130731317313273133731347313573136731377313873139731407314173142731437314473145731467314773148731497315073151731527315373154731557315673157731587315973160731617316273163731647316573166731677316873169731707317173172731737317473175731767317773178731797318073181731827318373184731857318673187731887318973190731917319273193731947319573196731977319873199732007320173202732037320473205732067320773208732097321073211732127321373214732157321673217732187321973220732217322273223732247322573226732277322873229732307323173232732337323473235732367323773238732397324073241732427324373244732457324673247732487324973250732517325273253732547325573256732577325873259732607326173262732637326473265732667326773268732697327073271732727327373274732757327673277732787327973280732817328273283732847328573286732877328873289732907329173292732937329473295732967329773298732997330073301733027330373304733057330673307733087330973310733117331273313733147331573316733177331873319733207332173322733237332473325733267332773328733297333073331733327333373334733357333673337733387333973340733417334273343733447334573346733477334873349733507335173352733537335473355733567335773358733597336073361733627336373364733657336673367733687336973370733717337273373733747337573376733777337873379733807338173382733837338473385733867338773388733897339073391733927339373394733957339673397733987339973400734017340273403734047340573406734077340873409734107341173412734137341473415734167341773418734197342073421734227342373424734257342673427734287342973430734317343273433734347343573436734377343873439734407344173442734437344473445734467344773448734497345073451734527345373454734557345673457734587345973460734617346273463734647346573466734677346873469734707347173472734737347473475734767347773478734797348073481734827348373484734857348673487734887348973490734917349273493734947349573496734977349873499735007350173502735037350473505735067350773508735097351073511735127351373514735157351673517735187351973520735217352273523735247352573526735277352873529735307353173532735337353473535735367353773538735397354073541735427354373544735457354673547735487354973550735517355273553735547355573556735577355873559735607356173562735637356473565735667356773568735697357073571735727357373574735757357673577735787357973580735817358273583735847358573586735877358873589735907359173592735937359473595735967359773598735997360073601736027360373604736057360673607736087360973610736117361273613736147361573616736177361873619736207362173622736237362473625736267362773628736297363073631736327363373634736357363673637736387363973640736417364273643736447364573646736477364873649736507365173652736537365473655736567365773658736597366073661736627366373664736657366673667736687366973670736717367273673736747367573676736777367873679736807368173682736837368473685736867368773688736897369073691736927369373694736957369673697736987369973700737017370273703737047370573706737077370873709737107371173712737137371473715737167371773718737197372073721737227372373724737257372673727737287372973730737317373273733737347373573736737377373873739737407374173742737437374473745737467374773748737497375073751737527375373754737557375673757737587375973760737617376273763737647376573766737677376873769737707377173772737737377473775737767377773778737797378073781737827378373784737857378673787737887378973790737917379273793737947379573796737977379873799738007380173802738037380473805738067380773808738097381073811738127381373814738157381673817738187381973820738217382273823738247382573826738277382873829738307383173832738337383473835738367383773838738397384073841738427384373844738457384673847738487384973850738517385273853738547385573856738577385873859738607386173862738637386473865738667386773868738697387073871738727387373874738757387673877738787387973880738817388273883738847388573886738877388873889738907389173892738937389473895738967389773898738997390073901739027390373904739057390673907739087390973910739117391273913739147391573916739177391873919739207392173922739237392473925739267392773928739297393073931739327393373934739357393673937739387393973940739417394273943739447394573946739477394873949739507395173952739537395473955739567395773958739597396073961739627396373964739657396673967739687396973970739717397273973739747397573976739777397873979739807398173982739837398473985739867398773988739897399073991739927399373994739957399673997739987399974000740017400274003740047400574006740077400874009740107401174012740137401474015740167401774018740197402074021740227402374024740257402674027740287402974030740317403274033740347403574036740377403874039740407404174042740437404474045740467404774048740497405074051740527405374054740557405674057740587405974060740617406274063740647406574066740677406874069740707407174072740737407474075740767407774078740797408074081740827408374084740857408674087740887408974090740917409274093740947409574096740977409874099741007410174102741037410474105741067410774108741097411074111741127411374114741157411674117741187411974120741217412274123741247412574126741277412874129741307413174132741337413474135741367413774138741397414074141741427414374144741457414674147741487414974150741517415274153741547415574156741577415874159741607416174162741637416474165741667416774168741697417074171741727417374174741757417674177741787417974180741817418274183741847418574186741877418874189741907419174192741937419474195741967419774198741997420074201742027420374204742057420674207742087420974210742117421274213742147421574216742177421874219742207422174222742237422474225742267422774228742297423074231742327423374234742357423674237742387423974240742417424274243742447424574246742477424874249742507425174252742537425474255742567425774258742597426074261742627426374264742657426674267742687426974270742717427274273742747427574276742777427874279742807428174282742837428474285742867428774288742897429074291742927429374294742957429674297742987429974300743017430274303743047430574306743077430874309743107431174312743137431474315743167431774318743197432074321743227432374324743257432674327743287432974330743317433274333743347433574336743377433874339743407434174342743437434474345743467434774348743497435074351743527435374354743557435674357743587435974360743617436274363743647436574366743677436874369743707437174372743737437474375743767437774378743797438074381743827438374384743857438674387743887438974390743917439274393743947439574396743977439874399744007440174402744037440474405744067440774408744097441074411744127441374414744157441674417744187441974420744217442274423744247442574426744277442874429744307443174432744337443474435744367443774438744397444074441744427444374444744457444674447744487444974450744517445274453744547445574456744577445874459744607446174462744637446474465744667446774468744697447074471744727447374474744757447674477744787447974480744817448274483744847448574486744877448874489744907449174492744937449474495744967449774498744997450074501745027450374504745057450674507745087450974510745117451274513745147451574516745177451874519745207452174522745237452474525745267452774528745297453074531745327453374534745357453674537745387453974540745417454274543745447454574546745477454874549745507455174552745537455474555745567455774558745597456074561745627456374564745657456674567745687456974570745717457274573745747457574576745777457874579745807458174582745837458474585745867458774588745897459074591745927459374594745957459674597745987459974600746017460274603746047460574606746077460874609746107461174612746137461474615746167461774618746197462074621746227462374624746257462674627746287462974630746317463274633746347463574636746377463874639746407464174642746437464474645746467464774648746497465074651746527465374654746557465674657746587465974660746617466274663746647466574666746677466874669746707467174672746737467474675746767467774678746797468074681746827468374684746857468674687746887468974690746917469274693746947469574696746977469874699747007470174702747037470474705747067470774708747097471074711747127471374714747157471674717747187471974720747217472274723747247472574726747277472874729747307473174732747337473474735747367473774738747397474074741747427474374744747457474674747747487474974750747517475274753747547475574756747577475874759747607476174762747637476474765747667476774768747697477074771747727477374774747757477674777747787477974780747817478274783747847478574786747877478874789747907479174792747937479474795747967479774798747997480074801748027480374804748057480674807748087480974810748117481274813748147481574816748177481874819748207482174822748237482474825748267482774828748297483074831748327483374834748357483674837748387483974840748417484274843748447484574846748477484874849748507485174852748537485474855748567485774858748597486074861748627486374864748657486674867748687486974870748717487274873748747487574876748777487874879748807488174882748837488474885748867488774888748897489074891748927489374894748957489674897748987489974900749017490274903749047490574906749077490874909749107491174912749137491474915749167491774918749197492074921749227492374924749257492674927749287492974930749317493274933749347493574936749377493874939749407494174942749437494474945749467494774948749497495074951749527495374954749557495674957749587495974960749617496274963749647496574966749677496874969749707497174972749737497474975749767497774978749797498074981749827498374984749857498674987749887498974990749917499274993749947499574996749977499874999750007500175002750037500475005750067500775008750097501075011750127501375014750157501675017750187501975020750217502275023750247502575026750277502875029750307503175032750337503475035750367503775038750397504075041750427504375044750457504675047750487504975050750517505275053750547505575056750577505875059750607506175062750637506475065750667506775068750697507075071750727507375074750757507675077750787507975080750817508275083750847508575086750877508875089750907509175092750937509475095750967509775098750997510075101751027510375104751057510675107751087510975110751117511275113751147511575116751177511875119751207512175122751237512475125751267512775128751297513075131751327513375134751357513675137751387513975140751417514275143751447514575146751477514875149751507515175152751537515475155751567515775158751597516075161751627516375164751657516675167751687516975170751717517275173751747517575176751777517875179751807518175182751837518475185751867518775188751897519075191751927519375194751957519675197751987519975200752017520275203752047520575206752077520875209752107521175212752137521475215752167521775218752197522075221752227522375224752257522675227752287522975230752317523275233752347523575236752377523875239752407524175242752437524475245752467524775248752497525075251752527525375254752557525675257752587525975260752617526275263752647526575266752677526875269752707527175272752737527475275752767527775278752797528075281752827528375284752857528675287752887528975290752917529275293752947529575296752977529875299753007530175302753037530475305753067530775308753097531075311753127531375314753157531675317753187531975320753217532275323753247532575326753277532875329753307533175332753337533475335753367533775338753397534075341753427534375344753457534675347753487534975350753517535275353753547535575356753577535875359753607536175362753637536475365753667536775368753697537075371753727537375374753757537675377753787537975380753817538275383753847538575386753877538875389753907539175392753937539475395753967539775398753997540075401754027540375404754057540675407754087540975410754117541275413754147541575416754177541875419754207542175422754237542475425754267542775428754297543075431754327543375434754357543675437754387543975440754417544275443754447544575446754477544875449754507545175452754537545475455754567545775458754597546075461754627546375464754657546675467754687546975470754717547275473754747547575476754777547875479754807548175482754837548475485754867548775488754897549075491754927549375494754957549675497754987549975500755017550275503755047550575506755077550875509755107551175512755137551475515755167551775518755197552075521755227552375524755257552675527755287552975530755317553275533755347553575536755377553875539755407554175542755437554475545755467554775548755497555075551755527555375554755557555675557755587555975560755617556275563755647556575566755677556875569755707557175572755737557475575755767557775578755797558075581755827558375584755857558675587755887558975590755917559275593755947559575596755977559875599756007560175602756037560475605756067560775608756097561075611756127561375614756157561675617756187561975620756217562275623756247562575626756277562875629756307563175632756337563475635756367563775638756397564075641756427564375644756457564675647756487564975650756517565275653756547565575656756577565875659756607566175662756637566475665756667566775668756697567075671756727567375674756757567675677756787567975680756817568275683756847568575686756877568875689756907569175692756937569475695756967569775698756997570075701757027570375704757057570675707757087570975710757117571275713757147571575716757177571875719757207572175722757237572475725757267572775728757297573075731757327573375734757357573675737757387573975740757417574275743757447574575746757477574875749757507575175752757537575475755757567575775758757597576075761757627576375764757657576675767757687576975770757717577275773757747577575776757777577875779757807578175782757837578475785757867578775788757897579075791757927579375794757957579675797757987579975800758017580275803758047580575806758077580875809758107581175812758137581475815758167581775818758197582075821758227582375824758257582675827758287582975830758317583275833758347583575836758377583875839758407584175842758437584475845758467584775848758497585075851758527585375854758557585675857758587585975860758617586275863758647586575866758677586875869758707587175872758737587475875758767587775878758797588075881758827588375884758857588675887758887588975890758917589275893758947589575896758977589875899759007590175902759037590475905759067590775908759097591075911759127591375914759157591675917759187591975920759217592275923759247592575926759277592875929759307593175932759337593475935759367593775938759397594075941759427594375944759457594675947759487594975950759517595275953759547595575956759577595875959759607596175962759637596475965759667596775968759697597075971759727597375974759757597675977759787597975980759817598275983759847598575986759877598875989759907599175992759937599475995759967599775998759997600076001760027600376004760057600676007760087600976010760117601276013760147601576016760177601876019760207602176022760237602476025760267602776028760297603076031760327603376034760357603676037760387603976040760417604276043760447604576046760477604876049760507605176052760537605476055760567605776058760597606076061760627606376064760657606676067760687606976070760717607276073760747607576076760777607876079760807608176082760837608476085760867608776088760897609076091760927609376094760957609676097760987609976100761017610276103761047610576106761077610876109761107611176112761137611476115761167611776118761197612076121761227612376124761257612676127761287612976130761317613276133761347613576136761377613876139761407614176142761437614476145761467614776148761497615076151761527615376154761557615676157761587615976160761617616276163761647616576166761677616876169761707617176172761737617476175761767617776178761797618076181761827618376184761857618676187761887618976190761917619276193761947619576196761977619876199762007620176202762037620476205762067620776208762097621076211762127621376214762157621676217762187621976220762217622276223762247622576226762277622876229762307623176232762337623476235762367623776238762397624076241762427624376244762457624676247762487624976250762517625276253762547625576256762577625876259762607626176262762637626476265762667626776268762697627076271762727627376274762757627676277762787627976280762817628276283762847628576286762877628876289762907629176292762937629476295762967629776298762997630076301763027630376304763057630676307763087630976310763117631276313763147631576316763177631876319763207632176322763237632476325763267632776328763297633076331763327633376334763357633676337763387633976340763417634276343763447634576346763477634876349763507635176352763537635476355763567635776358763597636076361763627636376364763657636676367763687636976370763717637276373763747637576376763777637876379763807638176382763837638476385763867638776388763897639076391763927639376394763957639676397763987639976400764017640276403764047640576406764077640876409764107641176412764137641476415764167641776418764197642076421764227642376424764257642676427764287642976430764317643276433764347643576436764377643876439764407644176442764437644476445764467644776448764497645076451764527645376454764557645676457764587645976460764617646276463764647646576466764677646876469764707647176472764737647476475764767647776478764797648076481764827648376484764857648676487764887648976490764917649276493764947649576496764977649876499765007650176502765037650476505765067650776508765097651076511765127651376514765157651676517765187651976520765217652276523765247652576526765277652876529765307653176532765337653476535765367653776538765397654076541765427654376544765457654676547765487654976550765517655276553765547655576556765577655876559765607656176562765637656476565765667656776568765697657076571765727657376574765757657676577765787657976580765817658276583765847658576586765877658876589765907659176592765937659476595765967659776598765997660076601766027660376604766057660676607766087660976610766117661276613766147661576616766177661876619766207662176622766237662476625766267662776628766297663076631766327663376634766357663676637766387663976640766417664276643766447664576646766477664876649766507665176652766537665476655766567665776658766597666076661766627666376664766657666676667766687666976670766717667276673766747667576676766777667876679766807668176682766837668476685766867668776688766897669076691766927669376694766957669676697766987669976700767017670276703767047670576706767077670876709767107671176712767137671476715767167671776718767197672076721767227672376724767257672676727767287672976730767317673276733767347673576736767377673876739767407674176742767437674476745767467674776748767497675076751767527675376754767557675676757767587675976760767617676276763767647676576766767677676876769767707677176772767737677476775767767677776778767797678076781767827678376784767857678676787767887678976790767917679276793767947679576796767977679876799768007680176802768037680476805768067680776808768097681076811768127681376814768157681676817768187681976820768217682276823768247682576826768277682876829768307683176832768337683476835768367683776838768397684076841768427684376844768457684676847768487684976850768517685276853768547685576856768577685876859768607686176862768637686476865768667686776868768697687076871768727687376874768757687676877768787687976880768817688276883768847688576886768877688876889768907689176892768937689476895768967689776898768997690076901769027690376904769057690676907769087690976910769117691276913769147691576916769177691876919769207692176922769237692476925769267692776928769297693076931769327693376934769357693676937769387693976940769417694276943769447694576946769477694876949769507695176952769537695476955769567695776958769597696076961769627696376964769657696676967769687696976970769717697276973769747697576976769777697876979769807698176982769837698476985769867698776988769897699076991769927699376994769957699676997769987699977000770017700277003770047700577006770077700877009770107701177012770137701477015770167701777018770197702077021770227702377024770257702677027770287702977030770317703277033770347703577036770377703877039770407704177042770437704477045770467704777048770497705077051770527705377054770557705677057770587705977060770617706277063770647706577066770677706877069770707707177072770737707477075770767707777078770797708077081770827708377084770857708677087770887708977090770917709277093770947709577096770977709877099771007710177102771037710477105771067710777108771097711077111771127711377114771157711677117771187711977120771217712277123771247712577126771277712877129771307713177132771337713477135771367713777138771397714077141771427714377144771457714677147771487714977150771517715277153771547715577156771577715877159771607716177162771637716477165771667716777168771697717077171771727717377174771757717677177771787717977180771817718277183771847718577186771877718877189771907719177192771937719477195771967719777198771997720077201772027720377204772057720677207772087720977210772117721277213772147721577216772177721877219772207722177222772237722477225772267722777228772297723077231772327723377234772357723677237772387723977240772417724277243772447724577246772477724877249772507725177252772537725477255772567725777258772597726077261772627726377264772657726677267772687726977270772717727277273772747727577276772777727877279772807728177282772837728477285772867728777288772897729077291772927729377294772957729677297772987729977300773017730277303773047730577306773077730877309773107731177312773137731477315773167731777318773197732077321773227732377324773257732677327773287732977330773317733277333773347733577336773377733877339773407734177342773437734477345773467734777348773497735077351773527735377354773557735677357773587735977360773617736277363773647736577366773677736877369773707737177372773737737477375773767737777378773797738077381773827738377384773857738677387773887738977390773917739277393773947739577396773977739877399774007740177402774037740477405774067740777408774097741077411774127741377414774157741677417774187741977420774217742277423774247742577426774277742877429774307743177432774337743477435774367743777438774397744077441774427744377444774457744677447774487744977450774517745277453774547745577456774577745877459774607746177462774637746477465774667746777468774697747077471774727747377474774757747677477774787747977480774817748277483774847748577486774877748877489774907749177492774937749477495774967749777498774997750077501775027750377504775057750677507775087750977510775117751277513775147751577516775177751877519775207752177522775237752477525775267752777528775297753077531775327753377534775357753677537775387753977540775417754277543775447754577546775477754877549775507755177552775537755477555775567755777558775597756077561775627756377564775657756677567775687756977570775717757277573775747757577576775777757877579775807758177582775837758477585775867758777588775897759077591775927759377594775957759677597775987759977600776017760277603776047760577606776077760877609776107761177612776137761477615776167761777618776197762077621776227762377624776257762677627776287762977630776317763277633776347763577636776377763877639776407764177642776437764477645776467764777648776497765077651776527765377654776557765677657776587765977660776617766277663776647766577666776677766877669776707767177672776737767477675776767767777678776797768077681776827768377684776857768677687776887768977690776917769277693776947769577696776977769877699777007770177702777037770477705777067770777708777097771077711777127771377714777157771677717777187771977720777217772277723777247772577726777277772877729777307773177732777337773477735777367773777738777397774077741777427774377744777457774677747777487774977750777517775277753777547775577756777577775877759777607776177762777637776477765777667776777768777697777077771777727777377774777757777677777777787777977780777817778277783777847778577786777877778877789777907779177792777937779477795777967779777798777997780077801778027780377804778057780677807778087780977810778117781277813778147781577816778177781877819778207782177822778237782477825778267782777828778297783077831778327783377834778357783677837778387783977840778417784277843778447784577846778477784877849778507785177852778537785477855778567785777858778597786077861778627786377864778657786677867778687786977870778717787277873778747787577876778777787877879778807788177882778837788477885778867788777888778897789077891778927789377894778957789677897778987789977900779017790277903779047790577906779077790877909779107791177912779137791477915779167791777918779197792077921779227792377924779257792677927779287792977930779317793277933779347793577936779377793877939779407794177942779437794477945779467794777948779497795077951779527795377954779557795677957779587795977960779617796277963779647796577966779677796877969779707797177972779737797477975779767797777978779797798077981779827798377984779857798677987779887798977990779917799277993779947799577996779977799877999780007800178002780037800478005780067800778008780097801078011780127801378014780157801678017780187801978020780217802278023780247802578026780277802878029780307803178032780337803478035780367803778038780397804078041780427804378044780457804678047780487804978050780517805278053780547805578056780577805878059780607806178062780637806478065780667806778068780697807078071780727807378074780757807678077780787807978080780817808278083780847808578086780877808878089780907809178092780937809478095780967809778098780997810078101781027810378104781057810678107781087810978110781117811278113781147811578116781177811878119781207812178122781237812478125781267812778128781297813078131781327813378134781357813678137781387813978140781417814278143781447814578146781477814878149781507815178152781537815478155781567815778158781597816078161781627816378164781657816678167781687816978170781717817278173781747817578176781777817878179781807818178182781837818478185781867818778188781897819078191781927819378194781957819678197781987819978200782017820278203782047820578206782077820878209782107821178212782137821478215782167821778218782197822078221782227822378224782257822678227782287822978230782317823278233782347823578236782377823878239782407824178242782437824478245782467824778248782497825078251782527825378254782557825678257782587825978260782617826278263782647826578266782677826878269782707827178272782737827478275782767827778278782797828078281782827828378284782857828678287782887828978290782917829278293782947829578296782977829878299783007830178302783037830478305783067830778308783097831078311783127831378314783157831678317783187831978320783217832278323783247832578326783277832878329783307833178332783337833478335783367833778338783397834078341783427834378344783457834678347783487834978350783517835278353783547835578356783577835878359783607836178362783637836478365783667836778368783697837078371783727837378374783757837678377783787837978380783817838278383783847838578386783877838878389783907839178392783937839478395783967839778398783997840078401784027840378404784057840678407784087840978410784117841278413784147841578416784177841878419784207842178422784237842478425784267842778428784297843078431784327843378434784357843678437784387843978440784417844278443784447844578446784477844878449784507845178452784537845478455784567845778458784597846078461784627846378464784657846678467784687846978470784717847278473784747847578476784777847878479784807848178482784837848478485784867848778488784897849078491784927849378494784957849678497784987849978500785017850278503785047850578506785077850878509785107851178512785137851478515785167851778518785197852078521785227852378524785257852678527785287852978530785317853278533785347853578536785377853878539785407854178542785437854478545785467854778548785497855078551785527855378554785557855678557785587855978560785617856278563785647856578566785677856878569785707857178572785737857478575785767857778578785797858078581785827858378584785857858678587785887858978590785917859278593785947859578596785977859878599786007860178602786037860478605786067860778608786097861078611786127861378614786157861678617786187861978620786217862278623786247862578626786277862878629786307863178632786337863478635786367863778638786397864078641786427864378644786457864678647786487864978650786517865278653786547865578656786577865878659786607866178662786637866478665786667866778668786697867078671786727867378674786757867678677786787867978680786817868278683786847868578686786877868878689786907869178692786937869478695786967869778698786997870078701787027870378704787057870678707787087870978710787117871278713787147871578716787177871878719787207872178722787237872478725787267872778728787297873078731787327873378734787357873678737787387873978740787417874278743787447874578746787477874878749787507875178752787537875478755787567875778758787597876078761787627876378764787657876678767787687876978770787717877278773787747877578776787777877878779787807878178782787837878478785787867878778788787897879078791787927879378794787957879678797787987879978800788017880278803788047880578806788077880878809788107881178812788137881478815788167881778818788197882078821788227882378824788257882678827788287882978830788317883278833788347883578836788377883878839788407884178842788437884478845788467884778848788497885078851788527885378854788557885678857788587885978860788617886278863788647886578866788677886878869788707887178872788737887478875788767887778878788797888078881788827888378884788857888678887788887888978890788917889278893788947889578896788977889878899789007890178902789037890478905789067890778908789097891078911789127891378914789157891678917789187891978920789217892278923789247892578926789277892878929789307893178932789337893478935789367893778938789397894078941789427894378944789457894678947789487894978950789517895278953789547895578956789577895878959789607896178962789637896478965789667896778968789697897078971789727897378974789757897678977789787897978980789817898278983789847898578986789877898878989789907899178992789937899478995789967899778998789997900079001790027900379004790057900679007790087900979010790117901279013790147901579016790177901879019790207902179022790237902479025790267902779028790297903079031790327903379034790357903679037790387903979040790417904279043790447904579046790477904879049790507905179052790537905479055790567905779058790597906079061790627906379064790657906679067790687906979070790717907279073790747907579076790777907879079790807908179082790837908479085790867908779088790897909079091790927909379094790957909679097790987909979100791017910279103791047910579106791077910879109791107911179112791137911479115791167911779118791197912079121791227912379124791257912679127791287912979130791317913279133791347913579136791377913879139791407914179142791437914479145791467914779148791497915079151791527915379154791557915679157791587915979160791617916279163791647916579166791677916879169791707917179172791737917479175791767917779178791797918079181791827918379184791857918679187791887918979190791917919279193791947919579196791977919879199792007920179202792037920479205792067920779208792097921079211792127921379214792157921679217792187921979220792217922279223792247922579226792277922879229792307923179232792337923479235792367923779238792397924079241792427924379244792457924679247792487924979250792517925279253792547925579256792577925879259792607926179262792637926479265792667926779268792697927079271792727927379274792757927679277792787927979280792817928279283792847928579286792877928879289792907929179292792937929479295792967929779298792997930079301793027930379304793057930679307793087930979310793117931279313793147931579316793177931879319793207932179322793237932479325793267932779328793297933079331793327933379334793357933679337793387933979340793417934279343793447934579346793477934879349793507935179352793537935479355793567935779358793597936079361793627936379364793657936679367793687936979370793717937279373793747937579376793777937879379793807938179382793837938479385793867938779388793897939079391793927939379394793957939679397793987939979400794017940279403794047940579406794077940879409794107941179412794137941479415794167941779418794197942079421794227942379424794257942679427794287942979430794317943279433794347943579436794377943879439794407944179442794437944479445794467944779448794497945079451794527945379454794557945679457794587945979460794617946279463794647946579466794677946879469794707947179472794737947479475794767947779478794797948079481794827948379484794857948679487794887948979490794917949279493794947949579496794977949879499795007950179502795037950479505795067950779508795097951079511795127951379514795157951679517795187951979520795217952279523795247952579526795277952879529795307953179532795337953479535795367953779538795397954079541795427954379544795457954679547795487954979550795517955279553795547955579556795577955879559795607956179562795637956479565795667956779568795697957079571795727957379574795757957679577795787957979580795817958279583795847958579586795877958879589795907959179592795937959479595795967959779598795997960079601796027960379604796057960679607796087960979610796117961279613796147961579616796177961879619796207962179622796237962479625796267962779628796297963079631796327963379634796357963679637796387963979640796417964279643796447964579646796477964879649796507965179652796537965479655796567965779658796597966079661796627966379664796657966679667796687966979670796717967279673796747967579676796777967879679796807968179682796837968479685796867968779688796897969079691796927969379694796957969679697796987969979700797017970279703797047970579706797077970879709797107971179712797137971479715797167971779718797197972079721797227972379724797257972679727797287972979730797317973279733797347973579736797377973879739797407974179742797437974479745797467974779748797497975079751797527975379754797557975679757797587975979760797617976279763797647976579766797677976879769797707977179772797737977479775797767977779778797797978079781797827978379784797857978679787797887978979790797917979279793797947979579796797977979879799798007980179802798037980479805798067980779808798097981079811798127981379814798157981679817798187981979820798217982279823798247982579826798277982879829798307983179832798337983479835798367983779838798397984079841798427984379844798457984679847798487984979850798517985279853798547985579856798577985879859798607986179862798637986479865798667986779868798697987079871798727987379874798757987679877798787987979880798817988279883798847988579886798877988879889798907989179892798937989479895798967989779898798997990079901799027990379904799057990679907799087990979910799117991279913799147991579916799177991879919799207992179922799237992479925799267992779928799297993079931799327993379934799357993679937799387993979940799417994279943799447994579946799477994879949799507995179952799537995479955799567995779958799597996079961799627996379964799657996679967799687996979970799717997279973799747997579976799777997879979799807998179982799837998479985799867998779988799897999079991799927999379994799957999679997799987999980000800018000280003800048000580006800078000880009800108001180012800138001480015800168001780018800198002080021800228002380024800258002680027800288002980030800318003280033800348003580036800378003880039800408004180042800438004480045800468004780048800498005080051800528005380054800558005680057800588005980060800618006280063800648006580066800678006880069800708007180072800738007480075800768007780078800798008080081800828008380084800858008680087800888008980090800918009280093800948009580096800978009880099801008010180102801038010480105801068010780108801098011080111801128011380114801158011680117801188011980120801218012280123801248012580126801278012880129801308013180132801338013480135801368013780138801398014080141801428014380144801458014680147801488014980150801518015280153801548015580156801578015880159801608016180162801638016480165801668016780168801698017080171801728017380174801758017680177801788017980180801818018280183801848018580186801878018880189801908019180192801938019480195801968019780198801998020080201802028020380204802058020680207802088020980210802118021280213802148021580216802178021880219802208022180222802238022480225802268022780228802298023080231802328023380234802358023680237802388023980240802418024280243802448024580246802478024880249802508025180252802538025480255802568025780258802598026080261802628026380264802658026680267802688026980270802718027280273802748027580276802778027880279802808028180282802838028480285802868028780288802898029080291802928029380294802958029680297802988029980300803018030280303803048030580306803078030880309803108031180312803138031480315803168031780318803198032080321803228032380324803258032680327803288032980330803318033280333803348033580336803378033880339803408034180342803438034480345803468034780348803498035080351803528035380354803558035680357803588035980360803618036280363803648036580366803678036880369803708037180372803738037480375803768037780378803798038080381803828038380384803858038680387803888038980390803918039280393803948039580396803978039880399804008040180402804038040480405804068040780408804098041080411804128041380414804158041680417804188041980420804218042280423804248042580426804278042880429804308043180432804338043480435804368043780438804398044080441804428044380444804458044680447804488044980450804518045280453804548045580456804578045880459804608046180462804638046480465804668046780468804698047080471804728047380474804758047680477804788047980480804818048280483804848048580486804878048880489804908049180492804938049480495804968049780498804998050080501805028050380504805058050680507805088050980510805118051280513805148051580516805178051880519805208052180522805238052480525805268052780528805298053080531805328053380534805358053680537805388053980540805418054280543805448054580546805478054880549805508055180552805538055480555805568055780558805598056080561805628056380564805658056680567805688056980570805718057280573805748057580576805778057880579805808058180582805838058480585805868058780588805898059080591805928059380594805958059680597805988059980600806018060280603806048060580606806078060880609806108061180612806138061480615806168061780618806198062080621806228062380624806258062680627806288062980630806318063280633806348063580636806378063880639806408064180642806438064480645806468064780648806498065080651806528065380654806558065680657806588065980660806618066280663806648066580666806678066880669806708067180672806738067480675806768067780678806798068080681806828068380684806858068680687806888068980690806918069280693806948069580696806978069880699807008070180702807038070480705807068070780708807098071080711807128071380714807158071680717807188071980720807218072280723807248072580726807278072880729807308073180732807338073480735807368073780738807398074080741807428074380744807458074680747807488074980750807518075280753807548075580756807578075880759807608076180762807638076480765807668076780768807698077080771807728077380774807758077680777807788077980780807818078280783807848078580786807878078880789807908079180792807938079480795807968079780798807998080080801808028080380804808058080680807808088080980810808118081280813808148081580816808178081880819808208082180822808238082480825808268082780828808298083080831808328083380834808358083680837808388083980840808418084280843808448084580846808478084880849808508085180852808538085480855808568085780858808598086080861808628086380864808658086680867808688086980870808718087280873808748087580876808778087880879808808088180882808838088480885808868088780888808898089080891808928089380894808958089680897808988089980900809018090280903809048090580906809078090880909809108091180912809138091480915809168091780918809198092080921809228092380924809258092680927809288092980930809318093280933809348093580936809378093880939809408094180942809438094480945809468094780948809498095080951809528095380954809558095680957809588095980960809618096280963809648096580966809678096880969809708097180972809738097480975809768097780978809798098080981809828098380984809858098680987809888098980990809918099280993809948099580996809978099880999810008100181002810038100481005810068100781008810098101081011810128101381014810158101681017810188101981020810218102281023810248102581026810278102881029810308103181032810338103481035810368103781038810398104081041810428104381044810458104681047810488104981050810518105281053810548105581056810578105881059810608106181062810638106481065810668106781068810698107081071810728107381074810758107681077810788107981080810818108281083810848108581086810878108881089810908109181092810938109481095810968109781098810998110081101811028110381104811058110681107811088110981110811118111281113811148111581116811178111881119811208112181122811238112481125811268112781128811298113081131811328113381134811358113681137811388113981140811418114281143811448114581146811478114881149811508115181152811538115481155811568115781158811598116081161811628116381164811658116681167811688116981170811718117281173811748117581176811778117881179811808118181182811838118481185811868118781188811898119081191811928119381194811958119681197811988119981200812018120281203812048120581206812078120881209812108121181212812138121481215812168121781218812198122081221812228122381224812258122681227812288122981230812318123281233812348123581236812378123881239812408124181242812438124481245812468124781248812498125081251812528125381254812558125681257812588125981260812618126281263812648126581266812678126881269812708127181272812738127481275812768127781278812798128081281812828128381284812858128681287812888128981290812918129281293812948129581296812978129881299813008130181302813038130481305813068130781308813098131081311813128131381314813158131681317813188131981320813218132281323813248132581326813278132881329813308133181332813338133481335813368133781338813398134081341813428134381344813458134681347813488134981350813518135281353813548135581356813578135881359813608136181362813638136481365813668136781368813698137081371813728137381374813758137681377813788137981380813818138281383813848138581386813878138881389813908139181392813938139481395813968139781398813998140081401814028140381404814058140681407814088140981410814118141281413814148141581416814178141881419814208142181422814238142481425814268142781428814298143081431814328143381434814358143681437814388143981440814418144281443814448144581446814478144881449814508145181452814538145481455814568145781458814598146081461814628146381464814658146681467814688146981470814718147281473814748147581476814778147881479814808148181482814838148481485814868148781488814898149081491814928149381494814958149681497814988149981500815018150281503815048150581506815078150881509815108151181512815138151481515815168151781518815198152081521815228152381524815258152681527815288152981530815318153281533815348153581536815378153881539815408154181542815438154481545815468154781548815498155081551815528155381554815558155681557815588155981560815618156281563815648156581566815678156881569815708157181572815738157481575815768157781578815798158081581815828158381584815858158681587815888158981590815918159281593815948159581596815978159881599816008160181602816038160481605816068160781608816098161081611816128161381614816158161681617816188161981620816218162281623816248162581626816278162881629816308163181632816338163481635816368163781638816398164081641816428164381644816458164681647816488164981650816518165281653816548165581656816578165881659816608166181662816638166481665816668166781668816698167081671816728167381674816758167681677816788167981680816818168281683816848168581686816878168881689816908169181692816938169481695816968169781698816998170081701817028170381704817058170681707817088170981710817118171281713817148171581716817178171881719817208172181722817238172481725817268172781728817298173081731817328173381734817358173681737817388173981740817418174281743817448174581746817478174881749817508175181752817538175481755817568175781758817598176081761817628176381764817658176681767817688176981770817718177281773817748177581776817778177881779817808178181782817838178481785817868178781788817898179081791817928179381794817958179681797817988179981800818018180281803818048180581806818078180881809818108181181812818138181481815818168181781818818198182081821818228182381824818258182681827818288182981830818318183281833818348183581836818378183881839818408184181842818438184481845818468184781848818498185081851818528185381854818558185681857818588185981860818618186281863818648186581866818678186881869818708187181872818738187481875818768187781878818798188081881818828188381884818858188681887818888188981890818918189281893818948189581896818978189881899819008190181902819038190481905819068190781908819098191081911819128191381914819158191681917819188191981920819218192281923819248192581926819278192881929819308193181932819338193481935819368193781938819398194081941819428194381944819458194681947819488194981950819518195281953819548195581956819578195881959819608196181962819638196481965819668196781968819698197081971819728197381974819758197681977819788197981980819818198281983819848198581986819878198881989819908199181992819938199481995819968199781998819998200082001820028200382004820058200682007820088200982010820118201282013820148201582016820178201882019820208202182022820238202482025820268202782028820298203082031820328203382034820358203682037820388203982040820418204282043820448204582046820478204882049820508205182052820538205482055820568205782058820598206082061820628206382064820658206682067820688206982070820718207282073820748207582076820778207882079820808208182082820838208482085820868208782088820898209082091820928209382094820958209682097820988209982100821018210282103821048210582106821078210882109821108211182112821138211482115821168211782118821198212082121821228212382124821258212682127821288212982130821318213282133821348213582136821378213882139821408214182142821438214482145821468214782148821498215082151821528215382154821558215682157821588215982160821618216282163821648216582166821678216882169821708217182172821738217482175821768217782178821798218082181821828218382184821858218682187821888218982190821918219282193821948219582196821978219882199822008220182202822038220482205822068220782208822098221082211822128221382214822158221682217822188221982220822218222282223822248222582226822278222882229822308223182232822338223482235822368223782238822398224082241822428224382244822458224682247822488224982250822518225282253822548225582256822578225882259822608226182262822638226482265822668226782268822698227082271822728227382274822758227682277822788227982280822818228282283822848228582286822878228882289822908229182292822938229482295822968229782298822998230082301823028230382304823058230682307823088230982310823118231282313823148231582316823178231882319823208232182322823238232482325823268232782328823298233082331823328233382334823358233682337823388233982340823418234282343823448234582346823478234882349823508235182352823538235482355823568235782358823598236082361823628236382364823658236682367823688236982370823718237282373823748237582376823778237882379823808238182382823838238482385823868238782388823898239082391823928239382394823958239682397823988239982400824018240282403824048240582406824078240882409824108241182412824138241482415824168241782418824198242082421824228242382424824258242682427824288242982430824318243282433824348243582436824378243882439824408244182442824438244482445824468244782448824498245082451824528245382454824558245682457824588245982460824618246282463824648246582466824678246882469824708247182472824738247482475824768247782478824798248082481824828248382484824858248682487824888248982490824918249282493824948249582496824978249882499825008250182502825038250482505825068250782508825098251082511825128251382514825158251682517825188251982520825218252282523825248252582526825278252882529825308253182532825338253482535825368253782538825398254082541825428254382544825458254682547825488254982550825518255282553825548255582556825578255882559825608256182562825638256482565825668256782568825698257082571825728257382574825758257682577825788257982580825818258282583825848258582586825878258882589825908259182592825938259482595825968259782598825998260082601826028260382604826058260682607826088260982610826118261282613826148261582616826178261882619826208262182622826238262482625826268262782628826298263082631826328263382634826358263682637826388263982640826418264282643826448264582646826478264882649826508265182652826538265482655826568265782658826598266082661826628266382664826658266682667826688266982670826718267282673826748267582676826778267882679826808268182682826838268482685826868268782688826898269082691826928269382694826958269682697826988269982700827018270282703827048270582706827078270882709827108271182712827138271482715827168271782718827198272082721827228272382724827258272682727827288272982730827318273282733827348273582736827378273882739827408274182742827438274482745827468274782748827498275082751827528275382754827558275682757827588275982760827618276282763827648276582766827678276882769827708277182772827738277482775827768277782778827798278082781827828278382784827858278682787827888278982790827918279282793827948279582796827978279882799828008280182802828038280482805828068280782808828098281082811828128281382814828158281682817828188281982820828218282282823828248282582826828278282882829828308283182832828338283482835828368283782838828398284082841828428284382844828458284682847828488284982850828518285282853828548285582856828578285882859828608286182862828638286482865828668286782868828698287082871828728287382874828758287682877828788287982880828818288282883828848288582886828878288882889828908289182892828938289482895828968289782898828998290082901829028290382904829058290682907829088290982910829118291282913829148291582916829178291882919829208292182922829238292482925829268292782928829298293082931829328293382934829358293682937829388293982940829418294282943829448294582946829478294882949829508295182952829538295482955829568295782958829598296082961829628296382964829658296682967829688296982970829718297282973829748297582976829778297882979829808298182982829838298482985829868298782988829898299082991829928299382994829958299682997829988299983000830018300283003830048300583006830078300883009830108301183012830138301483015830168301783018830198302083021830228302383024830258302683027830288302983030830318303283033830348303583036830378303883039830408304183042830438304483045830468304783048830498305083051830528305383054830558305683057830588305983060830618306283063830648306583066830678306883069830708307183072830738307483075830768307783078830798308083081830828308383084830858308683087830888308983090830918309283093830948309583096830978309883099831008310183102831038310483105831068310783108831098311083111831128311383114831158311683117831188311983120831218312283123831248312583126831278312883129831308313183132831338313483135831368313783138831398314083141831428314383144831458314683147831488314983150831518315283153831548315583156831578315883159831608316183162831638316483165831668316783168831698317083171831728317383174831758317683177831788317983180831818318283183831848318583186831878318883189831908319183192831938319483195831968319783198831998320083201832028320383204832058320683207832088320983210832118321283213832148321583216832178321883219832208322183222832238322483225832268322783228832298323083231832328323383234832358323683237832388323983240832418324283243832448324583246832478324883249832508325183252832538325483255832568325783258832598326083261832628326383264832658326683267832688326983270832718327283273832748327583276832778327883279832808328183282832838328483285832868328783288832898329083291832928329383294832958329683297832988329983300833018330283303833048330583306833078330883309833108331183312833138331483315833168331783318833198332083321833228332383324833258332683327833288332983330833318333283333833348333583336833378333883339833408334183342833438334483345833468334783348833498335083351833528335383354833558335683357833588335983360833618336283363833648336583366833678336883369833708337183372833738337483375833768337783378833798338083381833828338383384833858338683387833888338983390833918339283393833948339583396833978339883399834008340183402834038340483405834068340783408834098341083411834128341383414834158341683417834188341983420834218342283423834248342583426834278342883429834308343183432834338343483435834368343783438834398344083441834428344383444834458344683447834488344983450834518345283453834548345583456834578345883459834608346183462834638346483465834668346783468834698347083471834728347383474834758347683477834788347983480834818348283483834848348583486834878348883489834908349183492834938349483495834968349783498834998350083501835028350383504835058350683507835088350983510835118351283513835148351583516835178351883519835208352183522835238352483525835268352783528835298353083531835328353383534835358353683537835388353983540835418354283543835448354583546835478354883549835508355183552835538355483555835568355783558835598356083561835628356383564835658356683567835688356983570835718357283573835748357583576835778357883579835808358183582835838358483585835868358783588835898359083591835928359383594835958359683597835988359983600836018360283603836048360583606836078360883609836108361183612836138361483615836168361783618836198362083621836228362383624836258362683627836288362983630836318363283633836348363583636836378363883639836408364183642836438364483645836468364783648836498365083651836528365383654836558365683657836588365983660836618366283663836648366583666836678366883669836708367183672836738367483675836768367783678836798368083681836828368383684836858368683687836888368983690836918369283693836948369583696836978369883699837008370183702837038370483705837068370783708837098371083711837128371383714837158371683717837188371983720837218372283723837248372583726837278372883729837308373183732837338373483735837368373783738837398374083741837428374383744837458374683747837488374983750837518375283753837548375583756837578375883759837608376183762837638376483765837668376783768837698377083771837728377383774837758377683777837788377983780837818378283783837848378583786837878378883789837908379183792837938379483795837968379783798837998380083801838028380383804838058380683807838088380983810838118381283813838148381583816838178381883819838208382183822838238382483825838268382783828838298383083831838328383383834838358383683837838388383983840838418384283843838448384583846838478384883849838508385183852838538385483855838568385783858838598386083861838628386383864838658386683867838688386983870838718387283873838748387583876838778387883879838808388183882838838388483885838868388783888838898389083891838928389383894838958389683897838988389983900839018390283903839048390583906839078390883909839108391183912839138391483915839168391783918839198392083921839228392383924839258392683927839288392983930839318393283933839348393583936839378393883939839408394183942839438394483945839468394783948839498395083951839528395383954839558395683957839588395983960839618396283963839648396583966839678396883969839708397183972839738397483975839768397783978839798398083981839828398383984839858398683987839888398983990839918399283993839948399583996839978399883999840008400184002840038400484005840068400784008840098401084011840128401384014840158401684017840188401984020840218402284023840248402584026840278402884029840308403184032840338403484035840368403784038840398404084041840428404384044840458404684047840488404984050840518405284053840548405584056840578405884059840608406184062840638406484065840668406784068840698407084071840728407384074840758407684077840788407984080840818408284083840848408584086840878408884089840908409184092840938409484095840968409784098840998410084101841028410384104841058410684107841088410984110841118411284113841148411584116841178411884119841208412184122841238412484125841268412784128841298413084131841328413384134841358413684137841388413984140841418414284143841448414584146841478414884149841508415184152841538415484155841568415784158841598416084161841628416384164841658416684167841688416984170841718417284173841748417584176841778417884179841808418184182841838418484185841868418784188841898419084191841928419384194841958419684197841988419984200842018420284203842048420584206842078420884209842108421184212842138421484215842168421784218842198422084221842228422384224842258422684227842288422984230842318423284233842348423584236842378423884239842408424184242842438424484245842468424784248842498425084251842528425384254842558425684257842588425984260842618426284263842648426584266842678426884269842708427184272842738427484275842768427784278842798428084281842828428384284842858428684287842888428984290842918429284293842948429584296842978429884299843008430184302843038430484305843068430784308843098431084311843128431384314843158431684317843188431984320843218432284323843248432584326843278432884329843308433184332843338433484335843368433784338843398434084341843428434384344843458434684347843488434984350843518435284353843548435584356843578435884359843608436184362843638436484365843668436784368843698437084371843728437384374843758437684377843788437984380843818438284383843848438584386843878438884389843908439184392843938439484395843968439784398843998440084401844028440384404844058440684407844088440984410844118441284413844148441584416844178441884419844208442184422844238442484425844268442784428844298443084431844328443384434844358443684437844388443984440844418444284443844448444584446844478444884449844508445184452844538445484455844568445784458844598446084461844628446384464844658446684467844688446984470844718447284473844748447584476844778447884479844808448184482844838448484485844868448784488844898449084491844928449384494844958449684497844988449984500845018450284503845048450584506845078450884509845108451184512845138451484515845168451784518845198452084521845228452384524845258452684527845288452984530845318453284533845348453584536845378453884539845408454184542845438454484545845468454784548845498455084551845528455384554845558455684557845588455984560845618456284563845648456584566845678456884569845708457184572845738457484575845768457784578845798458084581845828458384584845858458684587845888458984590845918459284593845948459584596845978459884599846008460184602846038460484605846068460784608846098461084611846128461384614846158461684617846188461984620846218462284623846248462584626846278462884629846308463184632846338463484635846368463784638846398464084641846428464384644846458464684647846488464984650846518465284653846548465584656846578465884659846608466184662846638466484665846668466784668846698467084671846728467384674846758467684677846788467984680846818468284683846848468584686846878468884689846908469184692846938469484695846968469784698846998470084701847028470384704847058470684707847088470984710847118471284713847148471584716847178471884719847208472184722847238472484725847268472784728847298473084731847328473384734847358473684737847388473984740847418474284743847448474584746847478474884749847508475184752847538475484755847568475784758847598476084761847628476384764847658476684767847688476984770847718477284773847748477584776847778477884779847808478184782847838478484785847868478784788847898479084791847928479384794847958479684797847988479984800848018480284803848048480584806848078480884809848108481184812848138481484815848168481784818848198482084821848228482384824848258482684827848288482984830848318483284833848348483584836848378483884839848408484184842848438484484845848468484784848848498485084851848528485384854848558485684857848588485984860848618486284863848648486584866848678486884869848708487184872848738487484875848768487784878848798488084881848828488384884848858488684887848888488984890848918489284893848948489584896848978489884899849008490184902849038490484905849068490784908849098491084911849128491384914849158491684917849188491984920849218492284923849248492584926849278492884929849308493184932849338493484935849368493784938849398494084941849428494384944849458494684947849488494984950849518495284953849548495584956849578495884959849608496184962849638496484965849668496784968849698497084971849728497384974849758497684977849788497984980849818498284983849848498584986849878498884989849908499184992849938499484995849968499784998849998500085001850028500385004850058500685007850088500985010850118501285013850148501585016850178501885019850208502185022850238502485025850268502785028850298503085031850328503385034850358503685037850388503985040850418504285043850448504585046850478504885049850508505185052850538505485055850568505785058850598506085061850628506385064850658506685067850688506985070850718507285073850748507585076850778507885079850808508185082850838508485085850868508785088850898509085091850928509385094850958509685097850988509985100851018510285103851048510585106851078510885109851108511185112851138511485115851168511785118851198512085121851228512385124851258512685127851288512985130851318513285133851348513585136851378513885139851408514185142851438514485145851468514785148851498515085151851528515385154851558515685157851588515985160851618516285163851648516585166851678516885169851708517185172851738517485175851768517785178851798518085181851828518385184851858518685187851888518985190851918519285193851948519585196851978519885199852008520185202852038520485205852068520785208852098521085211852128521385214852158521685217852188521985220852218522285223852248522585226852278522885229852308523185232852338523485235852368523785238852398524085241852428524385244852458524685247852488524985250852518525285253852548525585256852578525885259852608526185262852638526485265852668526785268852698527085271852728527385274852758527685277852788527985280852818528285283852848528585286852878528885289852908529185292852938529485295852968529785298852998530085301853028530385304853058530685307853088530985310853118531285313853148531585316853178531885319853208532185322853238532485325853268532785328853298533085331853328533385334853358533685337853388533985340853418534285343853448534585346853478534885349853508535185352853538535485355853568535785358853598536085361853628536385364853658536685367853688536985370853718537285373853748537585376853778537885379853808538185382853838538485385853868538785388853898539085391853928539385394853958539685397853988539985400854018540285403854048540585406854078540885409854108541185412854138541485415854168541785418854198542085421854228542385424854258542685427854288542985430854318543285433854348543585436854378543885439854408544185442854438544485445854468544785448854498545085451854528545385454854558545685457854588545985460854618546285463854648546585466854678546885469854708547185472854738547485475854768547785478854798548085481854828548385484854858548685487854888548985490854918549285493854948549585496854978549885499855008550185502855038550485505855068550785508855098551085511855128551385514855158551685517855188551985520855218552285523855248552585526855278552885529855308553185532855338553485535855368553785538855398554085541855428554385544855458554685547855488554985550855518555285553855548555585556855578555885559855608556185562855638556485565855668556785568855698557085571855728557385574855758557685577855788557985580855818558285583855848558585586855878558885589855908559185592855938559485595855968559785598855998560085601856028560385604856058560685607856088560985610856118561285613856148561585616856178561885619856208562185622856238562485625856268562785628856298563085631856328563385634856358563685637856388563985640856418564285643856448564585646856478564885649856508565185652856538565485655856568565785658856598566085661856628566385664856658566685667856688566985670856718567285673856748567585676856778567885679856808568185682856838568485685856868568785688856898569085691856928569385694856958569685697856988569985700857018570285703857048570585706857078570885709857108571185712857138571485715857168571785718857198572085721857228572385724857258572685727857288572985730857318573285733857348573585736857378573885739857408574185742857438574485745857468574785748857498575085751857528575385754857558575685757857588575985760857618576285763857648576585766857678576885769857708577185772857738577485775857768577785778857798578085781857828578385784857858578685787857888578985790857918579285793857948579585796857978579885799858008580185802858038580485805858068580785808858098581085811858128581385814858158581685817858188581985820858218582285823858248582585826858278582885829858308583185832858338583485835858368583785838858398584085841858428584385844858458584685847858488584985850858518585285853858548585585856858578585885859858608586185862858638586485865858668586785868858698587085871858728587385874858758587685877858788587985880858818588285883858848588585886858878588885889858908589185892858938589485895858968589785898858998590085901859028590385904859058590685907859088590985910859118591285913859148591585916859178591885919859208592185922859238592485925859268592785928859298593085931859328593385934859358593685937859388593985940859418594285943859448594585946859478594885949859508595185952859538595485955859568595785958859598596085961859628596385964859658596685967859688596985970859718597285973859748597585976859778597885979859808598185982859838598485985859868598785988859898599085991859928599385994859958599685997859988599986000860018600286003860048600586006860078600886009860108601186012860138601486015860168601786018860198602086021860228602386024860258602686027860288602986030860318603286033860348603586036860378603886039860408604186042860438604486045860468604786048860498605086051860528605386054860558605686057860588605986060860618606286063860648606586066860678606886069860708607186072860738607486075860768607786078860798608086081860828608386084860858608686087860888608986090860918609286093860948609586096860978609886099861008610186102861038610486105861068610786108861098611086111861128611386114861158611686117861188611986120861218612286123861248612586126861278612886129861308613186132861338613486135861368613786138861398614086141861428614386144861458614686147861488614986150861518615286153861548615586156861578615886159861608616186162861638616486165861668616786168861698617086171861728617386174861758617686177861788617986180861818618286183861848618586186861878618886189861908619186192861938619486195861968619786198861998620086201862028620386204862058620686207862088620986210862118621286213862148621586216862178621886219862208622186222862238622486225862268622786228862298623086231862328623386234862358623686237862388623986240862418624286243862448624586246862478624886249862508625186252862538625486255862568625786258862598626086261862628626386264862658626686267862688626986270862718627286273862748627586276862778627886279862808628186282862838628486285862868628786288862898629086291862928629386294862958629686297862988629986300863018630286303863048630586306863078630886309863108631186312863138631486315863168631786318863198632086321863228632386324863258632686327863288632986330863318633286333863348633586336863378633886339863408634186342863438634486345863468634786348863498635086351863528635386354863558635686357863588635986360863618636286363863648636586366863678636886369863708637186372863738637486375863768637786378863798638086381863828638386384863858638686387863888638986390863918639286393863948639586396863978639886399864008640186402864038640486405864068640786408864098641086411864128641386414864158641686417864188641986420864218642286423864248642586426864278642886429864308643186432864338643486435864368643786438864398644086441864428644386444864458644686447864488644986450864518645286453864548645586456864578645886459864608646186462864638646486465864668646786468864698647086471864728647386474864758647686477864788647986480864818648286483864848648586486864878648886489864908649186492864938649486495864968649786498864998650086501865028650386504865058650686507865088650986510865118651286513865148651586516865178651886519865208652186522865238652486525865268652786528865298653086531865328653386534865358653686537865388653986540865418654286543865448654586546865478654886549865508655186552865538655486555865568655786558865598656086561865628656386564865658656686567865688656986570865718657286573865748657586576865778657886579865808658186582865838658486585865868658786588865898659086591865928659386594865958659686597865988659986600866018660286603866048660586606866078660886609866108661186612866138661486615866168661786618866198662086621866228662386624866258662686627866288662986630866318663286633866348663586636866378663886639866408664186642866438664486645866468664786648866498665086651866528665386654866558665686657866588665986660866618666286663866648666586666866678666886669866708667186672866738667486675866768667786678866798668086681866828668386684866858668686687866888668986690866918669286693866948669586696866978669886699867008670186702867038670486705867068670786708867098671086711867128671386714867158671686717867188671986720867218672286723867248672586726867278672886729867308673186732867338673486735867368673786738867398674086741867428674386744867458674686747867488674986750867518675286753867548675586756867578675886759867608676186762867638676486765867668676786768867698677086771867728677386774867758677686777867788677986780867818678286783867848678586786867878678886789867908679186792867938679486795867968679786798867998680086801868028680386804868058680686807868088680986810868118681286813868148681586816868178681886819868208682186822868238682486825868268682786828868298683086831868328683386834868358683686837868388683986840868418684286843868448684586846868478684886849868508685186852868538685486855868568685786858868598686086861868628686386864868658686686867868688686986870868718687286873868748687586876868778687886879868808688186882868838688486885868868688786888868898689086891868928689386894868958689686897868988689986900869018690286903869048690586906869078690886909869108691186912869138691486915869168691786918869198692086921869228692386924869258692686927869288692986930869318693286933869348693586936869378693886939869408694186942869438694486945869468694786948869498695086951869528695386954869558695686957869588695986960869618696286963869648696586966869678696886969869708697186972869738697486975869768697786978869798698086981869828698386984869858698686987869888698986990869918699286993869948699586996869978699886999870008700187002870038700487005870068700787008870098701087011870128701387014870158701687017870188701987020870218702287023870248702587026870278702887029870308703187032870338703487035870368703787038870398704087041870428704387044870458704687047870488704987050870518705287053870548705587056870578705887059870608706187062870638706487065870668706787068870698707087071870728707387074870758707687077870788707987080870818708287083870848708587086870878708887089870908709187092870938709487095870968709787098870998710087101871028710387104871058710687107871088710987110871118711287113871148711587116871178711887119871208712187122871238712487125871268712787128871298713087131871328713387134871358713687137871388713987140871418714287143871448714587146871478714887149871508715187152871538715487155871568715787158871598716087161871628716387164871658716687167871688716987170871718717287173871748717587176871778717887179871808718187182871838718487185871868718787188871898719087191871928719387194871958719687197871988719987200872018720287203872048720587206872078720887209872108721187212872138721487215872168721787218872198722087221872228722387224872258722687227872288722987230872318723287233872348723587236872378723887239872408724187242872438724487245872468724787248872498725087251872528725387254872558725687257872588725987260872618726287263872648726587266872678726887269872708727187272872738727487275872768727787278872798728087281872828728387284872858728687287872888728987290872918729287293872948729587296872978729887299873008730187302873038730487305873068730787308873098731087311873128731387314873158731687317873188731987320873218732287323873248732587326873278732887329873308733187332873338733487335873368733787338873398734087341873428734387344873458734687347873488734987350873518735287353873548735587356873578735887359873608736187362873638736487365873668736787368873698737087371873728737387374873758737687377873788737987380873818738287383873848738587386873878738887389873908739187392873938739487395873968739787398873998740087401874028740387404874058740687407874088740987410874118741287413874148741587416874178741887419874208742187422874238742487425874268742787428874298743087431874328743387434874358743687437874388743987440874418744287443874448744587446874478744887449874508745187452874538745487455874568745787458874598746087461874628746387464874658746687467874688746987470874718747287473874748747587476874778747887479874808748187482874838748487485874868748787488874898749087491874928749387494874958749687497874988749987500875018750287503875048750587506875078750887509875108751187512875138751487515875168751787518875198752087521875228752387524875258752687527875288752987530875318753287533875348753587536875378753887539875408754187542875438754487545875468754787548875498755087551875528755387554875558755687557875588755987560875618756287563875648756587566875678756887569875708757187572875738757487575875768757787578875798758087581875828758387584875858758687587875888758987590875918759287593875948759587596875978759887599876008760187602876038760487605876068760787608876098761087611876128761387614876158761687617876188761987620876218762287623876248762587626876278762887629876308763187632876338763487635876368763787638876398764087641876428764387644876458764687647876488764987650876518765287653876548765587656876578765887659876608766187662876638766487665876668766787668876698767087671876728767387674876758767687677876788767987680876818768287683876848768587686876878768887689876908769187692876938769487695876968769787698876998770087701877028770387704877058770687707877088770987710877118771287713877148771587716877178771887719877208772187722877238772487725877268772787728877298773087731877328773387734877358773687737877388773987740877418774287743877448774587746877478774887749877508775187752877538775487755877568775787758877598776087761877628776387764877658776687767877688776987770877718777287773877748777587776877778777887779877808778187782877838778487785877868778787788877898779087791877928779387794877958779687797877988779987800878018780287803878048780587806878078780887809878108781187812878138781487815878168781787818878198782087821878228782387824878258782687827878288782987830878318783287833878348783587836878378783887839878408784187842878438784487845878468784787848878498785087851878528785387854878558785687857878588785987860878618786287863878648786587866878678786887869878708787187872878738787487875878768787787878878798788087881878828788387884878858788687887878888788987890878918789287893878948789587896878978789887899879008790187902879038790487905879068790787908879098791087911879128791387914879158791687917879188791987920879218792287923879248792587926879278792887929879308793187932879338793487935879368793787938879398794087941879428794387944879458794687947879488794987950879518795287953879548795587956879578795887959879608796187962879638796487965879668796787968879698797087971879728797387974879758797687977879788797987980879818798287983879848798587986879878798887989879908799187992879938799487995879968799787998879998800088001880028800388004880058800688007880088800988010880118801288013880148801588016880178801888019880208802188022880238802488025880268802788028880298803088031880328803388034880358803688037880388803988040880418804288043880448804588046880478804888049880508805188052880538805488055880568805788058880598806088061880628806388064880658806688067880688806988070880718807288073880748807588076880778807888079880808808188082880838808488085880868808788088880898809088091880928809388094880958809688097880988809988100881018810288103881048810588106881078810888109881108811188112881138811488115881168811788118881198812088121881228812388124881258812688127881288812988130881318813288133881348813588136881378813888139881408814188142881438814488145881468814788148881498815088151881528815388154881558815688157881588815988160881618816288163881648816588166881678816888169881708817188172881738817488175881768817788178881798818088181881828818388184881858818688187881888818988190881918819288193881948819588196881978819888199882008820188202882038820488205882068820788208882098821088211882128821388214882158821688217882188821988220882218822288223882248822588226882278822888229882308823188232882338823488235882368823788238882398824088241882428824388244882458824688247882488824988250882518825288253882548825588256882578825888259882608826188262882638826488265882668826788268882698827088271882728827388274882758827688277882788827988280882818828288283882848828588286882878828888289882908829188292882938829488295882968829788298882998830088301883028830388304883058830688307883088830988310883118831288313883148831588316883178831888319883208832188322883238832488325883268832788328883298833088331883328833388334883358833688337883388833988340883418834288343883448834588346883478834888349883508835188352883538835488355883568835788358883598836088361883628836388364883658836688367883688836988370883718837288373883748837588376883778837888379883808838188382883838838488385883868838788388883898839088391883928839388394883958839688397883988839988400884018840288403884048840588406884078840888409884108841188412884138841488415884168841788418884198842088421884228842388424884258842688427884288842988430884318843288433884348843588436884378843888439884408844188442884438844488445884468844788448884498845088451884528845388454884558845688457884588845988460884618846288463884648846588466884678846888469884708847188472884738847488475884768847788478884798848088481884828848388484884858848688487884888848988490884918849288493884948849588496884978849888499885008850188502885038850488505885068850788508885098851088511885128851388514885158851688517885188851988520885218852288523885248852588526885278852888529885308853188532885338853488535885368853788538885398854088541885428854388544885458854688547885488854988550885518855288553885548855588556885578855888559885608856188562885638856488565885668856788568885698857088571885728857388574885758857688577885788857988580885818858288583885848858588586885878858888589885908859188592885938859488595885968859788598885998860088601886028860388604886058860688607886088860988610886118861288613886148861588616886178861888619886208862188622886238862488625886268862788628886298863088631886328863388634886358863688637886388863988640886418864288643886448864588646886478864888649886508865188652886538865488655886568865788658886598866088661886628866388664886658866688667886688866988670886718867288673886748867588676886778867888679886808868188682886838868488685886868868788688886898869088691886928869388694886958869688697886988869988700887018870288703887048870588706887078870888709887108871188712887138871488715887168871788718887198872088721887228872388724887258872688727887288872988730887318873288733887348873588736887378873888739887408874188742887438874488745887468874788748887498875088751887528875388754887558875688757887588875988760887618876288763887648876588766887678876888769887708877188772887738877488775887768877788778887798878088781887828878388784887858878688787887888878988790887918879288793887948879588796887978879888799888008880188802888038880488805888068880788808888098881088811888128881388814888158881688817888188881988820888218882288823888248882588826888278882888829888308883188832888338883488835888368883788838888398884088841888428884388844888458884688847888488884988850888518885288853888548885588856888578885888859888608886188862888638886488865888668886788868888698887088871888728887388874888758887688877888788887988880888818888288883888848888588886888878888888889888908889188892888938889488895888968889788898888998890088901889028890388904889058890688907889088890988910889118891288913889148891588916889178891888919889208892188922889238892488925889268892788928889298893088931889328893388934889358893688937889388893988940889418894288943889448894588946889478894888949889508895188952889538895488955889568895788958889598896088961889628896388964889658896688967889688896988970889718897288973889748897588976889778897888979889808898188982889838898488985889868898788988889898899088991889928899388994889958899688997889988899989000890018900289003890048900589006890078900889009890108901189012890138901489015890168901789018890198902089021890228902389024890258902689027890288902989030890318903289033890348903589036890378903889039890408904189042890438904489045890468904789048890498905089051890528905389054890558905689057890588905989060890618906289063890648906589066890678906889069890708907189072890738907489075890768907789078890798908089081890828908389084890858908689087890888908989090890918909289093890948909589096890978909889099891008910189102891038910489105891068910789108891098911089111891128911389114891158911689117891188911989120891218912289123891248912589126891278912889129891308913189132891338913489135891368913789138891398914089141891428914389144891458914689147891488914989150891518915289153891548915589156891578915889159891608916189162891638916489165891668916789168891698917089171891728917389174891758917689177891788917989180891818918289183891848918589186891878918889189891908919189192891938919489195891968919789198891998920089201892028920389204892058920689207892088920989210892118921289213892148921589216892178921889219892208922189222892238922489225892268922789228892298923089231892328923389234892358923689237892388923989240892418924289243892448924589246892478924889249892508925189252892538925489255892568925789258892598926089261892628926389264892658926689267892688926989270892718927289273892748927589276892778927889279892808928189282892838928489285892868928789288892898929089291892928929389294892958929689297892988929989300893018930289303893048930589306893078930889309893108931189312893138931489315893168931789318893198932089321893228932389324893258932689327893288932989330893318933289333893348933589336893378933889339893408934189342893438934489345893468934789348893498935089351893528935389354893558935689357893588935989360893618936289363893648936589366893678936889369893708937189372893738937489375893768937789378893798938089381893828938389384893858938689387893888938989390893918939289393893948939589396893978939889399894008940189402894038940489405894068940789408894098941089411894128941389414894158941689417894188941989420894218942289423894248942589426894278942889429894308943189432894338943489435894368943789438894398944089441894428944389444894458944689447894488944989450894518945289453894548945589456894578945889459894608946189462894638946489465894668946789468894698947089471894728947389474894758947689477894788947989480894818948289483894848948589486894878948889489894908949189492894938949489495894968949789498894998950089501895028950389504895058950689507895088950989510895118951289513895148951589516895178951889519895208952189522895238952489525895268952789528895298953089531895328953389534895358953689537895388953989540895418954289543895448954589546895478954889549895508955189552895538955489555895568955789558895598956089561895628956389564895658956689567895688956989570895718957289573895748957589576895778957889579895808958189582895838958489585895868958789588895898959089591895928959389594895958959689597895988959989600896018960289603896048960589606896078960889609896108961189612896138961489615896168961789618896198962089621896228962389624896258962689627896288962989630896318963289633896348963589636896378963889639896408964189642896438964489645896468964789648896498965089651896528965389654896558965689657896588965989660896618966289663896648966589666896678966889669896708967189672896738967489675896768967789678896798968089681896828968389684896858968689687896888968989690896918969289693896948969589696896978969889699897008970189702897038970489705897068970789708897098971089711897128971389714897158971689717897188971989720897218972289723897248972589726897278972889729897308973189732897338973489735897368973789738897398974089741897428974389744897458974689747897488974989750897518975289753897548975589756897578975889759897608976189762897638976489765897668976789768897698977089771897728977389774897758977689777897788977989780897818978289783897848978589786897878978889789897908979189792897938979489795897968979789798897998980089801898028980389804898058980689807898088980989810898118981289813898148981589816898178981889819898208982189822898238982489825898268982789828898298983089831898328983389834898358983689837898388983989840898418984289843898448984589846898478984889849898508985189852898538985489855898568985789858898598986089861898628986389864898658986689867898688986989870898718987289873898748987589876898778987889879898808988189882898838988489885898868988789888898898989089891898928989389894898958989689897898988989989900899018990289903899048990589906899078990889909899108991189912899138991489915899168991789918899198992089921899228992389924899258992689927899288992989930899318993289933899348993589936899378993889939899408994189942899438994489945899468994789948899498995089951899528995389954899558995689957899588995989960899618996289963899648996589966899678996889969899708997189972899738997489975899768997789978899798998089981899828998389984899858998689987899888998989990899918999289993899948999589996899978999889999900009000190002900039000490005900069000790008900099001090011900129001390014900159001690017900189001990020900219002290023900249002590026900279002890029900309003190032900339003490035900369003790038900399004090041900429004390044900459004690047900489004990050900519005290053900549005590056900579005890059900609006190062900639006490065900669006790068900699007090071900729007390074900759007690077900789007990080900819008290083900849008590086900879008890089900909009190092900939009490095900969009790098900999010090101901029010390104901059010690107901089010990110901119011290113901149011590116901179011890119901209012190122901239012490125901269012790128901299013090131901329013390134901359013690137901389013990140901419014290143901449014590146901479014890149901509015190152901539015490155901569015790158901599016090161901629016390164901659016690167901689016990170901719017290173901749017590176901779017890179901809018190182901839018490185901869018790188901899019090191901929019390194901959019690197901989019990200902019020290203902049020590206902079020890209902109021190212902139021490215902169021790218902199022090221902229022390224902259022690227902289022990230902319023290233902349023590236902379023890239902409024190242902439024490245902469024790248902499025090251902529025390254902559025690257902589025990260902619026290263902649026590266902679026890269902709027190272902739027490275902769027790278902799028090281902829028390284902859028690287902889028990290902919029290293902949029590296902979029890299903009030190302903039030490305903069030790308903099031090311903129031390314903159031690317903189031990320903219032290323903249032590326903279032890329903309033190332903339033490335903369033790338903399034090341903429034390344903459034690347903489034990350903519035290353903549035590356903579035890359903609036190362903639036490365903669036790368903699037090371903729037390374903759037690377903789037990380903819038290383903849038590386903879038890389903909039190392903939039490395903969039790398903999040090401904029040390404904059040690407904089040990410904119041290413904149041590416904179041890419904209042190422904239042490425904269042790428904299043090431904329043390434904359043690437904389043990440904419044290443904449044590446904479044890449904509045190452904539045490455904569045790458904599046090461904629046390464904659046690467904689046990470904719047290473904749047590476904779047890479904809048190482904839048490485904869048790488904899049090491904929049390494904959049690497904989049990500905019050290503905049050590506905079050890509905109051190512905139051490515905169051790518905199052090521905229052390524905259052690527905289052990530905319053290533905349053590536905379053890539905409054190542905439054490545905469054790548905499055090551905529055390554905559055690557905589055990560905619056290563905649056590566905679056890569905709057190572905739057490575905769057790578905799058090581905829058390584905859058690587905889058990590905919059290593905949059590596905979059890599906009060190602906039060490605906069060790608906099061090611906129061390614906159061690617906189061990620906219062290623906249062590626906279062890629906309063190632906339063490635906369063790638906399064090641906429064390644906459064690647906489064990650906519065290653906549065590656906579065890659906609066190662906639066490665906669066790668906699067090671906729067390674906759067690677906789067990680906819068290683906849068590686906879068890689906909069190692906939069490695906969069790698906999070090701907029070390704907059070690707907089070990710907119071290713907149071590716907179071890719907209072190722907239072490725907269072790728907299073090731907329073390734907359073690737907389073990740907419074290743907449074590746907479074890749907509075190752907539075490755907569075790758907599076090761907629076390764907659076690767907689076990770907719077290773907749077590776907779077890779907809078190782907839078490785907869078790788907899079090791907929079390794907959079690797907989079990800908019080290803908049080590806908079080890809908109081190812908139081490815908169081790818908199082090821908229082390824908259082690827908289082990830908319083290833908349083590836908379083890839908409084190842908439084490845908469084790848908499085090851908529085390854908559085690857908589085990860908619086290863908649086590866908679086890869908709087190872908739087490875908769087790878908799088090881908829088390884908859088690887908889088990890908919089290893908949089590896908979089890899909009090190902909039090490905909069090790908909099091090911909129091390914909159091690917909189091990920909219092290923909249092590926909279092890929909309093190932909339093490935909369093790938909399094090941909429094390944909459094690947909489094990950909519095290953909549095590956909579095890959909609096190962909639096490965909669096790968909699097090971909729097390974909759097690977909789097990980909819098290983909849098590986909879098890989909909099190992909939099490995909969099790998909999100091001910029100391004910059100691007910089100991010910119101291013910149101591016910179101891019910209102191022910239102491025910269102791028910299103091031910329103391034910359103691037910389103991040910419104291043910449104591046910479104891049910509105191052910539105491055910569105791058910599106091061910629106391064910659106691067910689106991070910719107291073910749107591076910779107891079910809108191082910839108491085910869108791088910899109091091910929109391094910959109691097910989109991100911019110291103911049110591106911079110891109911109111191112911139111491115911169111791118911199112091121911229112391124911259112691127911289112991130911319113291133911349113591136911379113891139911409114191142911439114491145911469114791148911499115091151911529115391154911559115691157911589115991160911619116291163911649116591166911679116891169911709117191172911739117491175911769117791178911799118091181911829118391184911859118691187911889118991190911919119291193911949119591196911979119891199912009120191202912039120491205912069120791208912099121091211912129121391214912159121691217912189121991220912219122291223912249122591226912279122891229912309123191232912339123491235912369123791238912399124091241912429124391244912459124691247912489124991250912519125291253912549125591256912579125891259912609126191262912639126491265912669126791268912699127091271912729127391274912759127691277912789127991280912819128291283912849128591286912879128891289912909129191292912939129491295912969129791298912999130091301913029130391304913059130691307913089130991310913119131291313913149131591316913179131891319913209132191322913239132491325913269132791328913299133091331913329133391334913359133691337913389133991340913419134291343913449134591346913479134891349913509135191352913539135491355913569135791358913599136091361913629136391364913659136691367913689136991370913719137291373913749137591376913779137891379913809138191382913839138491385913869138791388913899139091391913929139391394913959139691397913989139991400914019140291403914049140591406914079140891409914109141191412914139141491415914169141791418914199142091421914229142391424914259142691427914289142991430914319143291433914349143591436914379143891439914409144191442914439144491445914469144791448914499145091451914529145391454914559145691457914589145991460914619146291463914649146591466914679146891469914709147191472914739147491475914769147791478914799148091481914829148391484914859148691487914889148991490914919149291493914949149591496914979149891499915009150191502915039150491505915069150791508915099151091511915129151391514915159151691517915189151991520915219152291523915249152591526915279152891529915309153191532915339153491535915369153791538915399154091541915429154391544915459154691547915489154991550915519155291553915549155591556915579155891559915609156191562915639156491565915669156791568915699157091571915729157391574915759157691577915789157991580915819158291583915849158591586915879158891589915909159191592915939159491595915969159791598915999160091601916029160391604916059160691607916089160991610916119161291613916149161591616916179161891619916209162191622916239162491625916269162791628916299163091631916329163391634916359163691637916389163991640916419164291643916449164591646916479164891649916509165191652916539165491655916569165791658916599166091661916629166391664916659166691667916689166991670916719167291673916749167591676916779167891679916809168191682916839168491685916869168791688916899169091691916929169391694916959169691697916989169991700917019170291703917049170591706917079170891709917109171191712917139171491715917169171791718917199172091721917229172391724917259172691727917289172991730917319173291733917349173591736917379173891739917409174191742917439174491745917469174791748917499175091751917529175391754917559175691757917589175991760917619176291763917649176591766917679176891769917709177191772917739177491775917769177791778917799178091781917829178391784917859178691787917889178991790917919179291793917949179591796917979179891799918009180191802918039180491805918069180791808918099181091811918129181391814918159181691817918189181991820918219182291823918249182591826918279182891829918309183191832918339183491835918369183791838918399184091841918429184391844918459184691847918489184991850918519185291853918549185591856918579185891859918609186191862918639186491865918669186791868918699187091871918729187391874918759187691877918789187991880918819188291883918849188591886918879188891889918909189191892918939189491895918969189791898918999190091901919029190391904919059190691907919089190991910919119191291913919149191591916919179191891919919209192191922919239192491925919269192791928919299193091931919329193391934919359193691937919389193991940919419194291943919449194591946919479194891949919509195191952919539195491955919569195791958919599196091961919629196391964919659196691967919689196991970919719197291973919749197591976919779197891979919809198191982919839198491985919869198791988919899199091991919929199391994919959199691997919989199992000920019200292003920049200592006920079200892009920109201192012920139201492015920169201792018920199202092021920229202392024920259202692027920289202992030920319203292033920349203592036920379203892039920409204192042920439204492045920469204792048920499205092051920529205392054920559205692057920589205992060920619206292063920649206592066920679206892069920709207192072920739207492075920769207792078920799208092081920829208392084920859208692087920889208992090920919209292093920949209592096920979209892099921009210192102921039210492105921069210792108921099211092111921129211392114921159211692117921189211992120921219212292123921249212592126921279212892129921309213192132921339213492135921369213792138921399214092141921429214392144921459214692147921489214992150921519215292153921549215592156921579215892159921609216192162921639216492165921669216792168921699217092171921729217392174921759217692177921789217992180921819218292183921849218592186921879218892189921909219192192921939219492195921969219792198921999220092201922029220392204922059220692207922089220992210922119221292213922149221592216922179221892219922209222192222922239222492225922269222792228922299223092231922329223392234922359223692237922389223992240922419224292243922449224592246922479224892249922509225192252922539225492255922569225792258922599226092261922629226392264922659226692267922689226992270922719227292273922749227592276922779227892279922809228192282922839228492285922869228792288922899229092291922929229392294922959229692297922989229992300923019230292303923049230592306923079230892309923109231192312923139231492315923169231792318923199232092321923229232392324923259232692327923289232992330923319233292333923349233592336923379233892339923409234192342923439234492345923469234792348923499235092351923529235392354923559235692357923589235992360923619236292363923649236592366923679236892369923709237192372923739237492375923769237792378923799238092381923829238392384923859238692387923889238992390923919239292393923949239592396923979239892399924009240192402924039240492405924069240792408924099241092411924129241392414924159241692417924189241992420924219242292423924249242592426924279242892429924309243192432924339243492435924369243792438924399244092441924429244392444924459244692447924489244992450924519245292453924549245592456924579245892459924609246192462924639246492465924669246792468924699247092471924729247392474924759247692477924789247992480924819248292483924849248592486924879248892489924909249192492924939249492495924969249792498924999250092501925029250392504925059250692507925089250992510925119251292513925149251592516925179251892519925209252192522925239252492525925269252792528925299253092531925329253392534925359253692537925389253992540925419254292543925449254592546925479254892549925509255192552925539255492555925569255792558925599256092561925629256392564925659256692567925689256992570925719257292573925749257592576925779257892579925809258192582925839258492585925869258792588925899259092591925929259392594925959259692597925989259992600926019260292603926049260592606926079260892609926109261192612926139261492615926169261792618926199262092621926229262392624926259262692627926289262992630926319263292633926349263592636926379263892639926409264192642926439264492645926469264792648926499265092651926529265392654926559265692657926589265992660926619266292663926649266592666926679266892669926709267192672926739267492675926769267792678926799268092681926829268392684926859268692687926889268992690926919269292693926949269592696926979269892699927009270192702927039270492705927069270792708927099271092711927129271392714927159271692717927189271992720927219272292723927249272592726927279272892729927309273192732927339273492735927369273792738927399274092741927429274392744927459274692747927489274992750927519275292753927549275592756927579275892759927609276192762927639276492765927669276792768927699277092771927729277392774927759277692777927789277992780927819278292783927849278592786927879278892789927909279192792927939279492795927969279792798927999280092801928029280392804928059280692807928089280992810928119281292813928149281592816928179281892819928209282192822928239282492825928269282792828928299283092831928329283392834928359283692837928389283992840928419284292843928449284592846928479284892849928509285192852928539285492855928569285792858928599286092861928629286392864928659286692867928689286992870928719287292873928749287592876928779287892879928809288192882928839288492885928869288792888928899289092891928929289392894928959289692897928989289992900929019290292903929049290592906929079290892909929109291192912929139291492915929169291792918929199292092921929229292392924929259292692927929289292992930929319293292933929349293592936929379293892939929409294192942929439294492945929469294792948929499295092951929529295392954929559295692957929589295992960929619296292963929649296592966929679296892969929709297192972929739297492975929769297792978929799298092981929829298392984929859298692987929889298992990929919299292993929949299592996929979299892999930009300193002930039300493005930069300793008930099301093011930129301393014930159301693017930189301993020930219302293023930249302593026930279302893029930309303193032930339303493035930369303793038930399304093041930429304393044930459304693047930489304993050930519305293053930549305593056930579305893059930609306193062930639306493065930669306793068930699307093071930729307393074930759307693077930789307993080930819308293083930849308593086930879308893089930909309193092930939309493095930969309793098930999310093101931029310393104931059310693107931089310993110931119311293113931149311593116931179311893119931209312193122931239312493125931269312793128931299313093131931329313393134931359313693137931389313993140931419314293143931449314593146931479314893149931509315193152931539315493155931569315793158931599316093161931629316393164931659316693167931689316993170931719317293173931749317593176931779317893179931809318193182931839318493185931869318793188931899319093191931929319393194931959319693197931989319993200932019320293203932049320593206932079320893209932109321193212932139321493215932169321793218932199322093221932229322393224932259322693227932289322993230932319323293233932349323593236932379323893239932409324193242932439324493245932469324793248932499325093251932529325393254932559325693257932589325993260932619326293263932649326593266932679326893269932709327193272932739327493275932769327793278932799328093281932829328393284932859328693287932889328993290932919329293293932949329593296932979329893299933009330193302933039330493305933069330793308933099331093311933129331393314933159331693317933189331993320933219332293323933249332593326933279332893329933309333193332933339333493335933369333793338933399334093341933429334393344933459334693347933489334993350933519335293353933549335593356933579335893359933609336193362933639336493365933669336793368933699337093371933729337393374933759337693377933789337993380933819338293383933849338593386933879338893389933909339193392933939339493395933969339793398933999340093401934029340393404934059340693407934089340993410934119341293413934149341593416934179341893419934209342193422934239342493425934269342793428934299343093431934329343393434934359343693437934389343993440934419344293443934449344593446934479344893449934509345193452934539345493455934569345793458934599346093461934629346393464934659346693467934689346993470934719347293473934749347593476934779347893479934809348193482934839348493485934869348793488934899349093491934929349393494934959349693497934989349993500935019350293503935049350593506935079350893509935109351193512935139351493515935169351793518935199352093521935229352393524935259352693527935289352993530935319353293533935349353593536935379353893539935409354193542935439354493545935469354793548935499355093551935529355393554935559355693557935589355993560935619356293563935649356593566935679356893569935709357193572935739357493575935769357793578935799358093581935829358393584935859358693587935889358993590935919359293593935949359593596935979359893599936009360193602936039360493605936069360793608936099361093611936129361393614936159361693617936189361993620936219362293623936249362593626936279362893629936309363193632936339363493635936369363793638936399364093641936429364393644936459364693647936489364993650936519365293653936549365593656936579365893659936609366193662936639366493665936669366793668936699367093671936729367393674936759367693677936789367993680936819368293683936849368593686936879368893689936909369193692936939369493695936969369793698936999370093701937029370393704937059370693707937089370993710937119371293713937149371593716937179371893719937209372193722937239372493725937269372793728937299373093731937329373393734937359373693737937389373993740937419374293743937449374593746937479374893749937509375193752937539375493755937569375793758937599376093761937629376393764937659376693767937689376993770937719377293773937749377593776937779377893779937809378193782937839378493785937869378793788937899379093791937929379393794937959379693797937989379993800938019380293803938049380593806938079380893809938109381193812938139381493815938169381793818938199382093821938229382393824938259382693827938289382993830938319383293833938349383593836938379383893839938409384193842938439384493845938469384793848938499385093851938529385393854938559385693857938589385993860938619386293863938649386593866938679386893869938709387193872938739387493875938769387793878938799388093881938829388393884938859388693887938889388993890938919389293893938949389593896938979389893899939009390193902939039390493905939069390793908939099391093911939129391393914939159391693917939189391993920939219392293923939249392593926939279392893929939309393193932939339393493935939369393793938939399394093941939429394393944939459394693947939489394993950939519395293953939549395593956939579395893959939609396193962939639396493965939669396793968939699397093971939729397393974939759397693977939789397993980939819398293983939849398593986939879398893989939909399193992939939399493995939969399793998939999400094001940029400394004940059400694007940089400994010940119401294013940149401594016940179401894019940209402194022940239402494025940269402794028940299403094031940329403394034940359403694037940389403994040940419404294043940449404594046940479404894049940509405194052940539405494055940569405794058940599406094061940629406394064940659406694067940689406994070940719407294073940749407594076940779407894079940809408194082940839408494085940869408794088940899409094091940929409394094940959409694097940989409994100941019410294103941049410594106941079410894109941109411194112941139411494115941169411794118941199412094121941229412394124941259412694127941289412994130941319413294133941349413594136941379413894139941409414194142941439414494145941469414794148941499415094151941529415394154941559415694157941589415994160941619416294163941649416594166941679416894169941709417194172941739417494175941769417794178941799418094181941829418394184941859418694187941889418994190941919419294193941949419594196941979419894199942009420194202942039420494205942069420794208942099421094211942129421394214942159421694217942189421994220942219422294223942249422594226942279422894229942309423194232942339423494235942369423794238942399424094241942429424394244942459424694247942489424994250942519425294253942549425594256942579425894259942609426194262942639426494265942669426794268942699427094271942729427394274942759427694277942789427994280942819428294283942849428594286942879428894289942909429194292942939429494295942969429794298942999430094301943029430394304943059430694307943089430994310943119431294313943149431594316943179431894319943209432194322943239432494325943269432794328943299433094331943329433394334943359433694337943389433994340943419434294343943449434594346943479434894349943509435194352943539435494355943569435794358943599436094361943629436394364943659436694367943689436994370943719437294373943749437594376943779437894379943809438194382943839438494385943869438794388943899439094391943929439394394943959439694397943989439994400944019440294403944049440594406944079440894409944109441194412944139441494415944169441794418944199442094421944229442394424944259442694427944289442994430944319443294433944349443594436944379443894439944409444194442944439444494445944469444794448944499445094451944529445394454944559445694457944589445994460944619446294463944649446594466944679446894469944709447194472944739447494475944769447794478944799448094481944829448394484944859448694487944889448994490944919449294493944949449594496944979449894499945009450194502945039450494505945069450794508945099451094511945129451394514945159451694517945189451994520945219452294523945249452594526945279452894529945309453194532945339453494535945369453794538945399454094541945429454394544945459454694547945489454994550945519455294553945549455594556945579455894559945609456194562945639456494565945669456794568945699457094571945729457394574945759457694577945789457994580945819458294583945849458594586945879458894589945909459194592945939459494595945969459794598945999460094601946029460394604946059460694607946089460994610946119461294613946149461594616946179461894619946209462194622946239462494625946269462794628946299463094631946329463394634946359463694637946389463994640946419464294643946449464594646946479464894649946509465194652946539465494655946569465794658946599466094661946629466394664946659466694667946689466994670946719467294673946749467594676946779467894679946809468194682946839468494685946869468794688946899469094691946929469394694946959469694697946989469994700947019470294703947049470594706947079470894709947109471194712947139471494715947169471794718947199472094721947229472394724947259472694727947289472994730947319473294733947349473594736947379473894739947409474194742947439474494745947469474794748947499475094751947529475394754947559475694757947589475994760947619476294763947649476594766947679476894769947709477194772947739477494775947769477794778947799478094781947829478394784947859478694787947889478994790947919479294793947949479594796947979479894799948009480194802948039480494805948069480794808948099481094811948129481394814948159481694817948189481994820948219482294823948249482594826948279482894829948309483194832948339483494835948369483794838948399484094841948429484394844948459484694847948489484994850948519485294853948549485594856948579485894859948609486194862948639486494865948669486794868948699487094871948729487394874948759487694877948789487994880948819488294883948849488594886948879488894889948909489194892948939489494895948969489794898948999490094901949029490394904949059490694907949089490994910949119491294913949149491594916949179491894919949209492194922949239492494925949269492794928949299493094931949329493394934949359493694937949389493994940949419494294943949449494594946949479494894949949509495194952949539495494955949569495794958949599496094961949629496394964949659496694967949689496994970949719497294973949749497594976949779497894979949809498194982949839498494985949869498794988949899499094991949929499394994949959499694997949989499995000950019500295003950049500595006950079500895009950109501195012950139501495015950169501795018950199502095021950229502395024950259502695027950289502995030950319503295033950349503595036950379503895039950409504195042950439504495045950469504795048950499505095051950529505395054950559505695057950589505995060950619506295063950649506595066950679506895069950709507195072950739507495075950769507795078950799508095081950829508395084950859508695087950889508995090950919509295093950949509595096950979509895099951009510195102951039510495105951069510795108951099511095111951129511395114951159511695117951189511995120951219512295123951249512595126951279512895129951309513195132951339513495135951369513795138951399514095141951429514395144951459514695147951489514995150951519515295153951549515595156951579515895159951609516195162951639516495165951669516795168951699517095171951729517395174951759517695177951789517995180951819518295183951849518595186951879518895189951909519195192951939519495195951969519795198951999520095201952029520395204952059520695207952089520995210952119521295213952149521595216952179521895219952209522195222952239522495225952269522795228952299523095231952329523395234952359523695237952389523995240952419524295243952449524595246952479524895249952509525195252952539525495255952569525795258952599526095261952629526395264952659526695267952689526995270952719527295273952749527595276952779527895279952809528195282952839528495285952869528795288952899529095291952929529395294952959529695297952989529995300953019530295303953049530595306953079530895309953109531195312953139531495315953169531795318953199532095321953229532395324953259532695327953289532995330953319533295333953349533595336953379533895339953409534195342953439534495345953469534795348953499535095351953529535395354953559535695357953589535995360953619536295363953649536595366953679536895369953709537195372953739537495375953769537795378953799538095381953829538395384953859538695387953889538995390953919539295393953949539595396953979539895399954009540195402954039540495405954069540795408954099541095411954129541395414954159541695417954189541995420954219542295423954249542595426954279542895429954309543195432954339543495435954369543795438954399544095441954429544395444954459544695447954489544995450954519545295453954549545595456954579545895459954609546195462954639546495465954669546795468954699547095471954729547395474954759547695477954789547995480954819548295483954849548595486954879548895489954909549195492954939549495495954969549795498954999550095501955029550395504955059550695507955089550995510955119551295513955149551595516955179551895519955209552195522955239552495525955269552795528955299553095531955329553395534955359553695537955389553995540955419554295543955449554595546955479554895549955509555195552955539555495555955569555795558955599556095561955629556395564955659556695567955689556995570955719557295573955749557595576955779557895579955809558195582955839558495585955869558795588955899559095591955929559395594955959559695597955989559995600956019560295603956049560595606956079560895609956109561195612956139561495615956169561795618956199562095621956229562395624956259562695627956289562995630956319563295633956349563595636956379563895639956409564195642956439564495645956469564795648956499565095651956529565395654956559565695657956589565995660956619566295663956649566595666956679566895669956709567195672956739567495675956769567795678956799568095681956829568395684956859568695687956889568995690956919569295693956949569595696956979569895699957009570195702957039570495705957069570795708957099571095711957129571395714957159571695717957189571995720957219572295723957249572595726957279572895729957309573195732957339573495735957369573795738957399574095741957429574395744957459574695747957489574995750957519575295753957549575595756957579575895759957609576195762957639576495765957669576795768957699577095771957729577395774957759577695777957789577995780957819578295783957849578595786957879578895789957909579195792957939579495795957969579795798957999580095801958029580395804958059580695807958089580995810958119581295813958149581595816958179581895819958209582195822958239582495825958269582795828958299583095831958329583395834958359583695837958389583995840958419584295843958449584595846958479584895849958509585195852958539585495855958569585795858958599586095861958629586395864958659586695867958689586995870958719587295873958749587595876958779587895879958809588195882958839588495885958869588795888958899589095891958929589395894958959589695897958989589995900959019590295903 |
- /*! @brief `EnTT` default namespace. */
- namespace entt {}
- // IWYU pragma: begin_exports
- // #include "config/config.h"
- #ifndef ENTT_CONFIG_CONFIG_H
- #define ENTT_CONFIG_CONFIG_H
- // #include "version.h"
- #ifndef ENTT_CONFIG_VERSION_H
- #define ENTT_CONFIG_VERSION_H
- // #include "macro.h"
- #ifndef ENTT_CONFIG_MACRO_H
- #define ENTT_CONFIG_MACRO_H
- // NOLINTBEGIN(cppcoreguidelines-macro-usage)
- #define ENTT_STR(arg) #arg
- #define ENTT_XSTR(arg) ENTT_STR(arg)
- // NOLINTEND(cppcoreguidelines-macro-usage)
- #endif
- // NOLINTBEGIN(cppcoreguidelines-macro-*,modernize-macro-*)
- #define ENTT_VERSION_MAJOR 3
- #define ENTT_VERSION_MINOR 16
- #define ENTT_VERSION_PATCH 0
- #define ENTT_VERSION \
- ENTT_XSTR(ENTT_VERSION_MAJOR) \
- "." ENTT_XSTR(ENTT_VERSION_MINOR) "." ENTT_XSTR(ENTT_VERSION_PATCH)
- // NOLINTEND(cppcoreguidelines-macro-*,modernize-macro-*)
- #endif
- // NOLINTBEGIN(cppcoreguidelines-macro-usage)
- #if defined(__cpp_exceptions) && !defined(ENTT_NOEXCEPTION)
- # define ENTT_CONSTEXPR
- # define ENTT_THROW throw
- # define ENTT_TRY try
- # define ENTT_CATCH catch(...)
- #else
- # define ENTT_CONSTEXPR constexpr // use only with throwing functions (waiting for C++20)
- # define ENTT_THROW
- # define ENTT_TRY if(true)
- # define ENTT_CATCH if(false)
- #endif
- #if __has_include(<version>)
- # include <version>
- #
- # if defined(__cpp_consteval)
- # define ENTT_CONSTEVAL consteval
- # endif
- #endif
- #ifndef ENTT_CONSTEVAL
- # define ENTT_CONSTEVAL constexpr
- #endif
- #ifdef ENTT_USE_ATOMIC
- # include <atomic>
- # define ENTT_MAYBE_ATOMIC(Type) std::atomic<Type>
- #else
- # define ENTT_MAYBE_ATOMIC(Type) Type
- #endif
- #ifndef ENTT_ID_TYPE
- # include <cstdint>
- # define ENTT_ID_TYPE std::uint32_t
- #else
- # include <cstdint> // provides coverage for types in the std namespace
- #endif
- #ifndef ENTT_SPARSE_PAGE
- # define ENTT_SPARSE_PAGE 4096
- #endif
- #ifndef ENTT_PACKED_PAGE
- # define ENTT_PACKED_PAGE 1024
- #endif
- #ifdef ENTT_DISABLE_ASSERT
- # undef ENTT_ASSERT
- # define ENTT_ASSERT(condition, msg) (void(0))
- #elif !defined ENTT_ASSERT
- # include <cassert>
- # define ENTT_ASSERT(condition, msg) assert(((condition) && (msg)))
- #endif
- #ifdef ENTT_DISABLE_ASSERT
- # undef ENTT_ASSERT_CONSTEXPR
- # define ENTT_ASSERT_CONSTEXPR(condition, msg) (void(0))
- #elif !defined ENTT_ASSERT_CONSTEXPR
- # define ENTT_ASSERT_CONSTEXPR(condition, msg) ENTT_ASSERT(condition, msg)
- #endif
- #define ENTT_FAIL(msg) ENTT_ASSERT(false, msg);
- #ifdef ENTT_NO_ETO
- # define ENTT_ETO_TYPE(Type) void
- #else
- # define ENTT_ETO_TYPE(Type) Type
- #endif
- #ifdef ENTT_NO_MIXIN
- # define ENTT_STORAGE(Mixin, ...) __VA_ARGS__
- #else
- # define ENTT_STORAGE(Mixin, ...) Mixin<__VA_ARGS__>
- #endif
- #ifdef ENTT_STANDARD_CPP
- # define ENTT_NONSTD false
- #else
- # define ENTT_NONSTD true
- # if defined __clang__ || defined __GNUC__
- # define ENTT_PRETTY_FUNCTION __PRETTY_FUNCTION__
- # define ENTT_PRETTY_FUNCTION_PREFIX '='
- # define ENTT_PRETTY_FUNCTION_SUFFIX ']'
- # elif defined _MSC_VER
- # define ENTT_PRETTY_FUNCTION __FUNCSIG__
- # define ENTT_PRETTY_FUNCTION_PREFIX '<'
- # define ENTT_PRETTY_FUNCTION_SUFFIX '>'
- # endif
- #endif
- #ifndef ENTT_EXPORT
- # if defined _WIN32 || defined __CYGWIN__ || defined _MSC_VER
- # define ENTT_EXPORT __declspec(dllexport)
- # define ENTT_IMPORT __declspec(dllimport)
- # define ENTT_HIDDEN
- # elif defined __GNUC__ && __GNUC__ >= 4
- # define ENTT_EXPORT __attribute__((visibility("default")))
- # define ENTT_IMPORT __attribute__((visibility("default")))
- # define ENTT_HIDDEN __attribute__((visibility("hidden")))
- # else /* Unsupported compiler */
- # define ENTT_EXPORT
- # define ENTT_IMPORT
- # define ENTT_HIDDEN
- # endif
- #endif
- #ifndef ENTT_API
- # if defined ENTT_API_EXPORT
- # define ENTT_API ENTT_EXPORT
- # elif defined ENTT_API_IMPORT
- # define ENTT_API ENTT_IMPORT
- # else /* No API */
- # define ENTT_API
- # endif
- #endif
- #if defined _MSC_VER
- # pragma detect_mismatch("entt.version", ENTT_VERSION)
- # pragma detect_mismatch("entt.noexcept", ENTT_XSTR(ENTT_TRY))
- # pragma detect_mismatch("entt.id", ENTT_XSTR(ENTT_ID_TYPE))
- # pragma detect_mismatch("entt.nonstd", ENTT_XSTR(ENTT_NONSTD))
- #endif
- // NOLINTEND(cppcoreguidelines-macro-usage)
- #endif
- // #include "config/macro.h"
- #ifndef ENTT_CONFIG_MACRO_H
- #define ENTT_CONFIG_MACRO_H
- // NOLINTBEGIN(cppcoreguidelines-macro-usage)
- #define ENTT_STR(arg) #arg
- #define ENTT_XSTR(arg) ENTT_STR(arg)
- // NOLINTEND(cppcoreguidelines-macro-usage)
- #endif
- // #include "config/version.h"
- #ifndef ENTT_CONFIG_VERSION_H
- #define ENTT_CONFIG_VERSION_H
- // #include "macro.h"
- // NOLINTBEGIN(cppcoreguidelines-macro-*,modernize-macro-*)
- #define ENTT_VERSION_MAJOR 3
- #define ENTT_VERSION_MINOR 16
- #define ENTT_VERSION_PATCH 0
- #define ENTT_VERSION \
- ENTT_XSTR(ENTT_VERSION_MAJOR) \
- "." ENTT_XSTR(ENTT_VERSION_MINOR) "." ENTT_XSTR(ENTT_VERSION_PATCH)
- // NOLINTEND(cppcoreguidelines-macro-*,modernize-macro-*)
- #endif
- // #include "container/dense_map.hpp"
- #ifndef ENTT_CONTAINER_DENSE_MAP_HPP
- #define ENTT_CONTAINER_DENSE_MAP_HPP
- #include <cmath>
- #include <cstddef>
- #include <functional>
- #include <iterator>
- #include <limits>
- #include <memory>
- #include <tuple>
- #include <type_traits>
- #include <utility>
- #include <vector>
- // #include "../config/config.h"
- #ifndef ENTT_CONFIG_CONFIG_H
- #define ENTT_CONFIG_CONFIG_H
- // #include "version.h"
- #ifndef ENTT_CONFIG_VERSION_H
- #define ENTT_CONFIG_VERSION_H
- // #include "macro.h"
- #ifndef ENTT_CONFIG_MACRO_H
- #define ENTT_CONFIG_MACRO_H
- // NOLINTBEGIN(cppcoreguidelines-macro-usage)
- #define ENTT_STR(arg) #arg
- #define ENTT_XSTR(arg) ENTT_STR(arg)
- // NOLINTEND(cppcoreguidelines-macro-usage)
- #endif
- // NOLINTBEGIN(cppcoreguidelines-macro-*,modernize-macro-*)
- #define ENTT_VERSION_MAJOR 3
- #define ENTT_VERSION_MINOR 16
- #define ENTT_VERSION_PATCH 0
- #define ENTT_VERSION \
- ENTT_XSTR(ENTT_VERSION_MAJOR) \
- "." ENTT_XSTR(ENTT_VERSION_MINOR) "." ENTT_XSTR(ENTT_VERSION_PATCH)
- // NOLINTEND(cppcoreguidelines-macro-*,modernize-macro-*)
- #endif
- // NOLINTBEGIN(cppcoreguidelines-macro-usage)
- #if defined(__cpp_exceptions) && !defined(ENTT_NOEXCEPTION)
- # define ENTT_CONSTEXPR
- # define ENTT_THROW throw
- # define ENTT_TRY try
- # define ENTT_CATCH catch(...)
- #else
- # define ENTT_CONSTEXPR constexpr // use only with throwing functions (waiting for C++20)
- # define ENTT_THROW
- # define ENTT_TRY if(true)
- # define ENTT_CATCH if(false)
- #endif
- #if __has_include(<version>)
- # include <version>
- #
- # if defined(__cpp_consteval)
- # define ENTT_CONSTEVAL consteval
- # endif
- #endif
- #ifndef ENTT_CONSTEVAL
- # define ENTT_CONSTEVAL constexpr
- #endif
- #ifdef ENTT_USE_ATOMIC
- # include <atomic>
- # define ENTT_MAYBE_ATOMIC(Type) std::atomic<Type>
- #else
- # define ENTT_MAYBE_ATOMIC(Type) Type
- #endif
- #ifndef ENTT_ID_TYPE
- # include <cstdint>
- # define ENTT_ID_TYPE std::uint32_t
- #else
- # include <cstdint> // provides coverage for types in the std namespace
- #endif
- #ifndef ENTT_SPARSE_PAGE
- # define ENTT_SPARSE_PAGE 4096
- #endif
- #ifndef ENTT_PACKED_PAGE
- # define ENTT_PACKED_PAGE 1024
- #endif
- #ifdef ENTT_DISABLE_ASSERT
- # undef ENTT_ASSERT
- # define ENTT_ASSERT(condition, msg) (void(0))
- #elif !defined ENTT_ASSERT
- # include <cassert>
- # define ENTT_ASSERT(condition, msg) assert(((condition) && (msg)))
- #endif
- #ifdef ENTT_DISABLE_ASSERT
- # undef ENTT_ASSERT_CONSTEXPR
- # define ENTT_ASSERT_CONSTEXPR(condition, msg) (void(0))
- #elif !defined ENTT_ASSERT_CONSTEXPR
- # define ENTT_ASSERT_CONSTEXPR(condition, msg) ENTT_ASSERT(condition, msg)
- #endif
- #define ENTT_FAIL(msg) ENTT_ASSERT(false, msg);
- #ifdef ENTT_NO_ETO
- # define ENTT_ETO_TYPE(Type) void
- #else
- # define ENTT_ETO_TYPE(Type) Type
- #endif
- #ifdef ENTT_NO_MIXIN
- # define ENTT_STORAGE(Mixin, ...) __VA_ARGS__
- #else
- # define ENTT_STORAGE(Mixin, ...) Mixin<__VA_ARGS__>
- #endif
- #ifdef ENTT_STANDARD_CPP
- # define ENTT_NONSTD false
- #else
- # define ENTT_NONSTD true
- # if defined __clang__ || defined __GNUC__
- # define ENTT_PRETTY_FUNCTION __PRETTY_FUNCTION__
- # define ENTT_PRETTY_FUNCTION_PREFIX '='
- # define ENTT_PRETTY_FUNCTION_SUFFIX ']'
- # elif defined _MSC_VER
- # define ENTT_PRETTY_FUNCTION __FUNCSIG__
- # define ENTT_PRETTY_FUNCTION_PREFIX '<'
- # define ENTT_PRETTY_FUNCTION_SUFFIX '>'
- # endif
- #endif
- #ifndef ENTT_EXPORT
- # if defined _WIN32 || defined __CYGWIN__ || defined _MSC_VER
- # define ENTT_EXPORT __declspec(dllexport)
- # define ENTT_IMPORT __declspec(dllimport)
- # define ENTT_HIDDEN
- # elif defined __GNUC__ && __GNUC__ >= 4
- # define ENTT_EXPORT __attribute__((visibility("default")))
- # define ENTT_IMPORT __attribute__((visibility("default")))
- # define ENTT_HIDDEN __attribute__((visibility("hidden")))
- # else /* Unsupported compiler */
- # define ENTT_EXPORT
- # define ENTT_IMPORT
- # define ENTT_HIDDEN
- # endif
- #endif
- #ifndef ENTT_API
- # if defined ENTT_API_EXPORT
- # define ENTT_API ENTT_EXPORT
- # elif defined ENTT_API_IMPORT
- # define ENTT_API ENTT_IMPORT
- # else /* No API */
- # define ENTT_API
- # endif
- #endif
- #if defined _MSC_VER
- # pragma detect_mismatch("entt.version", ENTT_VERSION)
- # pragma detect_mismatch("entt.noexcept", ENTT_XSTR(ENTT_TRY))
- # pragma detect_mismatch("entt.id", ENTT_XSTR(ENTT_ID_TYPE))
- # pragma detect_mismatch("entt.nonstd", ENTT_XSTR(ENTT_NONSTD))
- #endif
- // NOLINTEND(cppcoreguidelines-macro-usage)
- #endif
- // #include "../core/bit.hpp"
- #ifndef ENTT_CORE_BIT_HPP
- #define ENTT_CORE_BIT_HPP
- #include <cstddef>
- #include <limits>
- #include <type_traits>
- // #include "../config/config.h"
- #ifndef ENTT_CONFIG_CONFIG_H
- #define ENTT_CONFIG_CONFIG_H
- // #include "version.h"
- #ifndef ENTT_CONFIG_VERSION_H
- #define ENTT_CONFIG_VERSION_H
- // #include "macro.h"
- #ifndef ENTT_CONFIG_MACRO_H
- #define ENTT_CONFIG_MACRO_H
- // NOLINTBEGIN(cppcoreguidelines-macro-usage)
- #define ENTT_STR(arg) #arg
- #define ENTT_XSTR(arg) ENTT_STR(arg)
- // NOLINTEND(cppcoreguidelines-macro-usage)
- #endif
- // NOLINTBEGIN(cppcoreguidelines-macro-*,modernize-macro-*)
- #define ENTT_VERSION_MAJOR 3
- #define ENTT_VERSION_MINOR 16
- #define ENTT_VERSION_PATCH 0
- #define ENTT_VERSION \
- ENTT_XSTR(ENTT_VERSION_MAJOR) \
- "." ENTT_XSTR(ENTT_VERSION_MINOR) "." ENTT_XSTR(ENTT_VERSION_PATCH)
- // NOLINTEND(cppcoreguidelines-macro-*,modernize-macro-*)
- #endif
- // NOLINTBEGIN(cppcoreguidelines-macro-usage)
- #if defined(__cpp_exceptions) && !defined(ENTT_NOEXCEPTION)
- # define ENTT_CONSTEXPR
- # define ENTT_THROW throw
- # define ENTT_TRY try
- # define ENTT_CATCH catch(...)
- #else
- # define ENTT_CONSTEXPR constexpr // use only with throwing functions (waiting for C++20)
- # define ENTT_THROW
- # define ENTT_TRY if(true)
- # define ENTT_CATCH if(false)
- #endif
- #if __has_include(<version>)
- # include <version>
- #
- # if defined(__cpp_consteval)
- # define ENTT_CONSTEVAL consteval
- # endif
- #endif
- #ifndef ENTT_CONSTEVAL
- # define ENTT_CONSTEVAL constexpr
- #endif
- #ifdef ENTT_USE_ATOMIC
- # include <atomic>
- # define ENTT_MAYBE_ATOMIC(Type) std::atomic<Type>
- #else
- # define ENTT_MAYBE_ATOMIC(Type) Type
- #endif
- #ifndef ENTT_ID_TYPE
- # include <cstdint>
- # define ENTT_ID_TYPE std::uint32_t
- #else
- # include <cstdint> // provides coverage for types in the std namespace
- #endif
- #ifndef ENTT_SPARSE_PAGE
- # define ENTT_SPARSE_PAGE 4096
- #endif
- #ifndef ENTT_PACKED_PAGE
- # define ENTT_PACKED_PAGE 1024
- #endif
- #ifdef ENTT_DISABLE_ASSERT
- # undef ENTT_ASSERT
- # define ENTT_ASSERT(condition, msg) (void(0))
- #elif !defined ENTT_ASSERT
- # include <cassert>
- # define ENTT_ASSERT(condition, msg) assert(((condition) && (msg)))
- #endif
- #ifdef ENTT_DISABLE_ASSERT
- # undef ENTT_ASSERT_CONSTEXPR
- # define ENTT_ASSERT_CONSTEXPR(condition, msg) (void(0))
- #elif !defined ENTT_ASSERT_CONSTEXPR
- # define ENTT_ASSERT_CONSTEXPR(condition, msg) ENTT_ASSERT(condition, msg)
- #endif
- #define ENTT_FAIL(msg) ENTT_ASSERT(false, msg);
- #ifdef ENTT_NO_ETO
- # define ENTT_ETO_TYPE(Type) void
- #else
- # define ENTT_ETO_TYPE(Type) Type
- #endif
- #ifdef ENTT_NO_MIXIN
- # define ENTT_STORAGE(Mixin, ...) __VA_ARGS__
- #else
- # define ENTT_STORAGE(Mixin, ...) Mixin<__VA_ARGS__>
- #endif
- #ifdef ENTT_STANDARD_CPP
- # define ENTT_NONSTD false
- #else
- # define ENTT_NONSTD true
- # if defined __clang__ || defined __GNUC__
- # define ENTT_PRETTY_FUNCTION __PRETTY_FUNCTION__
- # define ENTT_PRETTY_FUNCTION_PREFIX '='
- # define ENTT_PRETTY_FUNCTION_SUFFIX ']'
- # elif defined _MSC_VER
- # define ENTT_PRETTY_FUNCTION __FUNCSIG__
- # define ENTT_PRETTY_FUNCTION_PREFIX '<'
- # define ENTT_PRETTY_FUNCTION_SUFFIX '>'
- # endif
- #endif
- #ifndef ENTT_EXPORT
- # if defined _WIN32 || defined __CYGWIN__ || defined _MSC_VER
- # define ENTT_EXPORT __declspec(dllexport)
- # define ENTT_IMPORT __declspec(dllimport)
- # define ENTT_HIDDEN
- # elif defined __GNUC__ && __GNUC__ >= 4
- # define ENTT_EXPORT __attribute__((visibility("default")))
- # define ENTT_IMPORT __attribute__((visibility("default")))
- # define ENTT_HIDDEN __attribute__((visibility("hidden")))
- # else /* Unsupported compiler */
- # define ENTT_EXPORT
- # define ENTT_IMPORT
- # define ENTT_HIDDEN
- # endif
- #endif
- #ifndef ENTT_API
- # if defined ENTT_API_EXPORT
- # define ENTT_API ENTT_EXPORT
- # elif defined ENTT_API_IMPORT
- # define ENTT_API ENTT_IMPORT
- # else /* No API */
- # define ENTT_API
- # endif
- #endif
- #if defined _MSC_VER
- # pragma detect_mismatch("entt.version", ENTT_VERSION)
- # pragma detect_mismatch("entt.noexcept", ENTT_XSTR(ENTT_TRY))
- # pragma detect_mismatch("entt.id", ENTT_XSTR(ENTT_ID_TYPE))
- # pragma detect_mismatch("entt.nonstd", ENTT_XSTR(ENTT_NONSTD))
- #endif
- // NOLINTEND(cppcoreguidelines-macro-usage)
- #endif
- namespace entt {
- /**
- * @brief Returns the number of set bits in a value (waiting for C++20 and
- * `std::popcount`).
- * @tparam Type Unsigned integer type.
- * @param value A value of unsigned integer type.
- * @return The number of set bits in the value.
- */
- template<typename Type>
- [[nodiscard]] constexpr std::enable_if_t<std::is_unsigned_v<Type>, int> popcount(const Type value) noexcept {
- return value ? (int(value & 1) + popcount(static_cast<Type>(value >> 1))) : 0;
- }
- /**
- * @brief Checks whether a value is a power of two or not (waiting for C++20 and
- * `std::has_single_bit`).
- * @tparam Type Unsigned integer type.
- * @param value A value of unsigned integer type.
- * @return True if the value is a power of two, false otherwise.
- */
- template<typename Type>
- [[nodiscard]] constexpr std::enable_if_t<std::is_unsigned_v<Type>, bool> has_single_bit(const Type value) noexcept {
- return value && ((value & (value - 1)) == 0);
- }
- /**
- * @brief Computes the smallest power of two greater than or equal to a value
- * (waiting for C++20 and `std::bit_ceil`).
- * @tparam Type Unsigned integer type.
- * @param value A value of unsigned integer type.
- * @return The smallest power of two greater than or equal to the given value.
- */
- template<typename Type>
- [[nodiscard]] constexpr std::enable_if_t<std::is_unsigned_v<Type>, Type> next_power_of_two(const Type value) noexcept {
- // NOLINTNEXTLINE(bugprone-assert-side-effect)
- ENTT_ASSERT_CONSTEXPR(value < (Type{1u} << (std::numeric_limits<Type>::digits - 1)), "Numeric limits exceeded");
- Type curr = value - (value != 0u);
- for(int next = 1; next < std::numeric_limits<Type>::digits; next = next * 2) {
- curr |= (curr >> next);
- }
- return ++curr;
- }
- /**
- * @brief Fast module utility function (powers of two only).
- * @tparam Type Unsigned integer type.
- * @param value A value of unsigned integer type.
- * @param mod _Modulus_, it must be a power of two.
- * @return The common remainder.
- */
- template<typename Type>
- [[nodiscard]] constexpr std::enable_if_t<std::is_unsigned_v<Type>, Type> fast_mod(const Type value, const std::size_t mod) noexcept {
- ENTT_ASSERT_CONSTEXPR(has_single_bit(mod), "Value must be a power of two");
- return static_cast<Type>(value & (mod - 1u));
- }
- } // namespace entt
- #endif
- // #include "../core/compressed_pair.hpp"
- #ifndef ENTT_CORE_COMPRESSED_PAIR_HPP
- #define ENTT_CORE_COMPRESSED_PAIR_HPP
- #include <cstddef>
- #include <tuple>
- #include <type_traits>
- #include <utility>
- // #include "fwd.hpp"
- #ifndef ENTT_CORE_FWD_HPP
- #define ENTT_CORE_FWD_HPP
- #include <cstddef>
- #include <cstdint>
- // #include "../config/config.h"
- namespace entt {
- /*! @brief Possible modes of an any object. */
- enum class any_policy : std::uint8_t {
- /*! @brief Default mode, no element available. */
- empty,
- /*! @brief Owning mode, dynamically allocated element. */
- dynamic,
- /*! @brief Owning mode, embedded element. */
- embedded,
- /*! @brief Aliasing mode, non-const reference. */
- ref,
- /*! @brief Const aliasing mode, const reference. */
- cref
- };
- // NOLINTNEXTLINE(cppcoreguidelines-avoid-c-arrays, modernize-avoid-c-arrays)
- template<std::size_t Len = sizeof(double[2]), std::size_t = alignof(double[2])>
- class basic_any;
- /*! @brief Alias declaration for type identifiers. */
- using id_type = ENTT_ID_TYPE;
- /*! @brief Alias declaration for the most common use case. */
- using any = basic_any<>;
- template<typename, typename>
- class compressed_pair;
- template<typename>
- class basic_hashed_string;
- /*! @brief Aliases for common character types. */
- using hashed_string = basic_hashed_string<char>;
- /*! @brief Aliases for common character types. */
- using hashed_wstring = basic_hashed_string<wchar_t>;
- // NOLINTNEXTLINE(bugprone-forward-declaration-namespace)
- struct type_info;
- } // namespace entt
- #endif
- // #include "type_traits.hpp"
- #ifndef ENTT_CORE_TYPE_TRAITS_HPP
- #define ENTT_CORE_TYPE_TRAITS_HPP
- #include <cstddef>
- #include <iterator>
- #include <tuple>
- #include <type_traits>
- #include <utility>
- // #include "../config/config.h"
- // #include "fwd.hpp"
- namespace entt {
- /**
- * @brief Utility class to disambiguate overloaded functions.
- * @tparam N Number of choices available.
- */
- template<std::size_t N>
- struct choice_t
- // unfortunately, doxygen cannot parse such a construct
- : /*! @cond TURN_OFF_DOXYGEN */ choice_t<N - 1> /*! @endcond */
- {};
- /*! @copybrief choice_t */
- template<>
- struct choice_t<0> {};
- /**
- * @brief Variable template for the choice trick.
- * @tparam N Number of choices available.
- */
- template<std::size_t N>
- inline constexpr choice_t<N> choice{};
- /**
- * @brief Identity type trait.
- *
- * Useful to establish non-deduced contexts in template argument deduction
- * (waiting for C++20) or to provide types through function arguments.
- *
- * @tparam Type A type.
- */
- template<typename Type>
- struct type_identity {
- /*! @brief Identity type. */
- using type = Type;
- };
- /**
- * @brief Helper type.
- * @tparam Type A type.
- */
- template<typename Type>
- using type_identity_t = typename type_identity<Type>::type;
- /**
- * @brief A type-only `sizeof` wrapper that returns 0 where `sizeof` complains.
- * @tparam Type The type of which to return the size.
- */
- template<typename Type, typename = void>
- struct size_of: std::integral_constant<std::size_t, 0u> {};
- /*! @copydoc size_of */
- template<typename Type>
- struct size_of<Type, std::void_t<decltype(sizeof(Type))>>
- // NOLINTNEXTLINE(bugprone-sizeof-expression)
- : std::integral_constant<std::size_t, sizeof(Type)> {};
- /**
- * @brief Helper variable template.
- * @tparam Type The type of which to return the size.
- */
- template<typename Type>
- inline constexpr std::size_t size_of_v = size_of<Type>::value;
- /**
- * @brief Using declaration to be used to _repeat_ the same type a number of
- * times equal to the size of a given parameter pack.
- * @tparam Type A type to repeat.
- */
- template<typename Type, typename>
- using unpack_as_type = Type;
- /**
- * @brief Helper variable template to be used to _repeat_ the same value a
- * number of times equal to the size of a given parameter pack.
- * @tparam Value A value to repeat.
- */
- template<auto Value, typename>
- inline constexpr auto unpack_as_value = Value;
- /**
- * @brief Wraps a static constant.
- * @tparam Value A static constant.
- */
- template<auto Value>
- using integral_constant = std::integral_constant<decltype(Value), Value>;
- /**
- * @brief Alias template to facilitate the creation of named values.
- * @tparam Value A constant value at least convertible to `id_type`.
- */
- template<id_type Value>
- using tag = integral_constant<Value>;
- /**
- * @brief A class to use to push around lists of types, nothing more.
- * @tparam Type Types provided by the type list.
- */
- template<typename... Type>
- struct type_list {
- /*! @brief Type list type. */
- using type = type_list;
- /*! @brief Compile-time number of elements in the type list. */
- static constexpr auto size = sizeof...(Type);
- };
- /*! @brief Primary template isn't defined on purpose. */
- template<std::size_t, typename>
- struct type_list_element;
- /**
- * @brief Provides compile-time indexed access to the types of a type list.
- * @tparam Index Index of the type to return.
- * @tparam First First type provided by the type list.
- * @tparam Other Other types provided by the type list.
- */
- template<std::size_t Index, typename First, typename... Other>
- struct type_list_element<Index, type_list<First, Other...>>
- : type_list_element<Index - 1u, type_list<Other...>> {};
- /**
- * @brief Provides compile-time indexed access to the types of a type list.
- * @tparam First First type provided by the type list.
- * @tparam Other Other types provided by the type list.
- */
- template<typename First, typename... Other>
- struct type_list_element<0u, type_list<First, Other...>> {
- /*! @brief Searched type. */
- using type = First;
- };
- /**
- * @brief Helper type.
- * @tparam Index Index of the type to return.
- * @tparam List Type list to search into.
- */
- template<std::size_t Index, typename List>
- using type_list_element_t = typename type_list_element<Index, List>::type;
- /*! @brief Primary template isn't defined on purpose. */
- template<typename, typename>
- struct type_list_index;
- /**
- * @brief Provides compile-time type access to the types of a type list.
- * @tparam Type Type to look for and for which to return the index.
- * @tparam First First type provided by the type list.
- * @tparam Other Other types provided by the type list.
- */
- template<typename Type, typename First, typename... Other>
- struct type_list_index<Type, type_list<First, Other...>> {
- /*! @brief Unsigned integer type. */
- using value_type = std::size_t;
- /*! @brief Compile-time position of the given type in the sublist. */
- static constexpr value_type value = 1u + type_list_index<Type, type_list<Other...>>::value;
- };
- /**
- * @brief Provides compile-time type access to the types of a type list.
- * @tparam Type Type to look for and for which to return the index.
- * @tparam Other Other types provided by the type list.
- */
- template<typename Type, typename... Other>
- struct type_list_index<Type, type_list<Type, Other...>> {
- static_assert(type_list_index<Type, type_list<Other...>>::value == sizeof...(Other), "Non-unique type");
- /*! @brief Unsigned integer type. */
- using value_type = std::size_t;
- /*! @brief Compile-time position of the given type in the sublist. */
- static constexpr value_type value = 0u;
- };
- /**
- * @brief Provides compile-time type access to the types of a type list.
- * @tparam Type Type to look for and for which to return the index.
- */
- template<typename Type>
- struct type_list_index<Type, type_list<>> {
- /*! @brief Unsigned integer type. */
- using value_type = std::size_t;
- /*! @brief Compile-time position of the given type in the sublist. */
- static constexpr value_type value = 0u;
- };
- /**
- * @brief Helper variable template.
- * @tparam List Type list.
- * @tparam Type Type to look for and for which to return the index.
- */
- template<typename Type, typename List>
- inline constexpr std::size_t type_list_index_v = type_list_index<Type, List>::value;
- /**
- * @brief Concatenates multiple type lists.
- * @tparam Type Types provided by the first type list.
- * @tparam Other Types provided by the second type list.
- * @return A type list composed by the types of both the type lists.
- */
- template<typename... Type, typename... Other>
- constexpr type_list<Type..., Other...> operator+(type_list<Type...>, type_list<Other...>) {
- return {};
- }
- /*! @brief Primary template isn't defined on purpose. */
- template<typename...>
- struct type_list_cat;
- /*! @brief Concatenates multiple type lists. */
- template<>
- struct type_list_cat<> {
- /*! @brief A type list composed by the types of all the type lists. */
- using type = type_list<>;
- };
- /**
- * @brief Concatenates multiple type lists.
- * @tparam Type Types provided by the first type list.
- * @tparam Other Types provided by the second type list.
- * @tparam List Other type lists, if any.
- */
- template<typename... Type, typename... Other, typename... List>
- struct type_list_cat<type_list<Type...>, type_list<Other...>, List...> {
- /*! @brief A type list composed by the types of all the type lists. */
- using type = typename type_list_cat<type_list<Type..., Other...>, List...>::type;
- };
- /**
- * @brief Concatenates multiple type lists.
- * @tparam Type Types provided by the type list.
- */
- template<typename... Type>
- struct type_list_cat<type_list<Type...>> {
- /*! @brief A type list composed by the types of all the type lists. */
- using type = type_list<Type...>;
- };
- /**
- * @brief Helper type.
- * @tparam List Type lists to concatenate.
- */
- template<typename... List>
- using type_list_cat_t = typename type_list_cat<List...>::type;
- /*! @cond TURN_OFF_DOXYGEN */
- namespace internal {
- template<typename...>
- struct type_list_unique;
- template<typename First, typename... Other, typename... Type>
- struct type_list_unique<type_list<First, Other...>, Type...>
- : std::conditional_t<(std::is_same_v<First, Type> || ...), type_list_unique<type_list<Other...>, Type...>, type_list_unique<type_list<Other...>, Type..., First>> {};
- template<typename... Type>
- struct type_list_unique<type_list<>, Type...> {
- using type = type_list<Type...>;
- };
- } // namespace internal
- /*! @endcond */
- /**
- * @brief Removes duplicates types from a type list.
- * @tparam List Type list.
- */
- template<typename List>
- struct type_list_unique {
- /*! @brief A type list without duplicate types. */
- using type = typename internal::type_list_unique<List>::type;
- };
- /**
- * @brief Helper type.
- * @tparam List Type list.
- */
- template<typename List>
- using type_list_unique_t = typename type_list_unique<List>::type;
- /**
- * @brief Provides the member constant `value` to true if a type list contains a
- * given type, false otherwise.
- * @tparam List Type list.
- * @tparam Type Type to look for.
- */
- template<typename List, typename Type>
- struct type_list_contains;
- /**
- * @copybrief type_list_contains
- * @tparam Type Types provided by the type list.
- * @tparam Other Type to look for.
- */
- template<typename... Type, typename Other>
- struct type_list_contains<type_list<Type...>, Other>
- : std::bool_constant<(std::is_same_v<Type, Other> || ...)> {};
- /**
- * @brief Helper variable template.
- * @tparam List Type list.
- * @tparam Type Type to look for.
- */
- template<typename List, typename Type>
- inline constexpr bool type_list_contains_v = type_list_contains<List, Type>::value;
- /*! @brief Primary template isn't defined on purpose. */
- template<typename...>
- struct type_list_diff;
- /**
- * @brief Computes the difference between two type lists.
- * @tparam Type Types provided by the first type list.
- * @tparam Other Types provided by the second type list.
- */
- template<typename... Type, typename... Other>
- struct type_list_diff<type_list<Type...>, type_list<Other...>> {
- /*! @brief A type list that is the difference between the two type lists. */
- using type = type_list_cat_t<std::conditional_t<type_list_contains_v<type_list<Other...>, Type>, type_list<>, type_list<Type>>...>;
- };
- /**
- * @brief Helper type.
- * @tparam List Type lists between which to compute the difference.
- */
- template<typename... List>
- using type_list_diff_t = typename type_list_diff<List...>::type;
- /*! @brief Primary template isn't defined on purpose. */
- template<typename, template<typename...> class>
- struct type_list_transform;
- /**
- * @brief Applies a given _function_ to a type list and generate a new list.
- * @tparam Type Types provided by the type list.
- * @tparam Op Unary operation as template class with a type member named `type`.
- */
- template<typename... Type, template<typename...> class Op>
- struct type_list_transform<type_list<Type...>, Op> {
- /*! @brief Resulting type list after applying the transform function. */
- // NOLINTNEXTLINE(modernize-type-traits)
- using type = type_list<typename Op<Type>::type...>;
- };
- /**
- * @brief Helper type.
- * @tparam List Type list.
- * @tparam Op Unary operation as template class with a type member named `type`.
- */
- template<typename List, template<typename...> class Op>
- using type_list_transform_t = typename type_list_transform<List, Op>::type;
- /**
- * @brief A class to use to push around lists of constant values, nothing more.
- * @tparam Value Values provided by the value list.
- */
- template<auto... Value>
- struct value_list {
- /*! @brief Value list type. */
- using type = value_list;
- /*! @brief Compile-time number of elements in the value list. */
- static constexpr auto size = sizeof...(Value);
- };
- /*! @brief Primary template isn't defined on purpose. */
- template<std::size_t, typename>
- struct value_list_element;
- /**
- * @brief Provides compile-time indexed access to the values of a value list.
- * @tparam Index Index of the value to return.
- * @tparam Value First value provided by the value list.
- * @tparam Other Other values provided by the value list.
- */
- template<std::size_t Index, auto Value, auto... Other>
- struct value_list_element<Index, value_list<Value, Other...>>
- : value_list_element<Index - 1u, value_list<Other...>> {};
- /**
- * @brief Provides compile-time indexed access to the types of a type list.
- * @tparam Value First value provided by the value list.
- * @tparam Other Other values provided by the value list.
- */
- template<auto Value, auto... Other>
- struct value_list_element<0u, value_list<Value, Other...>> {
- /*! @brief Searched type. */
- using type = decltype(Value);
- /*! @brief Searched value. */
- static constexpr auto value = Value;
- };
- /**
- * @brief Helper type.
- * @tparam Index Index of the type to return.
- * @tparam List Value list to search into.
- */
- template<std::size_t Index, typename List>
- using value_list_element_t = typename value_list_element<Index, List>::type;
- /**
- * @brief Helper type.
- * @tparam Index Index of the value to return.
- * @tparam List Value list to search into.
- */
- template<std::size_t Index, typename List>
- inline constexpr auto value_list_element_v = value_list_element<Index, List>::value;
- /*! @brief Primary template isn't defined on purpose. */
- template<auto, typename>
- struct value_list_index;
- /**
- * @brief Provides compile-time type access to the values of a value list.
- * @tparam Value Value to look for and for which to return the index.
- * @tparam First First value provided by the value list.
- * @tparam Other Other values provided by the value list.
- */
- template<auto Value, auto First, auto... Other>
- struct value_list_index<Value, value_list<First, Other...>> {
- /*! @brief Unsigned integer type. */
- using value_type = std::size_t;
- /*! @brief Compile-time position of the given value in the sublist. */
- static constexpr value_type value = 1u + value_list_index<Value, value_list<Other...>>::value;
- };
- /**
- * @brief Provides compile-time type access to the values of a value list.
- * @tparam Value Value to look for and for which to return the index.
- * @tparam Other Other values provided by the value list.
- */
- template<auto Value, auto... Other>
- struct value_list_index<Value, value_list<Value, Other...>> {
- static_assert(value_list_index<Value, value_list<Other...>>::value == sizeof...(Other), "Non-unique type");
- /*! @brief Unsigned integer type. */
- using value_type = std::size_t;
- /*! @brief Compile-time position of the given value in the sublist. */
- static constexpr value_type value = 0u;
- };
- /**
- * @brief Provides compile-time type access to the values of a value list.
- * @tparam Value Value to look for and for which to return the index.
- */
- template<auto Value>
- struct value_list_index<Value, value_list<>> {
- /*! @brief Unsigned integer type. */
- using value_type = std::size_t;
- /*! @brief Compile-time position of the given type in the sublist. */
- static constexpr value_type value = 0u;
- };
- /**
- * @brief Helper variable template.
- * @tparam List Value list.
- * @tparam Value Value to look for and for which to return the index.
- */
- template<auto Value, typename List>
- inline constexpr std::size_t value_list_index_v = value_list_index<Value, List>::value;
- /**
- * @brief Concatenates multiple value lists.
- * @tparam Value Values provided by the first value list.
- * @tparam Other Values provided by the second value list.
- * @return A value list composed by the values of both the value lists.
- */
- template<auto... Value, auto... Other>
- constexpr value_list<Value..., Other...> operator+(value_list<Value...>, value_list<Other...>) {
- return {};
- }
- /*! @brief Primary template isn't defined on purpose. */
- template<typename...>
- struct value_list_cat;
- /*! @brief Concatenates multiple value lists. */
- template<>
- struct value_list_cat<> {
- /*! @brief A value list composed by the values of all the value lists. */
- using type = value_list<>;
- };
- /**
- * @brief Concatenates multiple value lists.
- * @tparam Value Values provided by the first value list.
- * @tparam Other Values provided by the second value list.
- * @tparam List Other value lists, if any.
- */
- template<auto... Value, auto... Other, typename... List>
- struct value_list_cat<value_list<Value...>, value_list<Other...>, List...> {
- /*! @brief A value list composed by the values of all the value lists. */
- using type = typename value_list_cat<value_list<Value..., Other...>, List...>::type;
- };
- /**
- * @brief Concatenates multiple value lists.
- * @tparam Value Values provided by the value list.
- */
- template<auto... Value>
- struct value_list_cat<value_list<Value...>> {
- /*! @brief A value list composed by the values of all the value lists. */
- using type = value_list<Value...>;
- };
- /**
- * @brief Helper type.
- * @tparam List Value lists to concatenate.
- */
- template<typename... List>
- using value_list_cat_t = typename value_list_cat<List...>::type;
- /*! @brief Primary template isn't defined on purpose. */
- template<typename>
- struct value_list_unique;
- /**
- * @brief Removes duplicates values from a value list.
- * @tparam Value One of the values provided by the given value list.
- * @tparam Other The other values provided by the given value list.
- */
- template<auto Value, auto... Other>
- struct value_list_unique<value_list<Value, Other...>> {
- /*! @brief A value list without duplicate types. */
- using type = std::conditional_t<
- ((Value == Other) || ...),
- typename value_list_unique<value_list<Other...>>::type,
- value_list_cat_t<value_list<Value>, typename value_list_unique<value_list<Other...>>::type>>;
- };
- /*! @brief Removes duplicates values from a value list. */
- template<>
- struct value_list_unique<value_list<>> {
- /*! @brief A value list without duplicate types. */
- using type = value_list<>;
- };
- /**
- * @brief Helper type.
- * @tparam Type A value list.
- */
- template<typename Type>
- using value_list_unique_t = typename value_list_unique<Type>::type;
- /**
- * @brief Provides the member constant `value` to true if a value list contains
- * a given value, false otherwise.
- * @tparam List Value list.
- * @tparam Value Value to look for.
- */
- template<typename List, auto Value>
- struct value_list_contains;
- /**
- * @copybrief value_list_contains
- * @tparam Value Values provided by the value list.
- * @tparam Other Value to look for.
- */
- template<auto... Value, auto Other>
- struct value_list_contains<value_list<Value...>, Other>
- : std::bool_constant<((Value == Other) || ...)> {};
- /**
- * @brief Helper variable template.
- * @tparam List Value list.
- * @tparam Value Value to look for.
- */
- template<typename List, auto Value>
- inline constexpr bool value_list_contains_v = value_list_contains<List, Value>::value;
- /*! @brief Primary template isn't defined on purpose. */
- template<typename...>
- struct value_list_diff;
- /**
- * @brief Computes the difference between two value lists.
- * @tparam Value Values provided by the first value list.
- * @tparam Other Values provided by the second value list.
- */
- template<auto... Value, auto... Other>
- struct value_list_diff<value_list<Value...>, value_list<Other...>> {
- /*! @brief A value list that is the difference between the two value lists. */
- using type = value_list_cat_t<std::conditional_t<value_list_contains_v<value_list<Other...>, Value>, value_list<>, value_list<Value>>...>;
- };
- /**
- * @brief Helper type.
- * @tparam List Value lists between which to compute the difference.
- */
- template<typename... List>
- using value_list_diff_t = typename value_list_diff<List...>::type;
- /*! @brief Same as std::is_invocable, but with tuples. */
- template<typename, typename>
- struct is_applicable: std::false_type {};
- /**
- * @copybrief is_applicable
- * @tparam Func A valid function type.
- * @tparam Tuple Tuple-like type.
- * @tparam Args The list of arguments to use to probe the function type.
- */
- template<typename Func, template<typename...> class Tuple, typename... Args>
- struct is_applicable<Func, Tuple<Args...>>: std::is_invocable<Func, Args...> {};
- /**
- * @copybrief is_applicable
- * @tparam Func A valid function type.
- * @tparam Tuple Tuple-like type.
- * @tparam Args The list of arguments to use to probe the function type.
- */
- template<typename Func, template<typename...> class Tuple, typename... Args>
- struct is_applicable<Func, const Tuple<Args...>>: std::is_invocable<Func, Args...> {};
- /**
- * @brief Helper variable template.
- * @tparam Func A valid function type.
- * @tparam Args The list of arguments to use to probe the function type.
- */
- template<typename Func, typename Args>
- inline constexpr bool is_applicable_v = is_applicable<Func, Args>::value;
- /*! @brief Same as std::is_invocable_r, but with tuples for arguments. */
- template<typename, typename, typename>
- struct is_applicable_r: std::false_type {};
- /**
- * @copybrief is_applicable_r
- * @tparam Ret The type to which the return type of the function should be
- * convertible.
- * @tparam Func A valid function type.
- * @tparam Args The list of arguments to use to probe the function type.
- */
- template<typename Ret, typename Func, typename... Args>
- struct is_applicable_r<Ret, Func, std::tuple<Args...>>: std::is_invocable_r<Ret, Func, Args...> {};
- /**
- * @brief Helper variable template.
- * @tparam Ret The type to which the return type of the function should be
- * convertible.
- * @tparam Func A valid function type.
- * @tparam Args The list of arguments to use to probe the function type.
- */
- template<typename Ret, typename Func, typename Args>
- inline constexpr bool is_applicable_r_v = is_applicable_r<Ret, Func, Args>::value;
- /**
- * @brief Provides the member constant `value` to true if a given type is
- * complete, false otherwise.
- * @tparam Type The type to test.
- */
- template<typename Type, typename = void>
- struct is_complete: std::false_type {};
- /*! @copydoc is_complete */
- template<typename Type>
- struct is_complete<Type, std::void_t<decltype(sizeof(Type))>>: std::true_type {};
- /**
- * @brief Helper variable template.
- * @tparam Type The type to test.
- */
- template<typename Type>
- inline constexpr bool is_complete_v = is_complete<Type>::value;
- /**
- * @brief Provides the member constant `value` to true if a given type is an
- * iterator, false otherwise.
- * @tparam Type The type to test.
- */
- template<typename Type, typename = void>
- struct is_iterator: std::false_type {};
- /*! @cond TURN_OFF_DOXYGEN */
- namespace internal {
- template<typename, typename = void>
- struct has_iterator_category: std::false_type {};
- template<typename Type>
- struct has_iterator_category<Type, std::void_t<typename std::iterator_traits<Type>::iterator_category>>: std::true_type {};
- } // namespace internal
- /*! @endcond */
- /*! @copydoc is_iterator */
- template<typename Type>
- struct is_iterator<Type, std::enable_if_t<!std::is_void_v<std::remove_const_t<std::remove_pointer_t<Type>>>>>
- : internal::has_iterator_category<Type> {};
- /**
- * @brief Helper variable template.
- * @tparam Type The type to test.
- */
- template<typename Type>
- inline constexpr bool is_iterator_v = is_iterator<Type>::value;
- /**
- * @brief Provides the member constant `value` to true if a given type is both
- * an empty and non-final class, false otherwise.
- * @tparam Type The type to test
- */
- template<typename Type>
- struct is_ebco_eligible
- : std::bool_constant<std::is_empty_v<Type> && !std::is_final_v<Type>> {};
- /**
- * @brief Helper variable template.
- * @tparam Type The type to test.
- */
- template<typename Type>
- inline constexpr bool is_ebco_eligible_v = is_ebco_eligible<Type>::value;
- /**
- * @brief Provides the member constant `value` to true if `Type::is_transparent`
- * is valid and denotes a type, false otherwise.
- * @tparam Type The type to test.
- */
- template<typename Type, typename = void>
- struct is_transparent: std::false_type {};
- /*! @copydoc is_transparent */
- template<typename Type>
- struct is_transparent<Type, std::void_t<typename Type::is_transparent>>: std::true_type {};
- /**
- * @brief Helper variable template.
- * @tparam Type The type to test.
- */
- template<typename Type>
- inline constexpr bool is_transparent_v = is_transparent<Type>::value;
- /*! @cond TURN_OFF_DOXYGEN */
- namespace internal {
- template<typename, typename = void>
- struct has_tuple_size_value: std::false_type {};
- template<typename Type>
- struct has_tuple_size_value<Type, std::void_t<decltype(std::tuple_size<const Type>::value)>>: std::true_type {};
- template<typename, typename = void>
- struct has_value_type: std::false_type {};
- template<typename Type>
- struct has_value_type<Type, std::void_t<typename Type::value_type>>: std::true_type {};
- template<typename>
- [[nodiscard]] constexpr bool dispatch_is_equality_comparable();
- template<typename Type, std::size_t... Index>
- [[nodiscard]] constexpr bool unpack_maybe_equality_comparable(std::index_sequence<Index...>) {
- return (dispatch_is_equality_comparable<std::tuple_element_t<Index, Type>>() && ...);
- }
- template<typename>
- [[nodiscard]] constexpr bool maybe_equality_comparable(char) {
- return false;
- }
- template<typename Type>
- [[nodiscard]] constexpr auto maybe_equality_comparable(int) -> decltype(std::declval<Type>() == std::declval<Type>()) {
- return true;
- }
- template<typename Type>
- [[nodiscard]] constexpr bool dispatch_is_equality_comparable() {
- // NOLINTBEGIN(modernize-use-transparent-functors)
- if constexpr(std::is_array_v<Type>) {
- return false;
- } else if constexpr(is_complete_v<std::tuple_size<std::remove_const_t<Type>>>) {
- if constexpr(has_tuple_size_value<Type>::value) {
- return maybe_equality_comparable<Type>(0) && unpack_maybe_equality_comparable<Type>(std::make_index_sequence<std::tuple_size<Type>::value>{});
- } else {
- return maybe_equality_comparable<Type>(0);
- }
- } else if constexpr(has_value_type<Type>::value) {
- if constexpr(is_iterator_v<Type> || std::is_same_v<typename Type::value_type, Type> || dispatch_is_equality_comparable<typename Type::value_type>()) {
- return maybe_equality_comparable<Type>(0);
- } else {
- return false;
- }
- } else {
- return maybe_equality_comparable<Type>(0);
- }
- // NOLINTEND(modernize-use-transparent-functors)
- }
- } // namespace internal
- /*! @endcond */
- /**
- * @brief Provides the member constant `value` to true if a given type is
- * equality comparable, false otherwise.
- * @tparam Type The type to test.
- */
- template<typename Type>
- struct is_equality_comparable: std::bool_constant<internal::dispatch_is_equality_comparable<Type>()> {};
- /*! @copydoc is_equality_comparable */
- template<typename Type>
- struct is_equality_comparable<const Type>: is_equality_comparable<Type> {};
- /**
- * @brief Helper variable template.
- * @tparam Type The type to test.
- */
- template<typename Type>
- inline constexpr bool is_equality_comparable_v = is_equality_comparable<Type>::value;
- /**
- * @brief Transcribes the constness of a type to another type.
- * @tparam To The type to which to transcribe the constness.
- * @tparam From The type from which to transcribe the constness.
- */
- template<typename To, typename From>
- struct constness_as {
- /*! @brief The type resulting from the transcription of the constness. */
- using type = std::remove_const_t<To>;
- };
- /*! @copydoc constness_as */
- template<typename To, typename From>
- struct constness_as<To, const From> {
- /*! @brief The type resulting from the transcription of the constness. */
- using type = const To;
- };
- /**
- * @brief Alias template to facilitate the transcription of the constness.
- * @tparam To The type to which to transcribe the constness.
- * @tparam From The type from which to transcribe the constness.
- */
- template<typename To, typename From>
- using constness_as_t = typename constness_as<To, From>::type;
- /**
- * @brief Extracts the class of a non-static member object or function.
- * @tparam Member A pointer to a non-static member object or function.
- */
- template<typename Member>
- class member_class {
- static_assert(std::is_member_pointer_v<Member>, "Invalid pointer type to non-static member object or function");
- template<typename Class, typename Ret, typename... Args>
- static Class *clazz(Ret (Class::*)(Args...));
- template<typename Class, typename Ret, typename... Args>
- static Class *clazz(Ret (Class::*)(Args...) const);
- template<typename Class, typename Type>
- static Class *clazz(Type Class::*);
- public:
- /*! @brief The class of the given non-static member object or function. */
- using type = std::remove_pointer_t<decltype(clazz(std::declval<Member>()))>;
- };
- /**
- * @brief Helper type.
- * @tparam Member A pointer to a non-static member object or function.
- */
- template<typename Member>
- using member_class_t = typename member_class<Member>::type;
- /**
- * @brief Extracts the n-th argument of a _callable_ type.
- * @tparam Index The index of the argument to extract.
- * @tparam Candidate A valid _callable_ type.
- */
- template<std::size_t Index, typename Candidate>
- class nth_argument {
- template<typename Ret, typename... Args>
- static constexpr type_list<Args...> pick_up(Ret (*)(Args...));
- template<typename Ret, typename Class, typename... Args>
- static constexpr type_list<Args...> pick_up(Ret (Class ::*)(Args...));
- template<typename Ret, typename Class, typename... Args>
- static constexpr type_list<Args...> pick_up(Ret (Class ::*)(Args...) const);
- template<typename Type, typename Class>
- static constexpr type_list<Type> pick_up(Type Class ::*);
- template<typename Type>
- static constexpr decltype(pick_up(&Type::operator())) pick_up(Type &&);
- public:
- /*! @brief N-th argument of the _callable_ type. */
- using type = type_list_element_t<Index, decltype(pick_up(std::declval<Candidate>()))>;
- };
- /**
- * @brief Helper type.
- * @tparam Index The index of the argument to extract.
- * @tparam Candidate A valid function, member function or data member type.
- */
- template<std::size_t Index, typename Candidate>
- using nth_argument_t = typename nth_argument<Index, Candidate>::type;
- } // namespace entt
- template<typename... Type>
- struct std::tuple_size<entt::type_list<Type...>>: std::integral_constant<std::size_t, entt::type_list<Type...>::size> {};
- template<std::size_t Index, typename... Type>
- struct std::tuple_element<Index, entt::type_list<Type...>>: entt::type_list_element<Index, entt::type_list<Type...>> {};
- template<auto... Value>
- struct std::tuple_size<entt::value_list<Value...>>: std::integral_constant<std::size_t, entt::value_list<Value...>::size> {};
- template<std::size_t Index, auto... Value>
- struct std::tuple_element<Index, entt::value_list<Value...>>: entt::value_list_element<Index, entt::value_list<Value...>> {};
- #endif
- namespace entt {
- /*! @cond TURN_OFF_DOXYGEN */
- namespace internal {
- template<typename Type, std::size_t, typename = void>
- struct compressed_pair_element {
- using reference = Type &;
- using const_reference = const Type &;
- template<typename Dummy = Type, typename = std::enable_if_t<std::is_default_constructible_v<Dummy>>>
- // NOLINTNEXTLINE(modernize-use-equals-default)
- constexpr compressed_pair_element() noexcept(std::is_nothrow_default_constructible_v<Type>) {}
- template<typename Arg, typename = std::enable_if_t<!std::is_same_v<std::remove_const_t<std::remove_reference_t<Arg>>, compressed_pair_element>>>
- constexpr compressed_pair_element(Arg &&arg) noexcept(std::is_nothrow_constructible_v<Type, Arg>)
- : value{std::forward<Arg>(arg)} {}
- template<typename... Args, std::size_t... Index>
- constexpr compressed_pair_element(std::tuple<Args...> args, std::index_sequence<Index...>) noexcept(std::is_nothrow_constructible_v<Type, Args...>)
- : value{std::forward<Args>(std::get<Index>(args))...} {}
- [[nodiscard]] constexpr reference get() noexcept {
- return value;
- }
- [[nodiscard]] constexpr const_reference get() const noexcept {
- return value;
- }
- private:
- Type value{};
- };
- template<typename Type, std::size_t Tag>
- struct compressed_pair_element<Type, Tag, std::enable_if_t<is_ebco_eligible_v<Type>>>: Type {
- using reference = Type &;
- using const_reference = const Type &;
- using base_type = Type;
- template<typename Dummy = Type, typename = std::enable_if_t<std::is_default_constructible_v<Dummy>>>
- constexpr compressed_pair_element() noexcept(std::is_nothrow_default_constructible_v<base_type>)
- : base_type{} {}
- template<typename Arg, typename = std::enable_if_t<!std::is_same_v<std::remove_const_t<std::remove_reference_t<Arg>>, compressed_pair_element>>>
- constexpr compressed_pair_element(Arg &&arg) noexcept(std::is_nothrow_constructible_v<base_type, Arg>)
- : base_type{std::forward<Arg>(arg)} {}
- template<typename... Args, std::size_t... Index>
- constexpr compressed_pair_element(std::tuple<Args...> args, std::index_sequence<Index...>) noexcept(std::is_nothrow_constructible_v<base_type, Args...>)
- : base_type{std::forward<Args>(std::get<Index>(args))...} {}
- [[nodiscard]] constexpr reference get() noexcept {
- return *this;
- }
- [[nodiscard]] constexpr const_reference get() const noexcept {
- return *this;
- }
- };
- } // namespace internal
- /*! @endcond */
- /**
- * @brief A compressed pair.
- *
- * A pair that exploits the _Empty Base Class Optimization_ (or _EBCO_) to
- * reduce its final size to a minimum.
- *
- * @tparam First The type of the first element that the pair stores.
- * @tparam Second The type of the second element that the pair stores.
- */
- template<typename First, typename Second>
- class compressed_pair final
- : internal::compressed_pair_element<First, 0u>,
- internal::compressed_pair_element<Second, 1u> {
- using first_base = internal::compressed_pair_element<First, 0u>;
- using second_base = internal::compressed_pair_element<Second, 1u>;
- public:
- /*! @brief The type of the first element that the pair stores. */
- using first_type = First;
- /*! @brief The type of the second element that the pair stores. */
- using second_type = Second;
- /**
- * @brief Default constructor, conditionally enabled.
- *
- * This constructor is only available when the types that the pair stores
- * are both at least default constructible.
- *
- * @tparam Dummy Dummy template parameter used for internal purposes.
- */
- template<bool Dummy = true, typename = std::enable_if_t<Dummy && std::is_default_constructible_v<first_type> && std::is_default_constructible_v<second_type>>>
- constexpr compressed_pair() noexcept(std::is_nothrow_default_constructible_v<first_base> && std::is_nothrow_default_constructible_v<second_base>)
- : first_base{},
- second_base{} {}
- /**
- * @brief Copy constructor.
- * @param other The instance to copy from.
- */
- constexpr compressed_pair(const compressed_pair &other) = default;
- /**
- * @brief Move constructor.
- * @param other The instance to move from.
- */
- constexpr compressed_pair(compressed_pair &&other) noexcept = default;
- /**
- * @brief Constructs a pair from its values.
- * @tparam Arg Type of value to use to initialize the first element.
- * @tparam Other Type of value to use to initialize the second element.
- * @param arg Value to use to initialize the first element.
- * @param other Value to use to initialize the second element.
- */
- template<typename Arg, typename Other>
- constexpr compressed_pair(Arg &&arg, Other &&other) noexcept(std::is_nothrow_constructible_v<first_base, Arg> && std::is_nothrow_constructible_v<second_base, Other>)
- : first_base{std::forward<Arg>(arg)},
- second_base{std::forward<Other>(other)} {}
- /**
- * @brief Constructs a pair by forwarding the arguments to its parts.
- * @tparam Args Types of arguments to use to initialize the first element.
- * @tparam Other Types of arguments to use to initialize the second element.
- * @param args Arguments to use to initialize the first element.
- * @param other Arguments to use to initialize the second element.
- */
- template<typename... Args, typename... Other>
- constexpr compressed_pair(std::piecewise_construct_t, std::tuple<Args...> args, std::tuple<Other...> other) noexcept(std::is_nothrow_constructible_v<first_base, Args...> && std::is_nothrow_constructible_v<second_base, Other...>)
- : first_base{std::move(args), std::index_sequence_for<Args...>{}},
- second_base{std::move(other), std::index_sequence_for<Other...>{}} {}
- /*! @brief Default destructor. */
- ~compressed_pair() = default;
- /**
- * @brief Copy assignment operator.
- * @param other The instance to copy from.
- * @return This compressed pair object.
- */
- constexpr compressed_pair &operator=(const compressed_pair &other) = default;
- /**
- * @brief Move assignment operator.
- * @param other The instance to move from.
- * @return This compressed pair object.
- */
- constexpr compressed_pair &operator=(compressed_pair &&other) noexcept = default;
- /**
- * @brief Returns the first element that a pair stores.
- * @return The first element that a pair stores.
- */
- [[nodiscard]] constexpr first_type &first() noexcept {
- return static_cast<first_base &>(*this).get();
- }
- /*! @copydoc first */
- [[nodiscard]] constexpr const first_type &first() const noexcept {
- return static_cast<const first_base &>(*this).get();
- }
- /**
- * @brief Returns the second element that a pair stores.
- * @return The second element that a pair stores.
- */
- [[nodiscard]] constexpr second_type &second() noexcept {
- return static_cast<second_base &>(*this).get();
- }
- /*! @copydoc second */
- [[nodiscard]] constexpr const second_type &second() const noexcept {
- return static_cast<const second_base &>(*this).get();
- }
- /**
- * @brief Swaps two compressed pair objects.
- * @param other The compressed pair to swap with.
- */
- constexpr void swap(compressed_pair &other) noexcept {
- using std::swap;
- swap(first(), other.first());
- swap(second(), other.second());
- }
- /**
- * @brief Extracts an element from the compressed pair.
- * @tparam Index An integer value that is either 0 or 1.
- * @return Returns a reference to the first element if `Index` is 0 and a
- * reference to the second element if `Index` is 1.
- */
- template<std::size_t Index>
- [[nodiscard]] constexpr decltype(auto) get() noexcept {
- if constexpr(Index == 0u) {
- return first();
- } else {
- static_assert(Index == 1u, "Index out of bounds");
- return second();
- }
- }
- /*! @copydoc get */
- template<std::size_t Index>
- [[nodiscard]] constexpr decltype(auto) get() const noexcept {
- if constexpr(Index == 0u) {
- return first();
- } else {
- static_assert(Index == 1u, "Index out of bounds");
- return second();
- }
- }
- };
- /**
- * @brief Deduction guide.
- * @tparam Type Type of value to use to initialize the first element.
- * @tparam Other Type of value to use to initialize the second element.
- */
- template<typename Type, typename Other>
- compressed_pair(Type &&, Other &&) -> compressed_pair<std::decay_t<Type>, std::decay_t<Other>>;
- /**
- * @brief Swaps two compressed pair objects.
- * @tparam First The type of the first element that the pairs store.
- * @tparam Second The type of the second element that the pairs store.
- * @param lhs A valid compressed pair object.
- * @param rhs A valid compressed pair object.
- */
- template<typename First, typename Second>
- constexpr void swap(compressed_pair<First, Second> &lhs, compressed_pair<First, Second> &rhs) noexcept {
- lhs.swap(rhs);
- }
- } // namespace entt
- namespace std {
- /**
- * @brief `std::tuple_size` specialization for `compressed_pair`s.
- * @tparam First The type of the first element that the pair stores.
- * @tparam Second The type of the second element that the pair stores.
- */
- template<typename First, typename Second>
- struct tuple_size<entt::compressed_pair<First, Second>>: integral_constant<size_t, 2u> {};
- /**
- * @brief `std::tuple_element` specialization for `compressed_pair`s.
- * @tparam Index The index of the type to return.
- * @tparam First The type of the first element that the pair stores.
- * @tparam Second The type of the second element that the pair stores.
- */
- template<size_t Index, typename First, typename Second>
- struct tuple_element<Index, entt::compressed_pair<First, Second>>: conditional<Index == 0u, First, Second> {
- static_assert(Index < 2u, "Index out of bounds");
- };
- } // namespace std
- #endif
- // #include "../core/iterator.hpp"
- #ifndef ENTT_CORE_ITERATOR_HPP
- #define ENTT_CORE_ITERATOR_HPP
- #include <iterator>
- #include <memory>
- #include <type_traits>
- #include <utility>
- namespace entt {
- /**
- * @brief Helper type to use as pointer with input iterators.
- * @tparam Type of wrapped value.
- */
- template<typename Type>
- struct input_iterator_pointer final {
- /*! @brief Value type. */
- using value_type = Type;
- /*! @brief Pointer type. */
- using pointer = Type *;
- /*! @brief Reference type. */
- using reference = Type &;
- /**
- * @brief Constructs a proxy object by move.
- * @param val Value to use to initialize the proxy object.
- */
- constexpr input_iterator_pointer(value_type &&val) noexcept(std::is_nothrow_move_constructible_v<value_type>)
- : value{std::move(val)} {}
- /**
- * @brief Access operator for accessing wrapped values.
- * @return A pointer to the wrapped value.
- */
- [[nodiscard]] constexpr pointer operator->() noexcept {
- return std::addressof(value);
- }
- /**
- * @brief Dereference operator for accessing wrapped values.
- * @return A reference to the wrapped value.
- */
- [[nodiscard]] constexpr reference operator*() noexcept {
- return value;
- }
- private:
- Type value;
- };
- /**
- * @brief Plain iota iterator (waiting for C++20).
- * @tparam Type Value type.
- */
- template<typename Type>
- class iota_iterator final {
- static_assert(std::is_integral_v<Type>, "Not an integral type");
- public:
- /*! @brief Value type, likely an integral one. */
- using value_type = Type;
- /*! @brief Invalid pointer type. */
- using pointer = void;
- /*! @brief Non-reference type, same as value type. */
- using reference = value_type;
- /*! @brief Difference type. */
- using difference_type = std::ptrdiff_t;
- /*! @brief Iterator category. */
- using iterator_category = std::input_iterator_tag;
- /*! @brief Default constructor. */
- constexpr iota_iterator() noexcept
- : current{} {}
- /**
- * @brief Constructs an iota iterator from a given value.
- * @param init The initial value assigned to the iota iterator.
- */
- constexpr iota_iterator(const value_type init) noexcept
- : current{init} {}
- /**
- * @brief Pre-increment operator.
- * @return This iota iterator.
- */
- constexpr iota_iterator &operator++() noexcept {
- return ++current, *this;
- }
- /**
- * @brief Post-increment operator.
- * @return This iota iterator.
- */
- constexpr iota_iterator operator++(int) noexcept {
- const iota_iterator orig = *this;
- return ++(*this), orig;
- }
- /**
- * @brief Dereference operator.
- * @return The underlying value.
- */
- [[nodiscard]] constexpr reference operator*() const noexcept {
- return current;
- }
- private:
- value_type current;
- };
- /**
- * @brief Comparison operator.
- * @tparam Type Value type of the iota iterator.
- * @param lhs A properly initialized iota iterator.
- * @param rhs A properly initialized iota iterator.
- * @return True if the two iterators are identical, false otherwise.
- */
- template<typename Type>
- [[nodiscard]] constexpr bool operator==(const iota_iterator<Type> &lhs, const iota_iterator<Type> &rhs) noexcept {
- return *lhs == *rhs;
- }
- /**
- * @brief Comparison operator.
- * @tparam Type Value type of the iota iterator.
- * @param lhs A properly initialized iota iterator.
- * @param rhs A properly initialized iota iterator.
- * @return True if the two iterators differ, false otherwise.
- */
- template<typename Type>
- [[nodiscard]] constexpr bool operator!=(const iota_iterator<Type> &lhs, const iota_iterator<Type> &rhs) noexcept {
- return !(lhs == rhs);
- }
- /**
- * @brief Utility class to create an iterable object from a pair of iterators.
- * @tparam It Type of iterator.
- * @tparam Sentinel Type of sentinel.
- */
- template<typename It, typename Sentinel = It>
- struct iterable_adaptor final {
- /*! @brief Value type. */
- using value_type = typename std::iterator_traits<It>::value_type;
- /*! @brief Iterator type. */
- using iterator = It;
- /*! @brief Sentinel type. */
- using sentinel = Sentinel;
- /*! @brief Default constructor. */
- constexpr iterable_adaptor() noexcept(std::is_nothrow_default_constructible_v<iterator> && std::is_nothrow_default_constructible_v<sentinel>)
- : first{},
- last{} {}
- /**
- * @brief Creates an iterable object from a pair of iterators.
- * @param from Begin iterator.
- * @param to End iterator.
- */
- constexpr iterable_adaptor(iterator from, sentinel to) noexcept(std::is_nothrow_move_constructible_v<iterator> && std::is_nothrow_move_constructible_v<sentinel>)
- : first{std::move(from)},
- last{std::move(to)} {}
- /**
- * @brief Returns an iterator to the beginning.
- * @return An iterator to the first element of the range.
- */
- [[nodiscard]] constexpr iterator begin() const noexcept {
- return first;
- }
- /**
- * @brief Returns an iterator to the end.
- * @return An iterator to the element following the last element of the
- * range.
- */
- [[nodiscard]] constexpr sentinel end() const noexcept {
- return last;
- }
- /*! @copydoc begin */
- [[nodiscard]] constexpr iterator cbegin() const noexcept {
- return begin();
- }
- /*! @copydoc end */
- [[nodiscard]] constexpr sentinel cend() const noexcept {
- return end();
- }
- private:
- It first;
- Sentinel last;
- };
- } // namespace entt
- #endif
- // #include "../core/memory.hpp"
- #ifndef ENTT_CORE_MEMORY_HPP
- #define ENTT_CORE_MEMORY_HPP
- #include <cstddef>
- #include <memory>
- #include <tuple>
- #include <type_traits>
- #include <utility>
- // #include "../config/config.h"
- namespace entt {
- /**
- * @brief Unwraps fancy pointers, does nothing otherwise (waiting for C++20).
- * @tparam Type Pointer type.
- * @param ptr Fancy or raw pointer.
- * @return A raw pointer that represents the address of the original pointer.
- */
- template<typename Type>
- [[nodiscard]] constexpr auto to_address(Type &&ptr) noexcept {
- if constexpr(std::is_pointer_v<std::decay_t<Type>>) {
- return ptr;
- } else {
- return to_address(std::forward<Type>(ptr).operator->());
- }
- }
- /**
- * @brief Utility function to design allocation-aware containers.
- * @tparam Allocator Type of allocator.
- * @param lhs A valid allocator.
- * @param rhs Another valid allocator.
- */
- template<typename Allocator>
- constexpr void propagate_on_container_copy_assignment([[maybe_unused]] Allocator &lhs, [[maybe_unused]] Allocator &rhs) noexcept {
- if constexpr(std::allocator_traits<Allocator>::propagate_on_container_copy_assignment::value) {
- lhs = rhs;
- }
- }
- /**
- * @brief Utility function to design allocation-aware containers.
- * @tparam Allocator Type of allocator.
- * @param lhs A valid allocator.
- * @param rhs Another valid allocator.
- */
- template<typename Allocator>
- constexpr void propagate_on_container_move_assignment([[maybe_unused]] Allocator &lhs, [[maybe_unused]] Allocator &rhs) noexcept {
- if constexpr(std::allocator_traits<Allocator>::propagate_on_container_move_assignment::value) {
- lhs = std::move(rhs);
- }
- }
- /**
- * @brief Utility function to design allocation-aware containers.
- * @tparam Allocator Type of allocator.
- * @param lhs A valid allocator.
- * @param rhs Another valid allocator.
- */
- template<typename Allocator>
- constexpr void propagate_on_container_swap([[maybe_unused]] Allocator &lhs, [[maybe_unused]] Allocator &rhs) noexcept {
- if constexpr(std::allocator_traits<Allocator>::propagate_on_container_swap::value) {
- using std::swap;
- swap(lhs, rhs);
- } else {
- ENTT_ASSERT_CONSTEXPR(lhs == rhs, "Cannot swap the containers");
- }
- }
- /**
- * @brief Deleter for allocator-aware unique pointers (waiting for C++20).
- * @tparam Allocator Type of allocator used to manage memory and elements.
- */
- template<typename Allocator>
- struct allocation_deleter: private Allocator {
- /*! @brief Allocator type. */
- using allocator_type = Allocator;
- /*! @brief Pointer type. */
- using pointer = typename std::allocator_traits<Allocator>::pointer;
- /**
- * @brief Inherited constructors.
- * @param alloc The allocator to use.
- */
- constexpr allocation_deleter(const allocator_type &alloc) noexcept(std::is_nothrow_copy_constructible_v<allocator_type>)
- : Allocator{alloc} {}
- /**
- * @brief Destroys the pointed object and deallocates its memory.
- * @param ptr A valid pointer to an object of the given type.
- */
- constexpr void operator()(pointer ptr) noexcept(std::is_nothrow_destructible_v<typename allocator_type::value_type>) {
- using alloc_traits = std::allocator_traits<Allocator>;
- alloc_traits::destroy(*this, to_address(ptr));
- alloc_traits::deallocate(*this, ptr, 1u);
- }
- };
- /**
- * @brief Allows `std::unique_ptr` to use allocators (waiting for C++20).
- * @tparam Type Type of object to allocate for and to construct.
- * @tparam Allocator Type of allocator used to manage memory and elements.
- * @tparam Args Types of arguments to use to construct the object.
- * @param allocator The allocator to use.
- * @param args Parameters to use to construct the object.
- * @return A properly initialized unique pointer with a custom deleter.
- */
- template<typename Type, typename Allocator, typename... Args>
- ENTT_CONSTEXPR auto allocate_unique(Allocator &allocator, Args &&...args) {
- static_assert(!std::is_array_v<Type>, "Array types are not supported");
- using alloc_traits = typename std::allocator_traits<Allocator>::template rebind_traits<Type>;
- using allocator_type = typename alloc_traits::allocator_type;
- allocator_type alloc{allocator};
- auto ptr = alloc_traits::allocate(alloc, 1u);
- ENTT_TRY {
- alloc_traits::construct(alloc, to_address(ptr), std::forward<Args>(args)...);
- }
- ENTT_CATCH {
- alloc_traits::deallocate(alloc, ptr, 1u);
- ENTT_THROW;
- }
- return std::unique_ptr<Type, allocation_deleter<allocator_type>>{ptr, alloc};
- }
- /*! @cond TURN_OFF_DOXYGEN */
- namespace internal {
- template<typename Type>
- struct uses_allocator_construction {
- template<typename Allocator, typename... Params>
- static constexpr auto args([[maybe_unused]] const Allocator &allocator, Params &&...params) noexcept {
- if constexpr(!std::uses_allocator_v<Type, Allocator> && std::is_constructible_v<Type, Params...>) {
- return std::forward_as_tuple(std::forward<Params>(params)...);
- } else {
- static_assert(std::uses_allocator_v<Type, Allocator>, "Ill-formed request");
- if constexpr(std::is_constructible_v<Type, std::allocator_arg_t, const Allocator &, Params...>) {
- return std::tuple<std::allocator_arg_t, const Allocator &, Params &&...>{std::allocator_arg, allocator, std::forward<Params>(params)...};
- } else {
- static_assert(std::is_constructible_v<Type, Params..., const Allocator &>, "Ill-formed request");
- return std::forward_as_tuple(std::forward<Params>(params)..., allocator);
- }
- }
- }
- };
- template<typename Type, typename Other>
- struct uses_allocator_construction<std::pair<Type, Other>> {
- using type = std::pair<Type, Other>;
- template<typename Allocator, typename First, typename Second>
- static constexpr auto args(const Allocator &allocator, std::piecewise_construct_t, First &&first, Second &&second) noexcept {
- return std::make_tuple(
- std::piecewise_construct,
- std::apply([&allocator](auto &&...curr) { return uses_allocator_construction<Type>::args(allocator, std::forward<decltype(curr)>(curr)...); }, std::forward<First>(first)),
- std::apply([&allocator](auto &&...curr) { return uses_allocator_construction<Other>::args(allocator, std::forward<decltype(curr)>(curr)...); }, std::forward<Second>(second)));
- }
- template<typename Allocator>
- static constexpr auto args(const Allocator &allocator) noexcept {
- return uses_allocator_construction<type>::args(allocator, std::piecewise_construct, std::tuple<>{}, std::tuple<>{});
- }
- template<typename Allocator, typename First, typename Second>
- static constexpr auto args(const Allocator &allocator, First &&first, Second &&second) noexcept {
- return uses_allocator_construction<type>::args(allocator, std::piecewise_construct, std::forward_as_tuple(std::forward<First>(first)), std::forward_as_tuple(std::forward<Second>(second)));
- }
- template<typename Allocator, typename First, typename Second>
- static constexpr auto args(const Allocator &allocator, const std::pair<First, Second> &value) noexcept {
- return uses_allocator_construction<type>::args(allocator, std::piecewise_construct, std::forward_as_tuple(value.first), std::forward_as_tuple(value.second));
- }
- template<typename Allocator, typename First, typename Second>
- static constexpr auto args(const Allocator &allocator, std::pair<First, Second> &&value) noexcept {
- return uses_allocator_construction<type>::args(allocator, std::piecewise_construct, std::forward_as_tuple(std::move(value.first)), std::forward_as_tuple(std::move(value.second)));
- }
- };
- } // namespace internal
- /*! @endcond */
- /**
- * @brief Uses-allocator construction utility (waiting for C++20).
- *
- * Primarily intended for internal use. Prepares the argument list needed to
- * create an object of a given type by means of uses-allocator construction.
- *
- * @tparam Type Type to return arguments for.
- * @tparam Allocator Type of allocator used to manage memory and elements.
- * @tparam Args Types of arguments to use to construct the object.
- * @param allocator The allocator to use.
- * @param args Parameters to use to construct the object.
- * @return The arguments needed to create an object of the given type.
- */
- template<typename Type, typename Allocator, typename... Args>
- constexpr auto uses_allocator_construction_args(const Allocator &allocator, Args &&...args) noexcept {
- return internal::uses_allocator_construction<Type>::args(allocator, std::forward<Args>(args)...);
- }
- /**
- * @brief Uses-allocator construction utility (waiting for C++20).
- *
- * Primarily intended for internal use. Creates an object of a given type by
- * means of uses-allocator construction.
- *
- * @tparam Type Type of object to create.
- * @tparam Allocator Type of allocator used to manage memory and elements.
- * @tparam Args Types of arguments to use to construct the object.
- * @param allocator The allocator to use.
- * @param args Parameters to use to construct the object.
- * @return A newly created object of the given type.
- */
- template<typename Type, typename Allocator, typename... Args>
- constexpr Type make_obj_using_allocator(const Allocator &allocator, Args &&...args) {
- return std::make_from_tuple<Type>(internal::uses_allocator_construction<Type>::args(allocator, std::forward<Args>(args)...));
- }
- /**
- * @brief Uses-allocator construction utility (waiting for C++20).
- *
- * Primarily intended for internal use. Creates an object of a given type by
- * means of uses-allocator construction at an uninitialized memory location.
- *
- * @tparam Type Type of object to create.
- * @tparam Allocator Type of allocator used to manage memory and elements.
- * @tparam Args Types of arguments to use to construct the object.
- * @param value Memory location in which to place the object.
- * @param allocator The allocator to use.
- * @param args Parameters to use to construct the object.
- * @return A pointer to the newly created object of the given type.
- */
- template<typename Type, typename Allocator, typename... Args>
- constexpr Type *uninitialized_construct_using_allocator(Type *value, const Allocator &allocator, Args &&...args) {
- return std::apply([value](auto &&...curr) { return ::new(value) Type(std::forward<decltype(curr)>(curr)...); }, internal::uses_allocator_construction<Type>::args(allocator, std::forward<Args>(args)...));
- }
- } // namespace entt
- #endif
- // #include "../core/type_traits.hpp"
- #ifndef ENTT_CORE_TYPE_TRAITS_HPP
- #define ENTT_CORE_TYPE_TRAITS_HPP
- #include <cstddef>
- #include <iterator>
- #include <tuple>
- #include <type_traits>
- #include <utility>
- // #include "../config/config.h"
- // #include "fwd.hpp"
- namespace entt {
- /**
- * @brief Utility class to disambiguate overloaded functions.
- * @tparam N Number of choices available.
- */
- template<std::size_t N>
- struct choice_t
- // unfortunately, doxygen cannot parse such a construct
- : /*! @cond TURN_OFF_DOXYGEN */ choice_t<N - 1> /*! @endcond */
- {};
- /*! @copybrief choice_t */
- template<>
- struct choice_t<0> {};
- /**
- * @brief Variable template for the choice trick.
- * @tparam N Number of choices available.
- */
- template<std::size_t N>
- inline constexpr choice_t<N> choice{};
- /**
- * @brief Identity type trait.
- *
- * Useful to establish non-deduced contexts in template argument deduction
- * (waiting for C++20) or to provide types through function arguments.
- *
- * @tparam Type A type.
- */
- template<typename Type>
- struct type_identity {
- /*! @brief Identity type. */
- using type = Type;
- };
- /**
- * @brief Helper type.
- * @tparam Type A type.
- */
- template<typename Type>
- using type_identity_t = typename type_identity<Type>::type;
- /**
- * @brief A type-only `sizeof` wrapper that returns 0 where `sizeof` complains.
- * @tparam Type The type of which to return the size.
- */
- template<typename Type, typename = void>
- struct size_of: std::integral_constant<std::size_t, 0u> {};
- /*! @copydoc size_of */
- template<typename Type>
- struct size_of<Type, std::void_t<decltype(sizeof(Type))>>
- // NOLINTNEXTLINE(bugprone-sizeof-expression)
- : std::integral_constant<std::size_t, sizeof(Type)> {};
- /**
- * @brief Helper variable template.
- * @tparam Type The type of which to return the size.
- */
- template<typename Type>
- inline constexpr std::size_t size_of_v = size_of<Type>::value;
- /**
- * @brief Using declaration to be used to _repeat_ the same type a number of
- * times equal to the size of a given parameter pack.
- * @tparam Type A type to repeat.
- */
- template<typename Type, typename>
- using unpack_as_type = Type;
- /**
- * @brief Helper variable template to be used to _repeat_ the same value a
- * number of times equal to the size of a given parameter pack.
- * @tparam Value A value to repeat.
- */
- template<auto Value, typename>
- inline constexpr auto unpack_as_value = Value;
- /**
- * @brief Wraps a static constant.
- * @tparam Value A static constant.
- */
- template<auto Value>
- using integral_constant = std::integral_constant<decltype(Value), Value>;
- /**
- * @brief Alias template to facilitate the creation of named values.
- * @tparam Value A constant value at least convertible to `id_type`.
- */
- template<id_type Value>
- using tag = integral_constant<Value>;
- /**
- * @brief A class to use to push around lists of types, nothing more.
- * @tparam Type Types provided by the type list.
- */
- template<typename... Type>
- struct type_list {
- /*! @brief Type list type. */
- using type = type_list;
- /*! @brief Compile-time number of elements in the type list. */
- static constexpr auto size = sizeof...(Type);
- };
- /*! @brief Primary template isn't defined on purpose. */
- template<std::size_t, typename>
- struct type_list_element;
- /**
- * @brief Provides compile-time indexed access to the types of a type list.
- * @tparam Index Index of the type to return.
- * @tparam First First type provided by the type list.
- * @tparam Other Other types provided by the type list.
- */
- template<std::size_t Index, typename First, typename... Other>
- struct type_list_element<Index, type_list<First, Other...>>
- : type_list_element<Index - 1u, type_list<Other...>> {};
- /**
- * @brief Provides compile-time indexed access to the types of a type list.
- * @tparam First First type provided by the type list.
- * @tparam Other Other types provided by the type list.
- */
- template<typename First, typename... Other>
- struct type_list_element<0u, type_list<First, Other...>> {
- /*! @brief Searched type. */
- using type = First;
- };
- /**
- * @brief Helper type.
- * @tparam Index Index of the type to return.
- * @tparam List Type list to search into.
- */
- template<std::size_t Index, typename List>
- using type_list_element_t = typename type_list_element<Index, List>::type;
- /*! @brief Primary template isn't defined on purpose. */
- template<typename, typename>
- struct type_list_index;
- /**
- * @brief Provides compile-time type access to the types of a type list.
- * @tparam Type Type to look for and for which to return the index.
- * @tparam First First type provided by the type list.
- * @tparam Other Other types provided by the type list.
- */
- template<typename Type, typename First, typename... Other>
- struct type_list_index<Type, type_list<First, Other...>> {
- /*! @brief Unsigned integer type. */
- using value_type = std::size_t;
- /*! @brief Compile-time position of the given type in the sublist. */
- static constexpr value_type value = 1u + type_list_index<Type, type_list<Other...>>::value;
- };
- /**
- * @brief Provides compile-time type access to the types of a type list.
- * @tparam Type Type to look for and for which to return the index.
- * @tparam Other Other types provided by the type list.
- */
- template<typename Type, typename... Other>
- struct type_list_index<Type, type_list<Type, Other...>> {
- static_assert(type_list_index<Type, type_list<Other...>>::value == sizeof...(Other), "Non-unique type");
- /*! @brief Unsigned integer type. */
- using value_type = std::size_t;
- /*! @brief Compile-time position of the given type in the sublist. */
- static constexpr value_type value = 0u;
- };
- /**
- * @brief Provides compile-time type access to the types of a type list.
- * @tparam Type Type to look for and for which to return the index.
- */
- template<typename Type>
- struct type_list_index<Type, type_list<>> {
- /*! @brief Unsigned integer type. */
- using value_type = std::size_t;
- /*! @brief Compile-time position of the given type in the sublist. */
- static constexpr value_type value = 0u;
- };
- /**
- * @brief Helper variable template.
- * @tparam List Type list.
- * @tparam Type Type to look for and for which to return the index.
- */
- template<typename Type, typename List>
- inline constexpr std::size_t type_list_index_v = type_list_index<Type, List>::value;
- /**
- * @brief Concatenates multiple type lists.
- * @tparam Type Types provided by the first type list.
- * @tparam Other Types provided by the second type list.
- * @return A type list composed by the types of both the type lists.
- */
- template<typename... Type, typename... Other>
- constexpr type_list<Type..., Other...> operator+(type_list<Type...>, type_list<Other...>) {
- return {};
- }
- /*! @brief Primary template isn't defined on purpose. */
- template<typename...>
- struct type_list_cat;
- /*! @brief Concatenates multiple type lists. */
- template<>
- struct type_list_cat<> {
- /*! @brief A type list composed by the types of all the type lists. */
- using type = type_list<>;
- };
- /**
- * @brief Concatenates multiple type lists.
- * @tparam Type Types provided by the first type list.
- * @tparam Other Types provided by the second type list.
- * @tparam List Other type lists, if any.
- */
- template<typename... Type, typename... Other, typename... List>
- struct type_list_cat<type_list<Type...>, type_list<Other...>, List...> {
- /*! @brief A type list composed by the types of all the type lists. */
- using type = typename type_list_cat<type_list<Type..., Other...>, List...>::type;
- };
- /**
- * @brief Concatenates multiple type lists.
- * @tparam Type Types provided by the type list.
- */
- template<typename... Type>
- struct type_list_cat<type_list<Type...>> {
- /*! @brief A type list composed by the types of all the type lists. */
- using type = type_list<Type...>;
- };
- /**
- * @brief Helper type.
- * @tparam List Type lists to concatenate.
- */
- template<typename... List>
- using type_list_cat_t = typename type_list_cat<List...>::type;
- /*! @cond TURN_OFF_DOXYGEN */
- namespace internal {
- template<typename...>
- struct type_list_unique;
- template<typename First, typename... Other, typename... Type>
- struct type_list_unique<type_list<First, Other...>, Type...>
- : std::conditional_t<(std::is_same_v<First, Type> || ...), type_list_unique<type_list<Other...>, Type...>, type_list_unique<type_list<Other...>, Type..., First>> {};
- template<typename... Type>
- struct type_list_unique<type_list<>, Type...> {
- using type = type_list<Type...>;
- };
- } // namespace internal
- /*! @endcond */
- /**
- * @brief Removes duplicates types from a type list.
- * @tparam List Type list.
- */
- template<typename List>
- struct type_list_unique {
- /*! @brief A type list without duplicate types. */
- using type = typename internal::type_list_unique<List>::type;
- };
- /**
- * @brief Helper type.
- * @tparam List Type list.
- */
- template<typename List>
- using type_list_unique_t = typename type_list_unique<List>::type;
- /**
- * @brief Provides the member constant `value` to true if a type list contains a
- * given type, false otherwise.
- * @tparam List Type list.
- * @tparam Type Type to look for.
- */
- template<typename List, typename Type>
- struct type_list_contains;
- /**
- * @copybrief type_list_contains
- * @tparam Type Types provided by the type list.
- * @tparam Other Type to look for.
- */
- template<typename... Type, typename Other>
- struct type_list_contains<type_list<Type...>, Other>
- : std::bool_constant<(std::is_same_v<Type, Other> || ...)> {};
- /**
- * @brief Helper variable template.
- * @tparam List Type list.
- * @tparam Type Type to look for.
- */
- template<typename List, typename Type>
- inline constexpr bool type_list_contains_v = type_list_contains<List, Type>::value;
- /*! @brief Primary template isn't defined on purpose. */
- template<typename...>
- struct type_list_diff;
- /**
- * @brief Computes the difference between two type lists.
- * @tparam Type Types provided by the first type list.
- * @tparam Other Types provided by the second type list.
- */
- template<typename... Type, typename... Other>
- struct type_list_diff<type_list<Type...>, type_list<Other...>> {
- /*! @brief A type list that is the difference between the two type lists. */
- using type = type_list_cat_t<std::conditional_t<type_list_contains_v<type_list<Other...>, Type>, type_list<>, type_list<Type>>...>;
- };
- /**
- * @brief Helper type.
- * @tparam List Type lists between which to compute the difference.
- */
- template<typename... List>
- using type_list_diff_t = typename type_list_diff<List...>::type;
- /*! @brief Primary template isn't defined on purpose. */
- template<typename, template<typename...> class>
- struct type_list_transform;
- /**
- * @brief Applies a given _function_ to a type list and generate a new list.
- * @tparam Type Types provided by the type list.
- * @tparam Op Unary operation as template class with a type member named `type`.
- */
- template<typename... Type, template<typename...> class Op>
- struct type_list_transform<type_list<Type...>, Op> {
- /*! @brief Resulting type list after applying the transform function. */
- // NOLINTNEXTLINE(modernize-type-traits)
- using type = type_list<typename Op<Type>::type...>;
- };
- /**
- * @brief Helper type.
- * @tparam List Type list.
- * @tparam Op Unary operation as template class with a type member named `type`.
- */
- template<typename List, template<typename...> class Op>
- using type_list_transform_t = typename type_list_transform<List, Op>::type;
- /**
- * @brief A class to use to push around lists of constant values, nothing more.
- * @tparam Value Values provided by the value list.
- */
- template<auto... Value>
- struct value_list {
- /*! @brief Value list type. */
- using type = value_list;
- /*! @brief Compile-time number of elements in the value list. */
- static constexpr auto size = sizeof...(Value);
- };
- /*! @brief Primary template isn't defined on purpose. */
- template<std::size_t, typename>
- struct value_list_element;
- /**
- * @brief Provides compile-time indexed access to the values of a value list.
- * @tparam Index Index of the value to return.
- * @tparam Value First value provided by the value list.
- * @tparam Other Other values provided by the value list.
- */
- template<std::size_t Index, auto Value, auto... Other>
- struct value_list_element<Index, value_list<Value, Other...>>
- : value_list_element<Index - 1u, value_list<Other...>> {};
- /**
- * @brief Provides compile-time indexed access to the types of a type list.
- * @tparam Value First value provided by the value list.
- * @tparam Other Other values provided by the value list.
- */
- template<auto Value, auto... Other>
- struct value_list_element<0u, value_list<Value, Other...>> {
- /*! @brief Searched type. */
- using type = decltype(Value);
- /*! @brief Searched value. */
- static constexpr auto value = Value;
- };
- /**
- * @brief Helper type.
- * @tparam Index Index of the type to return.
- * @tparam List Value list to search into.
- */
- template<std::size_t Index, typename List>
- using value_list_element_t = typename value_list_element<Index, List>::type;
- /**
- * @brief Helper type.
- * @tparam Index Index of the value to return.
- * @tparam List Value list to search into.
- */
- template<std::size_t Index, typename List>
- inline constexpr auto value_list_element_v = value_list_element<Index, List>::value;
- /*! @brief Primary template isn't defined on purpose. */
- template<auto, typename>
- struct value_list_index;
- /**
- * @brief Provides compile-time type access to the values of a value list.
- * @tparam Value Value to look for and for which to return the index.
- * @tparam First First value provided by the value list.
- * @tparam Other Other values provided by the value list.
- */
- template<auto Value, auto First, auto... Other>
- struct value_list_index<Value, value_list<First, Other...>> {
- /*! @brief Unsigned integer type. */
- using value_type = std::size_t;
- /*! @brief Compile-time position of the given value in the sublist. */
- static constexpr value_type value = 1u + value_list_index<Value, value_list<Other...>>::value;
- };
- /**
- * @brief Provides compile-time type access to the values of a value list.
- * @tparam Value Value to look for and for which to return the index.
- * @tparam Other Other values provided by the value list.
- */
- template<auto Value, auto... Other>
- struct value_list_index<Value, value_list<Value, Other...>> {
- static_assert(value_list_index<Value, value_list<Other...>>::value == sizeof...(Other), "Non-unique type");
- /*! @brief Unsigned integer type. */
- using value_type = std::size_t;
- /*! @brief Compile-time position of the given value in the sublist. */
- static constexpr value_type value = 0u;
- };
- /**
- * @brief Provides compile-time type access to the values of a value list.
- * @tparam Value Value to look for and for which to return the index.
- */
- template<auto Value>
- struct value_list_index<Value, value_list<>> {
- /*! @brief Unsigned integer type. */
- using value_type = std::size_t;
- /*! @brief Compile-time position of the given type in the sublist. */
- static constexpr value_type value = 0u;
- };
- /**
- * @brief Helper variable template.
- * @tparam List Value list.
- * @tparam Value Value to look for and for which to return the index.
- */
- template<auto Value, typename List>
- inline constexpr std::size_t value_list_index_v = value_list_index<Value, List>::value;
- /**
- * @brief Concatenates multiple value lists.
- * @tparam Value Values provided by the first value list.
- * @tparam Other Values provided by the second value list.
- * @return A value list composed by the values of both the value lists.
- */
- template<auto... Value, auto... Other>
- constexpr value_list<Value..., Other...> operator+(value_list<Value...>, value_list<Other...>) {
- return {};
- }
- /*! @brief Primary template isn't defined on purpose. */
- template<typename...>
- struct value_list_cat;
- /*! @brief Concatenates multiple value lists. */
- template<>
- struct value_list_cat<> {
- /*! @brief A value list composed by the values of all the value lists. */
- using type = value_list<>;
- };
- /**
- * @brief Concatenates multiple value lists.
- * @tparam Value Values provided by the first value list.
- * @tparam Other Values provided by the second value list.
- * @tparam List Other value lists, if any.
- */
- template<auto... Value, auto... Other, typename... List>
- struct value_list_cat<value_list<Value...>, value_list<Other...>, List...> {
- /*! @brief A value list composed by the values of all the value lists. */
- using type = typename value_list_cat<value_list<Value..., Other...>, List...>::type;
- };
- /**
- * @brief Concatenates multiple value lists.
- * @tparam Value Values provided by the value list.
- */
- template<auto... Value>
- struct value_list_cat<value_list<Value...>> {
- /*! @brief A value list composed by the values of all the value lists. */
- using type = value_list<Value...>;
- };
- /**
- * @brief Helper type.
- * @tparam List Value lists to concatenate.
- */
- template<typename... List>
- using value_list_cat_t = typename value_list_cat<List...>::type;
- /*! @brief Primary template isn't defined on purpose. */
- template<typename>
- struct value_list_unique;
- /**
- * @brief Removes duplicates values from a value list.
- * @tparam Value One of the values provided by the given value list.
- * @tparam Other The other values provided by the given value list.
- */
- template<auto Value, auto... Other>
- struct value_list_unique<value_list<Value, Other...>> {
- /*! @brief A value list without duplicate types. */
- using type = std::conditional_t<
- ((Value == Other) || ...),
- typename value_list_unique<value_list<Other...>>::type,
- value_list_cat_t<value_list<Value>, typename value_list_unique<value_list<Other...>>::type>>;
- };
- /*! @brief Removes duplicates values from a value list. */
- template<>
- struct value_list_unique<value_list<>> {
- /*! @brief A value list without duplicate types. */
- using type = value_list<>;
- };
- /**
- * @brief Helper type.
- * @tparam Type A value list.
- */
- template<typename Type>
- using value_list_unique_t = typename value_list_unique<Type>::type;
- /**
- * @brief Provides the member constant `value` to true if a value list contains
- * a given value, false otherwise.
- * @tparam List Value list.
- * @tparam Value Value to look for.
- */
- template<typename List, auto Value>
- struct value_list_contains;
- /**
- * @copybrief value_list_contains
- * @tparam Value Values provided by the value list.
- * @tparam Other Value to look for.
- */
- template<auto... Value, auto Other>
- struct value_list_contains<value_list<Value...>, Other>
- : std::bool_constant<((Value == Other) || ...)> {};
- /**
- * @brief Helper variable template.
- * @tparam List Value list.
- * @tparam Value Value to look for.
- */
- template<typename List, auto Value>
- inline constexpr bool value_list_contains_v = value_list_contains<List, Value>::value;
- /*! @brief Primary template isn't defined on purpose. */
- template<typename...>
- struct value_list_diff;
- /**
- * @brief Computes the difference between two value lists.
- * @tparam Value Values provided by the first value list.
- * @tparam Other Values provided by the second value list.
- */
- template<auto... Value, auto... Other>
- struct value_list_diff<value_list<Value...>, value_list<Other...>> {
- /*! @brief A value list that is the difference between the two value lists. */
- using type = value_list_cat_t<std::conditional_t<value_list_contains_v<value_list<Other...>, Value>, value_list<>, value_list<Value>>...>;
- };
- /**
- * @brief Helper type.
- * @tparam List Value lists between which to compute the difference.
- */
- template<typename... List>
- using value_list_diff_t = typename value_list_diff<List...>::type;
- /*! @brief Same as std::is_invocable, but with tuples. */
- template<typename, typename>
- struct is_applicable: std::false_type {};
- /**
- * @copybrief is_applicable
- * @tparam Func A valid function type.
- * @tparam Tuple Tuple-like type.
- * @tparam Args The list of arguments to use to probe the function type.
- */
- template<typename Func, template<typename...> class Tuple, typename... Args>
- struct is_applicable<Func, Tuple<Args...>>: std::is_invocable<Func, Args...> {};
- /**
- * @copybrief is_applicable
- * @tparam Func A valid function type.
- * @tparam Tuple Tuple-like type.
- * @tparam Args The list of arguments to use to probe the function type.
- */
- template<typename Func, template<typename...> class Tuple, typename... Args>
- struct is_applicable<Func, const Tuple<Args...>>: std::is_invocable<Func, Args...> {};
- /**
- * @brief Helper variable template.
- * @tparam Func A valid function type.
- * @tparam Args The list of arguments to use to probe the function type.
- */
- template<typename Func, typename Args>
- inline constexpr bool is_applicable_v = is_applicable<Func, Args>::value;
- /*! @brief Same as std::is_invocable_r, but with tuples for arguments. */
- template<typename, typename, typename>
- struct is_applicable_r: std::false_type {};
- /**
- * @copybrief is_applicable_r
- * @tparam Ret The type to which the return type of the function should be
- * convertible.
- * @tparam Func A valid function type.
- * @tparam Args The list of arguments to use to probe the function type.
- */
- template<typename Ret, typename Func, typename... Args>
- struct is_applicable_r<Ret, Func, std::tuple<Args...>>: std::is_invocable_r<Ret, Func, Args...> {};
- /**
- * @brief Helper variable template.
- * @tparam Ret The type to which the return type of the function should be
- * convertible.
- * @tparam Func A valid function type.
- * @tparam Args The list of arguments to use to probe the function type.
- */
- template<typename Ret, typename Func, typename Args>
- inline constexpr bool is_applicable_r_v = is_applicable_r<Ret, Func, Args>::value;
- /**
- * @brief Provides the member constant `value` to true if a given type is
- * complete, false otherwise.
- * @tparam Type The type to test.
- */
- template<typename Type, typename = void>
- struct is_complete: std::false_type {};
- /*! @copydoc is_complete */
- template<typename Type>
- struct is_complete<Type, std::void_t<decltype(sizeof(Type))>>: std::true_type {};
- /**
- * @brief Helper variable template.
- * @tparam Type The type to test.
- */
- template<typename Type>
- inline constexpr bool is_complete_v = is_complete<Type>::value;
- /**
- * @brief Provides the member constant `value` to true if a given type is an
- * iterator, false otherwise.
- * @tparam Type The type to test.
- */
- template<typename Type, typename = void>
- struct is_iterator: std::false_type {};
- /*! @cond TURN_OFF_DOXYGEN */
- namespace internal {
- template<typename, typename = void>
- struct has_iterator_category: std::false_type {};
- template<typename Type>
- struct has_iterator_category<Type, std::void_t<typename std::iterator_traits<Type>::iterator_category>>: std::true_type {};
- } // namespace internal
- /*! @endcond */
- /*! @copydoc is_iterator */
- template<typename Type>
- struct is_iterator<Type, std::enable_if_t<!std::is_void_v<std::remove_const_t<std::remove_pointer_t<Type>>>>>
- : internal::has_iterator_category<Type> {};
- /**
- * @brief Helper variable template.
- * @tparam Type The type to test.
- */
- template<typename Type>
- inline constexpr bool is_iterator_v = is_iterator<Type>::value;
- /**
- * @brief Provides the member constant `value` to true if a given type is both
- * an empty and non-final class, false otherwise.
- * @tparam Type The type to test
- */
- template<typename Type>
- struct is_ebco_eligible
- : std::bool_constant<std::is_empty_v<Type> && !std::is_final_v<Type>> {};
- /**
- * @brief Helper variable template.
- * @tparam Type The type to test.
- */
- template<typename Type>
- inline constexpr bool is_ebco_eligible_v = is_ebco_eligible<Type>::value;
- /**
- * @brief Provides the member constant `value` to true if `Type::is_transparent`
- * is valid and denotes a type, false otherwise.
- * @tparam Type The type to test.
- */
- template<typename Type, typename = void>
- struct is_transparent: std::false_type {};
- /*! @copydoc is_transparent */
- template<typename Type>
- struct is_transparent<Type, std::void_t<typename Type::is_transparent>>: std::true_type {};
- /**
- * @brief Helper variable template.
- * @tparam Type The type to test.
- */
- template<typename Type>
- inline constexpr bool is_transparent_v = is_transparent<Type>::value;
- /*! @cond TURN_OFF_DOXYGEN */
- namespace internal {
- template<typename, typename = void>
- struct has_tuple_size_value: std::false_type {};
- template<typename Type>
- struct has_tuple_size_value<Type, std::void_t<decltype(std::tuple_size<const Type>::value)>>: std::true_type {};
- template<typename, typename = void>
- struct has_value_type: std::false_type {};
- template<typename Type>
- struct has_value_type<Type, std::void_t<typename Type::value_type>>: std::true_type {};
- template<typename>
- [[nodiscard]] constexpr bool dispatch_is_equality_comparable();
- template<typename Type, std::size_t... Index>
- [[nodiscard]] constexpr bool unpack_maybe_equality_comparable(std::index_sequence<Index...>) {
- return (dispatch_is_equality_comparable<std::tuple_element_t<Index, Type>>() && ...);
- }
- template<typename>
- [[nodiscard]] constexpr bool maybe_equality_comparable(char) {
- return false;
- }
- template<typename Type>
- [[nodiscard]] constexpr auto maybe_equality_comparable(int) -> decltype(std::declval<Type>() == std::declval<Type>()) {
- return true;
- }
- template<typename Type>
- [[nodiscard]] constexpr bool dispatch_is_equality_comparable() {
- // NOLINTBEGIN(modernize-use-transparent-functors)
- if constexpr(std::is_array_v<Type>) {
- return false;
- } else if constexpr(is_complete_v<std::tuple_size<std::remove_const_t<Type>>>) {
- if constexpr(has_tuple_size_value<Type>::value) {
- return maybe_equality_comparable<Type>(0) && unpack_maybe_equality_comparable<Type>(std::make_index_sequence<std::tuple_size<Type>::value>{});
- } else {
- return maybe_equality_comparable<Type>(0);
- }
- } else if constexpr(has_value_type<Type>::value) {
- if constexpr(is_iterator_v<Type> || std::is_same_v<typename Type::value_type, Type> || dispatch_is_equality_comparable<typename Type::value_type>()) {
- return maybe_equality_comparable<Type>(0);
- } else {
- return false;
- }
- } else {
- return maybe_equality_comparable<Type>(0);
- }
- // NOLINTEND(modernize-use-transparent-functors)
- }
- } // namespace internal
- /*! @endcond */
- /**
- * @brief Provides the member constant `value` to true if a given type is
- * equality comparable, false otherwise.
- * @tparam Type The type to test.
- */
- template<typename Type>
- struct is_equality_comparable: std::bool_constant<internal::dispatch_is_equality_comparable<Type>()> {};
- /*! @copydoc is_equality_comparable */
- template<typename Type>
- struct is_equality_comparable<const Type>: is_equality_comparable<Type> {};
- /**
- * @brief Helper variable template.
- * @tparam Type The type to test.
- */
- template<typename Type>
- inline constexpr bool is_equality_comparable_v = is_equality_comparable<Type>::value;
- /**
- * @brief Transcribes the constness of a type to another type.
- * @tparam To The type to which to transcribe the constness.
- * @tparam From The type from which to transcribe the constness.
- */
- template<typename To, typename From>
- struct constness_as {
- /*! @brief The type resulting from the transcription of the constness. */
- using type = std::remove_const_t<To>;
- };
- /*! @copydoc constness_as */
- template<typename To, typename From>
- struct constness_as<To, const From> {
- /*! @brief The type resulting from the transcription of the constness. */
- using type = const To;
- };
- /**
- * @brief Alias template to facilitate the transcription of the constness.
- * @tparam To The type to which to transcribe the constness.
- * @tparam From The type from which to transcribe the constness.
- */
- template<typename To, typename From>
- using constness_as_t = typename constness_as<To, From>::type;
- /**
- * @brief Extracts the class of a non-static member object or function.
- * @tparam Member A pointer to a non-static member object or function.
- */
- template<typename Member>
- class member_class {
- static_assert(std::is_member_pointer_v<Member>, "Invalid pointer type to non-static member object or function");
- template<typename Class, typename Ret, typename... Args>
- static Class *clazz(Ret (Class::*)(Args...));
- template<typename Class, typename Ret, typename... Args>
- static Class *clazz(Ret (Class::*)(Args...) const);
- template<typename Class, typename Type>
- static Class *clazz(Type Class::*);
- public:
- /*! @brief The class of the given non-static member object or function. */
- using type = std::remove_pointer_t<decltype(clazz(std::declval<Member>()))>;
- };
- /**
- * @brief Helper type.
- * @tparam Member A pointer to a non-static member object or function.
- */
- template<typename Member>
- using member_class_t = typename member_class<Member>::type;
- /**
- * @brief Extracts the n-th argument of a _callable_ type.
- * @tparam Index The index of the argument to extract.
- * @tparam Candidate A valid _callable_ type.
- */
- template<std::size_t Index, typename Candidate>
- class nth_argument {
- template<typename Ret, typename... Args>
- static constexpr type_list<Args...> pick_up(Ret (*)(Args...));
- template<typename Ret, typename Class, typename... Args>
- static constexpr type_list<Args...> pick_up(Ret (Class ::*)(Args...));
- template<typename Ret, typename Class, typename... Args>
- static constexpr type_list<Args...> pick_up(Ret (Class ::*)(Args...) const);
- template<typename Type, typename Class>
- static constexpr type_list<Type> pick_up(Type Class ::*);
- template<typename Type>
- static constexpr decltype(pick_up(&Type::operator())) pick_up(Type &&);
- public:
- /*! @brief N-th argument of the _callable_ type. */
- using type = type_list_element_t<Index, decltype(pick_up(std::declval<Candidate>()))>;
- };
- /**
- * @brief Helper type.
- * @tparam Index The index of the argument to extract.
- * @tparam Candidate A valid function, member function or data member type.
- */
- template<std::size_t Index, typename Candidate>
- using nth_argument_t = typename nth_argument<Index, Candidate>::type;
- } // namespace entt
- template<typename... Type>
- struct std::tuple_size<entt::type_list<Type...>>: std::integral_constant<std::size_t, entt::type_list<Type...>::size> {};
- template<std::size_t Index, typename... Type>
- struct std::tuple_element<Index, entt::type_list<Type...>>: entt::type_list_element<Index, entt::type_list<Type...>> {};
- template<auto... Value>
- struct std::tuple_size<entt::value_list<Value...>>: std::integral_constant<std::size_t, entt::value_list<Value...>::size> {};
- template<std::size_t Index, auto... Value>
- struct std::tuple_element<Index, entt::value_list<Value...>>: entt::value_list_element<Index, entt::value_list<Value...>> {};
- #endif
- // #include "fwd.hpp"
- #ifndef ENTT_CONTAINER_FWD_HPP
- #define ENTT_CONTAINER_FWD_HPP
- #include <functional>
- #include <memory>
- #include <utility>
- #include <vector>
- namespace entt {
- template<
- typename Key,
- typename Type,
- typename = std::hash<Key>,
- typename = std::equal_to<>,
- typename = std::allocator<std::pair<const Key, Type>>>
- class dense_map;
- template<
- typename Type,
- typename = std::hash<Type>,
- typename = std::equal_to<>,
- typename = std::allocator<Type>>
- class dense_set;
- template<typename...>
- class basic_table;
- /**
- * @brief Alias declaration for the most common use case.
- * @tparam Type Element types.
- */
- template<typename... Type>
- using table = basic_table<std::vector<Type>...>;
- } // namespace entt
- #endif
- namespace entt {
- /*! @cond TURN_OFF_DOXYGEN */
- namespace internal {
- static constexpr std::size_t dense_map_placeholder_position = (std::numeric_limits<std::size_t>::max)();
- template<typename Key, typename Type>
- struct dense_map_node final {
- using value_type = std::pair<Key, Type>;
- template<typename... Args>
- dense_map_node(const std::size_t pos, Args &&...args)
- : next{pos},
- element{std::forward<Args>(args)...} {}
- template<typename Allocator, typename... Args>
- dense_map_node(std::allocator_arg_t, const Allocator &allocator, const std::size_t pos, Args &&...args)
- : next{pos},
- element{entt::make_obj_using_allocator<value_type>(allocator, std::forward<Args>(args)...)} {}
- template<typename Allocator>
- dense_map_node(std::allocator_arg_t, const Allocator &allocator, const dense_map_node &other)
- : next{other.next},
- element{entt::make_obj_using_allocator<value_type>(allocator, other.element)} {}
- template<typename Allocator>
- dense_map_node(std::allocator_arg_t, const Allocator &allocator, dense_map_node &&other)
- : next{other.next},
- element{entt::make_obj_using_allocator<value_type>(allocator, std::move(other.element))} {}
- std::size_t next;
- value_type element;
- };
- template<typename It>
- class dense_map_iterator final {
- template<typename>
- friend class dense_map_iterator;
- using first_type = decltype(std::as_const(std::declval<It>()->element.first));
- using second_type = decltype((std::declval<It>()->element.second));
- public:
- using value_type = std::pair<first_type, second_type>;
- using pointer = input_iterator_pointer<value_type>;
- using reference = value_type;
- using difference_type = std::ptrdiff_t;
- using iterator_category = std::input_iterator_tag;
- using iterator_concept = std::random_access_iterator_tag;
- constexpr dense_map_iterator() noexcept
- : it{} {}
- constexpr dense_map_iterator(const It iter) noexcept
- : it{iter} {}
- template<typename Other, typename = std::enable_if_t<!std::is_same_v<It, Other> && std::is_constructible_v<It, Other>>>
- constexpr dense_map_iterator(const dense_map_iterator<Other> &other) noexcept
- : it{other.it} {}
- constexpr dense_map_iterator &operator++() noexcept {
- return ++it, *this;
- }
- constexpr dense_map_iterator operator++(int) noexcept {
- const dense_map_iterator orig = *this;
- return ++(*this), orig;
- }
- constexpr dense_map_iterator &operator--() noexcept {
- return --it, *this;
- }
- constexpr dense_map_iterator operator--(int) noexcept {
- const dense_map_iterator orig = *this;
- return operator--(), orig;
- }
- constexpr dense_map_iterator &operator+=(const difference_type value) noexcept {
- it += value;
- return *this;
- }
- constexpr dense_map_iterator operator+(const difference_type value) const noexcept {
- dense_map_iterator copy = *this;
- return (copy += value);
- }
- constexpr dense_map_iterator &operator-=(const difference_type value) noexcept {
- return (*this += -value);
- }
- constexpr dense_map_iterator operator-(const difference_type value) const noexcept {
- return (*this + -value);
- }
- [[nodiscard]] constexpr reference operator[](const difference_type value) const noexcept {
- return {it[value].element.first, it[value].element.second};
- }
- [[nodiscard]] constexpr pointer operator->() const noexcept {
- return operator*();
- }
- [[nodiscard]] constexpr reference operator*() const noexcept {
- return operator[](0);
- }
- template<typename Lhs, typename Rhs>
- friend constexpr std::ptrdiff_t operator-(const dense_map_iterator<Lhs> &, const dense_map_iterator<Rhs> &) noexcept;
- template<typename Lhs, typename Rhs>
- friend constexpr bool operator==(const dense_map_iterator<Lhs> &, const dense_map_iterator<Rhs> &) noexcept;
- template<typename Lhs, typename Rhs>
- friend constexpr bool operator<(const dense_map_iterator<Lhs> &, const dense_map_iterator<Rhs> &) noexcept;
- private:
- It it;
- };
- template<typename Lhs, typename Rhs>
- [[nodiscard]] constexpr std::ptrdiff_t operator-(const dense_map_iterator<Lhs> &lhs, const dense_map_iterator<Rhs> &rhs) noexcept {
- return lhs.it - rhs.it;
- }
- template<typename Lhs, typename Rhs>
- [[nodiscard]] constexpr bool operator==(const dense_map_iterator<Lhs> &lhs, const dense_map_iterator<Rhs> &rhs) noexcept {
- return lhs.it == rhs.it;
- }
- template<typename Lhs, typename Rhs>
- [[nodiscard]] constexpr bool operator!=(const dense_map_iterator<Lhs> &lhs, const dense_map_iterator<Rhs> &rhs) noexcept {
- return !(lhs == rhs);
- }
- template<typename Lhs, typename Rhs>
- [[nodiscard]] constexpr bool operator<(const dense_map_iterator<Lhs> &lhs, const dense_map_iterator<Rhs> &rhs) noexcept {
- return lhs.it < rhs.it;
- }
- template<typename Lhs, typename Rhs>
- [[nodiscard]] constexpr bool operator>(const dense_map_iterator<Lhs> &lhs, const dense_map_iterator<Rhs> &rhs) noexcept {
- return rhs < lhs;
- }
- template<typename Lhs, typename Rhs>
- [[nodiscard]] constexpr bool operator<=(const dense_map_iterator<Lhs> &lhs, const dense_map_iterator<Rhs> &rhs) noexcept {
- return !(lhs > rhs);
- }
- template<typename Lhs, typename Rhs>
- [[nodiscard]] constexpr bool operator>=(const dense_map_iterator<Lhs> &lhs, const dense_map_iterator<Rhs> &rhs) noexcept {
- return !(lhs < rhs);
- }
- template<typename It>
- class dense_map_local_iterator final {
- template<typename>
- friend class dense_map_local_iterator;
- using first_type = decltype(std::as_const(std::declval<It>()->element.first));
- using second_type = decltype((std::declval<It>()->element.second));
- public:
- using value_type = std::pair<first_type, second_type>;
- using pointer = input_iterator_pointer<value_type>;
- using reference = value_type;
- using difference_type = std::ptrdiff_t;
- using iterator_category = std::input_iterator_tag;
- using iterator_concept = std::forward_iterator_tag;
- constexpr dense_map_local_iterator() noexcept = default;
- constexpr dense_map_local_iterator(It iter, const std::size_t pos) noexcept
- : it{iter},
- offset{pos} {}
- template<typename Other, typename = std::enable_if_t<!std::is_same_v<It, Other> && std::is_constructible_v<It, Other>>>
- constexpr dense_map_local_iterator(const dense_map_local_iterator<Other> &other) noexcept
- : it{other.it},
- offset{other.offset} {}
- constexpr dense_map_local_iterator &operator++() noexcept {
- return (offset = it[static_cast<typename It::difference_type>(offset)].next), *this;
- }
- constexpr dense_map_local_iterator operator++(int) noexcept {
- const dense_map_local_iterator orig = *this;
- return ++(*this), orig;
- }
- [[nodiscard]] constexpr pointer operator->() const noexcept {
- return operator*();
- }
- [[nodiscard]] constexpr reference operator*() const noexcept {
- const auto idx = static_cast<typename It::difference_type>(offset);
- return {it[idx].element.first, it[idx].element.second};
- }
- [[nodiscard]] constexpr std::size_t index() const noexcept {
- return offset;
- }
- private:
- It it{};
- std::size_t offset{dense_map_placeholder_position};
- };
- template<typename Lhs, typename Rhs>
- [[nodiscard]] constexpr bool operator==(const dense_map_local_iterator<Lhs> &lhs, const dense_map_local_iterator<Rhs> &rhs) noexcept {
- return lhs.index() == rhs.index();
- }
- template<typename Lhs, typename Rhs>
- [[nodiscard]] constexpr bool operator!=(const dense_map_local_iterator<Lhs> &lhs, const dense_map_local_iterator<Rhs> &rhs) noexcept {
- return !(lhs == rhs);
- }
- } // namespace internal
- /*! @endcond */
- /**
- * @brief Associative container for key-value pairs with unique keys.
- *
- * Internally, elements are organized into buckets. Which bucket an element is
- * placed into depends entirely on the hash of its key. Keys with the same hash
- * code appear in the same bucket.
- *
- * @tparam Key Key type of the associative container.
- * @tparam Type Mapped type of the associative container.
- * @tparam Hash Type of function to use to hash the keys.
- * @tparam KeyEqual Type of function to use to compare the keys for equality.
- * @tparam Allocator Type of allocator used to manage memory and elements.
- */
- template<typename Key, typename Type, typename Hash, typename KeyEqual, typename Allocator>
- class dense_map {
- static constexpr float default_threshold = 0.875f;
- static constexpr std::size_t minimum_capacity = 8u;
- static constexpr std::size_t placeholder_position = internal::dense_map_placeholder_position;
- using node_type = internal::dense_map_node<Key, Type>;
- using alloc_traits = std::allocator_traits<Allocator>;
- static_assert(std::is_same_v<typename alloc_traits::value_type, std::pair<const Key, Type>>, "Invalid value type");
- using sparse_container_type = std::vector<std::size_t, typename alloc_traits::template rebind_alloc<std::size_t>>;
- using packed_container_type = std::vector<node_type, typename alloc_traits::template rebind_alloc<node_type>>;
- template<typename Other>
- [[nodiscard]] std::size_t key_to_bucket(const Other &key) const noexcept {
- // NOLINTNEXTLINE(cppcoreguidelines-pro-bounds-array-to-pointer-decay)
- return fast_mod(static_cast<size_type>(sparse.second()(key)), bucket_count());
- }
- template<typename Other>
- [[nodiscard]] auto constrained_find(const Other &key, const std::size_t bucket) {
- for(auto offset = sparse.first()[bucket]; offset != placeholder_position; offset = packed.first()[offset].next) {
- if(packed.second()(packed.first()[offset].element.first, key)) {
- return begin() + static_cast<typename iterator::difference_type>(offset);
- }
- }
- return end();
- }
- template<typename Other>
- [[nodiscard]] auto constrained_find(const Other &key, const std::size_t bucket) const {
- for(auto offset = sparse.first()[bucket]; offset != placeholder_position; offset = packed.first()[offset].next) {
- if(packed.second()(packed.first()[offset].element.first, key)) {
- return cbegin() + static_cast<typename const_iterator::difference_type>(offset);
- }
- }
- return cend();
- }
- template<typename Other, typename... Args>
- [[nodiscard]] auto insert_or_do_nothing(Other &&key, Args &&...args) {
- const auto index = key_to_bucket(key);
- if(auto it = constrained_find(key, index); it != end()) {
- return std::make_pair(it, false);
- }
- packed.first().emplace_back(sparse.first()[index], std::piecewise_construct, std::forward_as_tuple(std::forward<Other>(key)), std::forward_as_tuple(std::forward<Args>(args)...));
- sparse.first()[index] = packed.first().size() - 1u;
- rehash_if_required();
- return std::make_pair(--end(), true);
- }
- template<typename Other, typename Arg>
- [[nodiscard]] auto insert_or_overwrite(Other &&key, Arg &&value) {
- const auto index = key_to_bucket(key);
- if(auto it = constrained_find(key, index); it != end()) {
- it->second = std::forward<Arg>(value);
- return std::make_pair(it, false);
- }
- packed.first().emplace_back(sparse.first()[index], std::forward<Other>(key), std::forward<Arg>(value));
- sparse.first()[index] = packed.first().size() - 1u;
- rehash_if_required();
- return std::make_pair(--end(), true);
- }
- void move_and_pop(const std::size_t pos) {
- if(const auto last = size() - 1u; pos != last) {
- size_type *curr = &sparse.first()[key_to_bucket(packed.first().back().element.first)];
- packed.first()[pos] = std::move(packed.first().back());
- for(; *curr != last; curr = &packed.first()[*curr].next) {}
- *curr = pos;
- }
- packed.first().pop_back();
- }
- void rehash_if_required() {
- if(const auto bc = bucket_count(); size() > static_cast<size_type>(static_cast<float>(bc) * max_load_factor())) {
- rehash(bc * 2u);
- }
- }
- public:
- /*! @brief Allocator type. */
- using allocator_type = Allocator;
- /*! @brief Key type of the container. */
- using key_type = Key;
- /*! @brief Mapped type of the container. */
- using mapped_type = Type;
- /*! @brief Key-value type of the container. */
- using value_type = std::pair<const Key, Type>;
- /*! @brief Unsigned integer type. */
- using size_type = std::size_t;
- /*! @brief Signed integer type. */
- using difference_type = std::ptrdiff_t;
- /*! @brief Type of function to use to hash the keys. */
- using hasher = Hash;
- /*! @brief Type of function to use to compare the keys for equality. */
- using key_equal = KeyEqual;
- /*! @brief Input iterator type. */
- using iterator = internal::dense_map_iterator<typename packed_container_type::iterator>;
- /*! @brief Constant input iterator type. */
- using const_iterator = internal::dense_map_iterator<typename packed_container_type::const_iterator>;
- /*! @brief Input iterator type. */
- using local_iterator = internal::dense_map_local_iterator<typename packed_container_type::iterator>;
- /*! @brief Constant input iterator type. */
- using const_local_iterator = internal::dense_map_local_iterator<typename packed_container_type::const_iterator>;
- /*! @brief Default constructor. */
- dense_map()
- : dense_map{minimum_capacity} {}
- /**
- * @brief Constructs an empty container with a given allocator.
- * @param allocator The allocator to use.
- */
- explicit dense_map(const allocator_type &allocator)
- : dense_map{minimum_capacity, hasher{}, key_equal{}, allocator} {}
- /**
- * @brief Constructs an empty container with a given allocator and user
- * supplied minimal number of buckets.
- * @param cnt Minimal number of buckets.
- * @param allocator The allocator to use.
- */
- dense_map(const size_type cnt, const allocator_type &allocator)
- : dense_map{cnt, hasher{}, key_equal{}, allocator} {}
- /**
- * @brief Constructs an empty container with a given allocator, hash
- * function and user supplied minimal number of buckets.
- * @param cnt Minimal number of buckets.
- * @param hash Hash function to use.
- * @param allocator The allocator to use.
- */
- dense_map(const size_type cnt, const hasher &hash, const allocator_type &allocator)
- : dense_map{cnt, hash, key_equal{}, allocator} {}
- /**
- * @brief Constructs an empty container with a given allocator, hash
- * function, compare function and user supplied minimal number of buckets.
- * @param cnt Minimal number of buckets.
- * @param hash Hash function to use.
- * @param equal Compare function to use.
- * @param allocator The allocator to use.
- */
- explicit dense_map(const size_type cnt, const hasher &hash = hasher{}, const key_equal &equal = key_equal{}, const allocator_type &allocator = allocator_type{})
- : sparse{allocator, hash},
- packed{allocator, equal} {
- rehash(cnt);
- }
- /*! @brief Default copy constructor. */
- dense_map(const dense_map &) = default;
- /**
- * @brief Allocator-extended copy constructor.
- * @param other The instance to copy from.
- * @param allocator The allocator to use.
- */
- dense_map(const dense_map &other, const allocator_type &allocator)
- : sparse{std::piecewise_construct, std::forward_as_tuple(other.sparse.first(), allocator), std::forward_as_tuple(other.sparse.second())},
- packed{std::piecewise_construct, std::forward_as_tuple(other.packed.first(), allocator), std::forward_as_tuple(other.packed.second())},
- threshold{other.threshold} {}
- /*! @brief Default move constructor. */
- dense_map(dense_map &&) noexcept = default;
- /**
- * @brief Allocator-extended move constructor.
- * @param other The instance to move from.
- * @param allocator The allocator to use.
- */
- dense_map(dense_map &&other, const allocator_type &allocator)
- : sparse{std::piecewise_construct, std::forward_as_tuple(std::move(other.sparse.first()), allocator), std::forward_as_tuple(std::move(other.sparse.second()))},
- packed{std::piecewise_construct, std::forward_as_tuple(std::move(other.packed.first()), allocator), std::forward_as_tuple(std::move(other.packed.second()))},
- threshold{other.threshold} {}
- /*! @brief Default destructor. */
- ~dense_map() = default;
- /**
- * @brief Default copy assignment operator.
- * @return This container.
- */
- dense_map &operator=(const dense_map &) = default;
- /**
- * @brief Default move assignment operator.
- * @return This container.
- */
- dense_map &operator=(dense_map &&) noexcept = default;
- /**
- * @brief Exchanges the contents with those of a given container.
- * @param other Container to exchange the content with.
- */
- void swap(dense_map &other) noexcept {
- using std::swap;
- swap(sparse, other.sparse);
- swap(packed, other.packed);
- swap(threshold, other.threshold);
- }
- /**
- * @brief Returns the associated allocator.
- * @return The associated allocator.
- */
- [[nodiscard]] constexpr allocator_type get_allocator() const noexcept {
- return sparse.first().get_allocator();
- }
- /**
- * @brief Returns an iterator to the beginning.
- *
- * If the array is empty, the returned iterator will be equal to `end()`.
- *
- * @return An iterator to the first instance of the internal array.
- */
- [[nodiscard]] const_iterator cbegin() const noexcept {
- return packed.first().begin();
- }
- /*! @copydoc cbegin */
- [[nodiscard]] const_iterator begin() const noexcept {
- return cbegin();
- }
- /*! @copydoc begin */
- [[nodiscard]] iterator begin() noexcept {
- return packed.first().begin();
- }
- /**
- * @brief Returns an iterator to the end.
- * @return An iterator to the element following the last instance of the
- * internal array.
- */
- [[nodiscard]] const_iterator cend() const noexcept {
- return packed.first().end();
- }
- /*! @copydoc cend */
- [[nodiscard]] const_iterator end() const noexcept {
- return cend();
- }
- /*! @copydoc end */
- [[nodiscard]] iterator end() noexcept {
- return packed.first().end();
- }
- /**
- * @brief Checks whether a container is empty.
- * @return True if the container is empty, false otherwise.
- */
- [[nodiscard]] bool empty() const noexcept {
- return packed.first().empty();
- }
- /**
- * @brief Returns the number of elements in a container.
- * @return Number of elements in a container.
- */
- [[nodiscard]] size_type size() const noexcept {
- return packed.first().size();
- }
- /**
- * @brief Returns the maximum possible number of elements.
- * @return Maximum possible number of elements.
- */
- [[nodiscard]] size_type max_size() const noexcept {
- return packed.first().max_size();
- }
- /*! @brief Clears the container. */
- void clear() noexcept {
- sparse.first().clear();
- packed.first().clear();
- rehash(0u);
- }
- /**
- * @brief Inserts an element into the container, if the key does not exist.
- * @param value A key-value pair eventually convertible to the value type.
- * @return A pair consisting of an iterator to the inserted element (or to
- * the element that prevented the insertion) and a bool denoting whether the
- * insertion took place.
- */
- std::pair<iterator, bool> insert(const value_type &value) {
- return insert_or_do_nothing(value.first, value.second);
- }
- /*! @copydoc insert */
- std::pair<iterator, bool> insert(value_type &&value) {
- return insert_or_do_nothing(std::move(value.first), std::move(value.second));
- }
- /**
- * @copydoc insert
- * @tparam Arg Type of the key-value pair to insert into the container.
- */
- template<typename Arg>
- std::enable_if_t<std::is_constructible_v<value_type, Arg &&>, std::pair<iterator, bool>>
- insert(Arg &&value) {
- return insert_or_do_nothing(std::forward<Arg>(value).first, std::forward<Arg>(value).second);
- }
- /**
- * @brief Inserts elements into the container, if their keys do not exist.
- * @tparam It Type of input iterator.
- * @param first An iterator to the first element of the range of elements.
- * @param last An iterator past the last element of the range of elements.
- */
- template<typename It>
- void insert(It first, It last) {
- for(; first != last; ++first) {
- insert(*first);
- }
- }
- /**
- * @brief Inserts an element into the container or assigns to the current
- * element if the key already exists.
- * @tparam Arg Type of the value to insert or assign.
- * @param key A key used both to look up and to insert if not found.
- * @param value A value to insert or assign.
- * @return A pair consisting of an iterator to the element and a bool
- * denoting whether the insertion took place.
- */
- template<typename Arg>
- std::pair<iterator, bool> insert_or_assign(const key_type &key, Arg &&value) {
- return insert_or_overwrite(key, std::forward<Arg>(value));
- }
- /*! @copydoc insert_or_assign */
- template<typename Arg>
- std::pair<iterator, bool> insert_or_assign(key_type &&key, Arg &&value) {
- return insert_or_overwrite(std::move(key), std::forward<Arg>(value));
- }
- /**
- * @brief Constructs an element in-place, if the key does not exist.
- *
- * The element is also constructed when the container already has the key,
- * in which case the newly constructed object is destroyed immediately.
- *
- * @tparam Args Types of arguments to forward to the constructor of the
- * element.
- * @param args Arguments to forward to the constructor of the element.
- * @return A pair consisting of an iterator to the inserted element (or to
- * the element that prevented the insertion) and a bool denoting whether the
- * insertion took place.
- */
- template<typename... Args>
- std::pair<iterator, bool> emplace([[maybe_unused]] Args &&...args) {
- if constexpr(sizeof...(Args) == 0u) {
- return insert_or_do_nothing(key_type{});
- } else if constexpr(sizeof...(Args) == 1u) {
- return insert_or_do_nothing(std::forward<Args>(args).first..., std::forward<Args>(args).second...);
- } else if constexpr(sizeof...(Args) == 2u) {
- return insert_or_do_nothing(std::forward<Args>(args)...);
- } else {
- auto &node = packed.first().emplace_back(packed.first().size(), std::forward<Args>(args)...);
- const auto index = key_to_bucket(node.element.first);
- if(auto it = constrained_find(node.element.first, index); it != end()) {
- packed.first().pop_back();
- return std::make_pair(it, false);
- }
- std::swap(node.next, sparse.first()[index]);
- rehash_if_required();
- return std::make_pair(--end(), true);
- }
- }
- /**
- * @brief Inserts in-place if the key does not exist, does nothing if the
- * key exists.
- * @tparam Args Types of arguments to forward to the constructor of the
- * element.
- * @param key A key used both to look up and to insert if not found.
- * @param args Arguments to forward to the constructor of the element.
- * @return A pair consisting of an iterator to the inserted element (or to
- * the element that prevented the insertion) and a bool denoting whether the
- * insertion took place.
- */
- template<typename... Args>
- std::pair<iterator, bool> try_emplace(const key_type &key, Args &&...args) {
- return insert_or_do_nothing(key, std::forward<Args>(args)...);
- }
- /*! @copydoc try_emplace */
- template<typename... Args>
- std::pair<iterator, bool> try_emplace(key_type &&key, Args &&...args) {
- return insert_or_do_nothing(std::move(key), std::forward<Args>(args)...);
- }
- /**
- * @brief Removes an element from a given position.
- * @param pos An iterator to the element to remove.
- * @return An iterator following the removed element.
- */
- iterator erase(const_iterator pos) {
- const auto diff = pos - cbegin();
- erase(pos->first);
- return begin() + diff;
- }
- /**
- * @brief Removes the given elements from a container.
- * @param first An iterator to the first element of the range of elements.
- * @param last An iterator past the last element of the range of elements.
- * @return An iterator following the last removed element.
- */
- iterator erase(const_iterator first, const_iterator last) {
- const auto dist = first - cbegin();
- for(auto from = last - cbegin(); from != dist; --from) {
- erase(packed.first()[static_cast<size_type>(from) - 1u].element.first);
- }
- return (begin() + dist);
- }
- /**
- * @brief Removes the element associated with a given key.
- * @param key A key value of an element to remove.
- * @return Number of elements removed (either 0 or 1).
- */
- size_type erase(const key_type &key) {
- for(size_type *curr = &sparse.first()[key_to_bucket(key)]; *curr != placeholder_position; curr = &packed.first()[*curr].next) {
- if(packed.second()(packed.first()[*curr].element.first, key)) {
- const auto index = *curr;
- *curr = packed.first()[*curr].next;
- move_and_pop(index);
- return 1u;
- }
- }
- return 0u;
- }
- /**
- * @brief Accesses a given element with bounds checking.
- * @param key A key of an element to find.
- * @return A reference to the mapped value of the requested element.
- */
- [[nodiscard]] mapped_type &at(const key_type &key) {
- auto it = find(key);
- ENTT_ASSERT(it != end(), "Invalid key");
- return it->second;
- }
- /*! @copydoc at */
- [[nodiscard]] const mapped_type &at(const key_type &key) const {
- auto it = find(key);
- ENTT_ASSERT(it != cend(), "Invalid key");
- return it->second;
- }
- /**
- * @brief Accesses a given element with bounds checking.
- * @tparam Other Type of the key of an element to find.
- * @param key A key of an element to find.
- * @return A reference to the mapped value of the requested element.
- */
- template<typename Other>
- [[nodiscard]] std::enable_if_t<is_transparent_v<hasher> && is_transparent_v<key_equal>, std::conditional_t<false, Other, mapped_type const &>>
- at(const Other &key) const {
- auto it = find(key);
- ENTT_ASSERT(it != cend(), "Invalid key");
- return it->second;
- }
- /*! @copydoc at */
- template<typename Other>
- [[nodiscard]] std::enable_if_t<is_transparent_v<hasher> && is_transparent_v<key_equal>, std::conditional_t<false, Other, mapped_type &>>
- at(const Other &key) {
- auto it = find(key);
- ENTT_ASSERT(it != end(), "Invalid key");
- return it->second;
- }
- /**
- * @brief Accesses or inserts a given element.
- * @param key A key of an element to find or insert.
- * @return A reference to the mapped value of the requested element.
- */
- [[nodiscard]] mapped_type &operator[](const key_type &key) {
- return insert_or_do_nothing(key).first->second;
- }
- /**
- * @brief Accesses or inserts a given element.
- * @param key A key of an element to find or insert.
- * @return A reference to the mapped value of the requested element.
- */
- [[nodiscard]] mapped_type &operator[](key_type &&key) {
- return insert_or_do_nothing(std::move(key)).first->second;
- }
- /**
- * @brief Returns the number of elements matching a key (either 1 or 0).
- * @param key Key value of an element to search for.
- * @return Number of elements matching the key (either 1 or 0).
- */
- [[nodiscard]] size_type count(const key_type &key) const {
- return find(key) != end();
- }
- /**
- * @brief Returns the number of elements matching a key (either 1 or 0).
- * @tparam Other Type of the key value of an element to search for.
- * @param key Key value of an element to search for.
- * @return Number of elements matching the key (either 1 or 0).
- */
- template<typename Other>
- [[nodiscard]] std::enable_if_t<is_transparent_v<hasher> && is_transparent_v<key_equal>, std::conditional_t<false, Other, size_type>>
- count(const Other &key) const {
- return find(key) != end();
- }
- /**
- * @brief Finds an element with a given key.
- * @param key Key value of an element to search for.
- * @return An iterator to an element with the given key. If no such element
- * is found, a past-the-end iterator is returned.
- */
- [[nodiscard]] iterator find(const key_type &key) {
- return constrained_find(key, key_to_bucket(key));
- }
- /*! @copydoc find */
- [[nodiscard]] const_iterator find(const key_type &key) const {
- return constrained_find(key, key_to_bucket(key));
- }
- /**
- * @brief Finds an element with a key that compares _equivalent_ to a given
- * key.
- * @tparam Other Type of the key value of an element to search for.
- * @param key Key value of an element to search for.
- * @return An iterator to an element with the given key. If no such element
- * is found, a past-the-end iterator is returned.
- */
- template<typename Other>
- [[nodiscard]] std::enable_if_t<is_transparent_v<hasher> && is_transparent_v<key_equal>, std::conditional_t<false, Other, iterator>>
- find(const Other &key) {
- return constrained_find(key, key_to_bucket(key));
- }
- /*! @copydoc find */
- template<typename Other>
- [[nodiscard]] std::enable_if_t<is_transparent_v<hasher> && is_transparent_v<key_equal>, std::conditional_t<false, Other, const_iterator>>
- find(const Other &key) const {
- return constrained_find(key, key_to_bucket(key));
- }
- /**
- * @brief Returns a range containing all elements with a given key.
- * @param key Key value of an element to search for.
- * @return A pair of iterators pointing to the first element and past the
- * last element of the range.
- */
- [[nodiscard]] std::pair<iterator, iterator> equal_range(const key_type &key) {
- const auto it = find(key);
- return {it, it + !(it == end())};
- }
- /*! @copydoc equal_range */
- [[nodiscard]] std::pair<const_iterator, const_iterator> equal_range(const key_type &key) const {
- const auto it = find(key);
- return {it, it + !(it == cend())};
- }
- /**
- * @brief Returns a range containing all elements that compare _equivalent_
- * to a given key.
- * @tparam Other Type of an element to search for.
- * @param key Key value of an element to search for.
- * @return A pair of iterators pointing to the first element and past the
- * last element of the range.
- */
- template<typename Other>
- [[nodiscard]] std::enable_if_t<is_transparent_v<hasher> && is_transparent_v<key_equal>, std::conditional_t<false, Other, std::pair<iterator, iterator>>>
- equal_range(const Other &key) {
- const auto it = find(key);
- return {it, it + !(it == end())};
- }
- /*! @copydoc equal_range */
- template<typename Other>
- [[nodiscard]] std::enable_if_t<is_transparent_v<hasher> && is_transparent_v<key_equal>, std::conditional_t<false, Other, std::pair<const_iterator, const_iterator>>>
- equal_range(const Other &key) const {
- const auto it = find(key);
- return {it, it + !(it == cend())};
- }
- /**
- * @brief Checks if the container contains an element with a given key.
- * @param key Key value of an element to search for.
- * @return True if there is such an element, false otherwise.
- */
- [[nodiscard]] bool contains(const key_type &key) const {
- return (find(key) != cend());
- }
- /**
- * @brief Checks if the container contains an element with a key that
- * compares _equivalent_ to a given value.
- * @tparam Other Type of the key value of an element to search for.
- * @param key Key value of an element to search for.
- * @return True if there is such an element, false otherwise.
- */
- template<typename Other>
- [[nodiscard]] std::enable_if_t<is_transparent_v<hasher> && is_transparent_v<key_equal>, std::conditional_t<false, Other, bool>>
- contains(const Other &key) const {
- return (find(key) != cend());
- }
- /**
- * @brief Returns an iterator to the beginning of a given bucket.
- * @param index An index of a bucket to access.
- * @return An iterator to the beginning of the given bucket.
- */
- [[nodiscard]] const_local_iterator cbegin(const size_type index) const {
- return {packed.first().begin(), sparse.first()[index]};
- }
- /**
- * @brief Returns an iterator to the beginning of a given bucket.
- * @param index An index of a bucket to access.
- * @return An iterator to the beginning of the given bucket.
- */
- [[nodiscard]] const_local_iterator begin(const size_type index) const {
- return cbegin(index);
- }
- /**
- * @brief Returns an iterator to the beginning of a given bucket.
- * @param index An index of a bucket to access.
- * @return An iterator to the beginning of the given bucket.
- */
- [[nodiscard]] local_iterator begin(const size_type index) {
- return {packed.first().begin(), sparse.first()[index]};
- }
- /**
- * @brief Returns an iterator to the end of a given bucket.
- * @param index An index of a bucket to access.
- * @return An iterator to the end of the given bucket.
- */
- [[nodiscard]] const_local_iterator cend([[maybe_unused]] const size_type index) const {
- return {};
- }
- /**
- * @brief Returns an iterator to the end of a given bucket.
- * @param index An index of a bucket to access.
- * @return An iterator to the end of the given bucket.
- */
- [[nodiscard]] const_local_iterator end(const size_type index) const {
- return cend(index);
- }
- /**
- * @brief Returns an iterator to the end of a given bucket.
- * @param index An index of a bucket to access.
- * @return An iterator to the end of the given bucket.
- */
- [[nodiscard]] local_iterator end([[maybe_unused]] const size_type index) {
- return {};
- }
- /**
- * @brief Returns the number of buckets.
- * @return The number of buckets.
- */
- [[nodiscard]] size_type bucket_count() const {
- return sparse.first().size();
- }
- /**
- * @brief Returns the maximum number of buckets.
- * @return The maximum number of buckets.
- */
- [[nodiscard]] size_type max_bucket_count() const {
- return sparse.first().max_size();
- }
- /**
- * @brief Returns the number of elements in a given bucket.
- * @param index The index of the bucket to examine.
- * @return The number of elements in the given bucket.
- */
- [[nodiscard]] size_type bucket_size(const size_type index) const {
- return static_cast<size_type>(std::distance(begin(index), end(index)));
- }
- /**
- * @brief Returns the bucket for a given key.
- * @param key The value of the key to examine.
- * @return The bucket for the given key.
- */
- [[nodiscard]] size_type bucket(const key_type &key) const {
- return key_to_bucket(key);
- }
- /**
- * @brief Returns the average number of elements per bucket.
- * @return The average number of elements per bucket.
- */
- [[nodiscard]] float load_factor() const {
- return static_cast<float>(size()) / static_cast<float>(bucket_count());
- }
- /**
- * @brief Returns the maximum average number of elements per bucket.
- * @return The maximum average number of elements per bucket.
- */
- [[nodiscard]] float max_load_factor() const {
- return threshold;
- }
- /**
- * @brief Sets the desired maximum average number of elements per bucket.
- * @param value A desired maximum average number of elements per bucket.
- */
- void max_load_factor(const float value) {
- ENTT_ASSERT(value > 0.f, "Invalid load factor");
- threshold = value;
- rehash(0u);
- }
- /**
- * @brief Reserves at least the specified number of buckets and regenerates
- * the hash table.
- * @param cnt New number of buckets.
- */
- void rehash(const size_type cnt) {
- auto value = cnt > minimum_capacity ? cnt : minimum_capacity;
- const auto cap = static_cast<size_type>(static_cast<float>(size()) / max_load_factor());
- value = value > cap ? value : cap;
- if(const auto sz = next_power_of_two(value); sz != bucket_count()) {
- sparse.first().resize(sz);
- for(auto &&elem: sparse.first()) {
- elem = placeholder_position;
- }
- for(size_type pos{}, last = size(); pos < last; ++pos) {
- const auto index = key_to_bucket(packed.first()[pos].element.first);
- packed.first()[pos].next = std::exchange(sparse.first()[index], pos);
- }
- }
- }
- /**
- * @brief Reserves space for at least the specified number of elements and
- * regenerates the hash table.
- * @param cnt New number of elements.
- */
- void reserve(const size_type cnt) {
- packed.first().reserve(cnt);
- rehash(static_cast<size_type>(std::ceil(static_cast<float>(cnt) / max_load_factor())));
- }
- /**
- * @brief Returns the function used to hash the keys.
- * @return The function used to hash the keys.
- */
- [[nodiscard]] hasher hash_function() const {
- return sparse.second();
- }
- /**
- * @brief Returns the function used to compare keys for equality.
- * @return The function used to compare keys for equality.
- */
- [[nodiscard]] key_equal key_eq() const {
- return packed.second();
- }
- private:
- compressed_pair<sparse_container_type, hasher> sparse;
- compressed_pair<packed_container_type, key_equal> packed;
- float threshold{default_threshold};
- };
- } // namespace entt
- /*! @cond TURN_OFF_DOXYGEN */
- namespace std {
- template<typename Key, typename Value, typename Allocator>
- struct uses_allocator<entt::internal::dense_map_node<Key, Value>, Allocator>
- : std::true_type {};
- } // namespace std
- /*! @endcond */
- #endif
- // #include "container/dense_set.hpp"
- #ifndef ENTT_CONTAINER_DENSE_SET_HPP
- #define ENTT_CONTAINER_DENSE_SET_HPP
- #include <cmath>
- #include <cstddef>
- #include <functional>
- #include <iterator>
- #include <limits>
- #include <memory>
- #include <tuple>
- #include <type_traits>
- #include <utility>
- #include <vector>
- // #include "../config/config.h"
- // #include "../core/bit.hpp"
- // #include "../core/compressed_pair.hpp"
- // #include "../core/type_traits.hpp"
- // #include "fwd.hpp"
- namespace entt {
- /*! @cond TURN_OFF_DOXYGEN */
- namespace internal {
- static constexpr std::size_t dense_set_placeholder_position = (std::numeric_limits<std::size_t>::max)();
- template<typename It>
- class dense_set_iterator final {
- template<typename>
- friend class dense_set_iterator;
- public:
- using value_type = typename It::value_type::second_type;
- using pointer = const value_type *;
- using reference = const value_type &;
- using difference_type = std::ptrdiff_t;
- using iterator_category = std::random_access_iterator_tag;
- constexpr dense_set_iterator() noexcept
- : it{} {}
- constexpr dense_set_iterator(const It iter) noexcept
- : it{iter} {}
- template<typename Other, typename = std::enable_if_t<!std::is_same_v<It, Other> && std::is_constructible_v<It, Other>>>
- constexpr dense_set_iterator(const dense_set_iterator<Other> &other) noexcept
- : it{other.it} {}
- constexpr dense_set_iterator &operator++() noexcept {
- return ++it, *this;
- }
- constexpr dense_set_iterator operator++(int) noexcept {
- const dense_set_iterator orig = *this;
- return ++(*this), orig;
- }
- constexpr dense_set_iterator &operator--() noexcept {
- return --it, *this;
- }
- constexpr dense_set_iterator operator--(int) noexcept {
- const dense_set_iterator orig = *this;
- return operator--(), orig;
- }
- constexpr dense_set_iterator &operator+=(const difference_type value) noexcept {
- it += value;
- return *this;
- }
- constexpr dense_set_iterator operator+(const difference_type value) const noexcept {
- dense_set_iterator copy = *this;
- return (copy += value);
- }
- constexpr dense_set_iterator &operator-=(const difference_type value) noexcept {
- return (*this += -value);
- }
- constexpr dense_set_iterator operator-(const difference_type value) const noexcept {
- return (*this + -value);
- }
- [[nodiscard]] constexpr reference operator[](const difference_type value) const noexcept {
- return it[value].second;
- }
- [[nodiscard]] constexpr pointer operator->() const noexcept {
- return std::addressof(operator[](0));
- }
- [[nodiscard]] constexpr reference operator*() const noexcept {
- return operator[](0);
- }
- template<typename Lhs, typename Rhs>
- friend constexpr std::ptrdiff_t operator-(const dense_set_iterator<Lhs> &, const dense_set_iterator<Rhs> &) noexcept;
- template<typename Lhs, typename Rhs>
- friend constexpr bool operator==(const dense_set_iterator<Lhs> &, const dense_set_iterator<Rhs> &) noexcept;
- template<typename Lhs, typename Rhs>
- friend constexpr bool operator<(const dense_set_iterator<Lhs> &, const dense_set_iterator<Rhs> &) noexcept;
- private:
- It it;
- };
- template<typename Lhs, typename Rhs>
- [[nodiscard]] constexpr std::ptrdiff_t operator-(const dense_set_iterator<Lhs> &lhs, const dense_set_iterator<Rhs> &rhs) noexcept {
- return lhs.it - rhs.it;
- }
- template<typename Lhs, typename Rhs>
- [[nodiscard]] constexpr bool operator==(const dense_set_iterator<Lhs> &lhs, const dense_set_iterator<Rhs> &rhs) noexcept {
- return lhs.it == rhs.it;
- }
- template<typename Lhs, typename Rhs>
- [[nodiscard]] constexpr bool operator!=(const dense_set_iterator<Lhs> &lhs, const dense_set_iterator<Rhs> &rhs) noexcept {
- return !(lhs == rhs);
- }
- template<typename Lhs, typename Rhs>
- [[nodiscard]] constexpr bool operator<(const dense_set_iterator<Lhs> &lhs, const dense_set_iterator<Rhs> &rhs) noexcept {
- return lhs.it < rhs.it;
- }
- template<typename Lhs, typename Rhs>
- [[nodiscard]] constexpr bool operator>(const dense_set_iterator<Lhs> &lhs, const dense_set_iterator<Rhs> &rhs) noexcept {
- return rhs < lhs;
- }
- template<typename Lhs, typename Rhs>
- [[nodiscard]] constexpr bool operator<=(const dense_set_iterator<Lhs> &lhs, const dense_set_iterator<Rhs> &rhs) noexcept {
- return !(lhs > rhs);
- }
- template<typename Lhs, typename Rhs>
- [[nodiscard]] constexpr bool operator>=(const dense_set_iterator<Lhs> &lhs, const dense_set_iterator<Rhs> &rhs) noexcept {
- return !(lhs < rhs);
- }
- template<typename It>
- class dense_set_local_iterator final {
- template<typename>
- friend class dense_set_local_iterator;
- public:
- using value_type = typename It::value_type::second_type;
- using pointer = const value_type *;
- using reference = const value_type &;
- using difference_type = std::ptrdiff_t;
- using iterator_category = std::forward_iterator_tag;
- constexpr dense_set_local_iterator() noexcept = default;
- constexpr dense_set_local_iterator(It iter, const std::size_t pos) noexcept
- : it{iter},
- offset{pos} {}
- template<typename Other, typename = std::enable_if_t<!std::is_same_v<It, Other> && std::is_constructible_v<It, Other>>>
- constexpr dense_set_local_iterator(const dense_set_local_iterator<Other> &other) noexcept
- : it{other.it},
- offset{other.offset} {}
- constexpr dense_set_local_iterator &operator++() noexcept {
- return offset = it[static_cast<typename It::difference_type>(offset)].first, *this;
- }
- constexpr dense_set_local_iterator operator++(int) noexcept {
- const dense_set_local_iterator orig = *this;
- return ++(*this), orig;
- }
- [[nodiscard]] constexpr pointer operator->() const noexcept {
- return std::addressof(it[static_cast<typename It::difference_type>(offset)].second);
- }
- [[nodiscard]] constexpr reference operator*() const noexcept {
- return *operator->();
- }
- [[nodiscard]] constexpr std::size_t index() const noexcept {
- return offset;
- }
- private:
- It it{};
- std::size_t offset{dense_set_placeholder_position};
- };
- template<typename Lhs, typename Rhs>
- [[nodiscard]] constexpr bool operator==(const dense_set_local_iterator<Lhs> &lhs, const dense_set_local_iterator<Rhs> &rhs) noexcept {
- return lhs.index() == rhs.index();
- }
- template<typename Lhs, typename Rhs>
- [[nodiscard]] constexpr bool operator!=(const dense_set_local_iterator<Lhs> &lhs, const dense_set_local_iterator<Rhs> &rhs) noexcept {
- return !(lhs == rhs);
- }
- } // namespace internal
- /*! @endcond */
- /**
- * @brief Associative container for unique objects of a given type.
- *
- * Internally, elements are organized into buckets. Which bucket an element is
- * placed into depends entirely on its hash. Elements with the same hash code
- * appear in the same bucket.
- *
- * @tparam Type Value type of the associative container.
- * @tparam Hash Type of function to use to hash the values.
- * @tparam KeyEqual Type of function to use to compare the values for equality.
- * @tparam Allocator Type of allocator used to manage memory and elements.
- */
- template<typename Type, typename Hash, typename KeyEqual, typename Allocator>
- class dense_set {
- static constexpr float default_threshold = 0.875f;
- static constexpr std::size_t minimum_capacity = 8u;
- static constexpr std::size_t placeholder_position = internal::dense_set_placeholder_position;
- using node_type = std::pair<std::size_t, Type>;
- using alloc_traits = std::allocator_traits<Allocator>;
- static_assert(std::is_same_v<typename alloc_traits::value_type, Type>, "Invalid value type");
- using sparse_container_type = std::vector<std::size_t, typename alloc_traits::template rebind_alloc<std::size_t>>;
- using packed_container_type = std::vector<node_type, typename alloc_traits::template rebind_alloc<node_type>>;
- template<typename Other>
- [[nodiscard]] std::size_t value_to_bucket(const Other &value) const noexcept {
- return fast_mod(static_cast<size_type>(sparse.second()(value)), bucket_count());
- }
- template<typename Other>
- [[nodiscard]] auto constrained_find(const Other &value, const std::size_t bucket) {
- for(auto offset = sparse.first()[bucket]; offset != placeholder_position; offset = packed.first()[offset].first) {
- if(packed.second()(packed.first()[offset].second, value)) {
- return begin() + static_cast<typename iterator::difference_type>(offset);
- }
- }
- return end();
- }
- template<typename Other>
- [[nodiscard]] auto constrained_find(const Other &value, const std::size_t bucket) const {
- for(auto offset = sparse.first()[bucket]; offset != placeholder_position; offset = packed.first()[offset].first) {
- if(packed.second()(packed.first()[offset].second, value)) {
- return cbegin() + static_cast<typename const_iterator::difference_type>(offset);
- }
- }
- return cend();
- }
- template<typename Other>
- [[nodiscard]] auto insert_or_do_nothing(Other &&value) {
- const auto index = value_to_bucket(value);
- if(auto it = constrained_find(value, index); it != end()) {
- return std::make_pair(it, false);
- }
- packed.first().emplace_back(sparse.first()[index], std::forward<Other>(value));
- sparse.first()[index] = packed.first().size() - 1u;
- rehash_if_required();
- return std::make_pair(--end(), true);
- }
- void move_and_pop(const std::size_t pos) {
- if(const auto last = size() - 1u; pos != last) {
- size_type *curr = &sparse.first()[value_to_bucket(packed.first().back().second)];
- packed.first()[pos] = std::move(packed.first().back());
- for(; *curr != last; curr = &packed.first()[*curr].first) {}
- *curr = pos;
- }
- packed.first().pop_back();
- }
- void rehash_if_required() {
- if(const auto bc = bucket_count(); size() > static_cast<size_type>(static_cast<float>(bc) * max_load_factor())) {
- rehash(bc * 2u);
- }
- }
- public:
- /*! @brief Allocator type. */
- using allocator_type = Allocator;
- /*! @brief Key type of the container. */
- using key_type = Type;
- /*! @brief Value type of the container. */
- using value_type = Type;
- /*! @brief Unsigned integer type. */
- using size_type = std::size_t;
- /*! @brief Signed integer type. */
- using difference_type = std::ptrdiff_t;
- /*! @brief Type of function to use to hash the elements. */
- using hasher = Hash;
- /*! @brief Type of function to use to compare the elements for equality. */
- using key_equal = KeyEqual;
- /*! @brief Random access iterator type. */
- using iterator = internal::dense_set_iterator<typename packed_container_type::iterator>;
- /*! @brief Constant random access iterator type. */
- using const_iterator = internal::dense_set_iterator<typename packed_container_type::const_iterator>;
- /*! @brief Reverse iterator type. */
- using reverse_iterator = std::reverse_iterator<iterator>;
- /*! @brief Constant reverse iterator type. */
- using const_reverse_iterator = std::reverse_iterator<const_iterator>;
- /*! @brief Forward iterator type. */
- using local_iterator = internal::dense_set_local_iterator<typename packed_container_type::iterator>;
- /*! @brief Constant forward iterator type. */
- using const_local_iterator = internal::dense_set_local_iterator<typename packed_container_type::const_iterator>;
- /*! @brief Default constructor. */
- dense_set()
- : dense_set{minimum_capacity} {}
- /**
- * @brief Constructs an empty container with a given allocator.
- * @param allocator The allocator to use.
- */
- explicit dense_set(const allocator_type &allocator)
- : dense_set{minimum_capacity, hasher{}, key_equal{}, allocator} {}
- /**
- * @brief Constructs an empty container with a given allocator and user
- * supplied minimal number of buckets.
- * @param cnt Minimal number of buckets.
- * @param allocator The allocator to use.
- */
- dense_set(const size_type cnt, const allocator_type &allocator)
- : dense_set{cnt, hasher{}, key_equal{}, allocator} {}
- /**
- * @brief Constructs an empty container with a given allocator, hash
- * function and user supplied minimal number of buckets.
- * @param cnt Minimal number of buckets.
- * @param hash Hash function to use.
- * @param allocator The allocator to use.
- */
- dense_set(const size_type cnt, const hasher &hash, const allocator_type &allocator)
- : dense_set{cnt, hash, key_equal{}, allocator} {}
- /**
- * @brief Constructs an empty container with a given allocator, hash
- * function, compare function and user supplied minimal number of buckets.
- * @param cnt Minimal number of buckets.
- * @param hash Hash function to use.
- * @param equal Compare function to use.
- * @param allocator The allocator to use.
- */
- explicit dense_set(const size_type cnt, const hasher &hash = hasher{}, const key_equal &equal = key_equal{}, const allocator_type &allocator = allocator_type{})
- : sparse{allocator, hash},
- packed{allocator, equal} {
- rehash(cnt);
- }
- /*! @brief Default copy constructor. */
- dense_set(const dense_set &) = default;
- /**
- * @brief Allocator-extended copy constructor.
- * @param other The instance to copy from.
- * @param allocator The allocator to use.
- */
- dense_set(const dense_set &other, const allocator_type &allocator)
- : sparse{std::piecewise_construct, std::forward_as_tuple(other.sparse.first(), allocator), std::forward_as_tuple(other.sparse.second())},
- packed{std::piecewise_construct, std::forward_as_tuple(other.packed.first(), allocator), std::forward_as_tuple(other.packed.second())},
- threshold{other.threshold} {}
- /*! @brief Default move constructor. */
- dense_set(dense_set &&) noexcept = default;
- /**
- * @brief Allocator-extended move constructor.
- * @param other The instance to move from.
- * @param allocator The allocator to use.
- */
- dense_set(dense_set &&other, const allocator_type &allocator)
- : sparse{std::piecewise_construct, std::forward_as_tuple(std::move(other.sparse.first()), allocator), std::forward_as_tuple(std::move(other.sparse.second()))},
- packed{std::piecewise_construct, std::forward_as_tuple(std::move(other.packed.first()), allocator), std::forward_as_tuple(std::move(other.packed.second()))},
- threshold{other.threshold} {}
- /*! @brief Default destructor. */
- ~dense_set() = default;
- /**
- * @brief Default copy assignment operator.
- * @return This container.
- */
- dense_set &operator=(const dense_set &) = default;
- /**
- * @brief Default move assignment operator.
- * @return This container.
- */
- dense_set &operator=(dense_set &&) noexcept = default;
- /**
- * @brief Exchanges the contents with those of a given container.
- * @param other Container to exchange the content with.
- */
- void swap(dense_set &other) noexcept {
- using std::swap;
- swap(sparse, other.sparse);
- swap(packed, other.packed);
- swap(threshold, other.threshold);
- }
- /**
- * @brief Returns the associated allocator.
- * @return The associated allocator.
- */
- [[nodiscard]] constexpr allocator_type get_allocator() const noexcept {
- return sparse.first().get_allocator();
- }
- /**
- * @brief Returns an iterator to the beginning.
- *
- * If the array is empty, the returned iterator will be equal to `end()`.
- *
- * @return An iterator to the first instance of the internal array.
- */
- [[nodiscard]] const_iterator cbegin() const noexcept {
- return packed.first().begin();
- }
- /*! @copydoc cbegin */
- [[nodiscard]] const_iterator begin() const noexcept {
- return cbegin();
- }
- /*! @copydoc begin */
- [[nodiscard]] iterator begin() noexcept {
- return packed.first().begin();
- }
- /**
- * @brief Returns an iterator to the end.
- * @return An iterator to the element following the last instance of the
- * internal array.
- */
- [[nodiscard]] const_iterator cend() const noexcept {
- return packed.first().end();
- }
- /*! @copydoc cend */
- [[nodiscard]] const_iterator end() const noexcept {
- return cend();
- }
- /*! @copydoc end */
- [[nodiscard]] iterator end() noexcept {
- return packed.first().end();
- }
- /**
- * @brief Returns a reverse iterator to the beginning.
- *
- * If the array is empty, the returned iterator will be equal to `rend()`.
- *
- * @return An iterator to the first instance of the reversed internal array.
- */
- [[nodiscard]] const_reverse_iterator crbegin() const noexcept {
- return std::make_reverse_iterator(cend());
- }
- /*! @copydoc crbegin */
- [[nodiscard]] const_reverse_iterator rbegin() const noexcept {
- return crbegin();
- }
- /*! @copydoc rbegin */
- [[nodiscard]] reverse_iterator rbegin() noexcept {
- return std::make_reverse_iterator(end());
- }
- /**
- * @brief Returns a reverse iterator to the end.
- * @return An iterator to the element following the last instance of the
- * reversed internal array.
- */
- [[nodiscard]] const_reverse_iterator crend() const noexcept {
- return std::make_reverse_iterator(cbegin());
- }
- /*! @copydoc crend */
- [[nodiscard]] const_reverse_iterator rend() const noexcept {
- return crend();
- }
- /*! @copydoc rend */
- [[nodiscard]] reverse_iterator rend() noexcept {
- return std::make_reverse_iterator(begin());
- }
- /**
- * @brief Checks whether a container is empty.
- * @return True if the container is empty, false otherwise.
- */
- [[nodiscard]] bool empty() const noexcept {
- return packed.first().empty();
- }
- /**
- * @brief Returns the number of elements in a container.
- * @return Number of elements in a container.
- */
- [[nodiscard]] size_type size() const noexcept {
- return packed.first().size();
- }
- /**
- * @brief Returns the maximum possible number of elements.
- * @return Maximum possible number of elements.
- */
- [[nodiscard]] size_type max_size() const noexcept {
- return packed.first().max_size();
- }
- /*! @brief Clears the container. */
- void clear() noexcept {
- sparse.first().clear();
- packed.first().clear();
- rehash(0u);
- }
- /**
- * @brief Inserts an element into the container, if it does not exist.
- * @param value An element to insert into the container.
- * @return A pair consisting of an iterator to the inserted element (or to
- * the element that prevented the insertion) and a bool denoting whether the
- * insertion took place.
- */
- std::pair<iterator, bool> insert(const value_type &value) {
- return insert_or_do_nothing(value);
- }
- /*! @copydoc insert */
- std::pair<iterator, bool> insert(value_type &&value) {
- return insert_or_do_nothing(std::move(value));
- }
- /**
- * @brief Inserts elements into the container, if they do not exist.
- * @tparam It Type of input iterator.
- * @param first An iterator to the first element of the range of elements.
- * @param last An iterator past the last element of the range of elements.
- */
- template<typename It>
- void insert(It first, It last) {
- for(; first != last; ++first) {
- insert(*first);
- }
- }
- /**
- * @brief Constructs an element in-place, if it does not exist.
- *
- * The element is also constructed when the container already has the key,
- * in which case the newly constructed object is destroyed immediately.
- *
- * @tparam Args Types of arguments to forward to the constructor of the
- * element.
- * @param args Arguments to forward to the constructor of the element.
- * @return A pair consisting of an iterator to the inserted element (or to
- * the element that prevented the insertion) and a bool denoting whether the
- * insertion took place.
- */
- template<typename... Args>
- std::pair<iterator, bool> emplace(Args &&...args) {
- if constexpr(((sizeof...(Args) == 1u) && ... && std::is_same_v<std::decay_t<Args>, value_type>)) {
- return insert_or_do_nothing(std::forward<Args>(args)...);
- } else {
- auto &node = packed.first().emplace_back(std::piecewise_construct, std::make_tuple(packed.first().size()), std::forward_as_tuple(std::forward<Args>(args)...));
- const auto index = value_to_bucket(node.second);
- if(auto it = constrained_find(node.second, index); it != end()) {
- packed.first().pop_back();
- return std::make_pair(it, false);
- }
- std::swap(node.first, sparse.first()[index]);
- rehash_if_required();
- return std::make_pair(--end(), true);
- }
- }
- /**
- * @brief Removes an element from a given position.
- * @param pos An iterator to the element to remove.
- * @return An iterator following the removed element.
- */
- iterator erase(const_iterator pos) {
- const auto diff = pos - cbegin();
- erase(*pos);
- return begin() + diff;
- }
- /**
- * @brief Removes the given elements from a container.
- * @param first An iterator to the first element of the range of elements.
- * @param last An iterator past the last element of the range of elements.
- * @return An iterator following the last removed element.
- */
- iterator erase(const_iterator first, const_iterator last) {
- const auto dist = first - cbegin();
- for(auto from = last - cbegin(); from != dist; --from) {
- erase(packed.first()[static_cast<size_type>(from) - 1u].second);
- }
- return (begin() + dist);
- }
- /**
- * @brief Removes the element associated with a given value.
- * @param value Value of an element to remove.
- * @return Number of elements removed (either 0 or 1).
- */
- size_type erase(const value_type &value) {
- for(size_type *curr = &sparse.first()[value_to_bucket(value)]; *curr != placeholder_position; curr = &packed.first()[*curr].first) {
- if(packed.second()(packed.first()[*curr].second, value)) {
- const auto index = *curr;
- *curr = packed.first()[*curr].first;
- move_and_pop(index);
- return 1u;
- }
- }
- return 0u;
- }
- /**
- * @brief Returns the number of elements matching a value (either 1 or 0).
- * @param key Key value of an element to search for.
- * @return Number of elements matching the key (either 1 or 0).
- */
- [[nodiscard]] size_type count(const value_type &key) const {
- return find(key) != end();
- }
- /**
- * @brief Returns the number of elements matching a key (either 1 or 0).
- * @tparam Other Type of the key value of an element to search for.
- * @param key Key value of an element to search for.
- * @return Number of elements matching the key (either 1 or 0).
- */
- template<typename Other>
- [[nodiscard]] std::enable_if_t<is_transparent_v<hasher> && is_transparent_v<key_equal>, std::conditional_t<false, Other, size_type>>
- count(const Other &key) const {
- return find(key) != end();
- }
- /**
- * @brief Finds an element with a given value.
- * @param value Value of an element to search for.
- * @return An iterator to an element with the given value. If no such
- * element is found, a past-the-end iterator is returned.
- */
- [[nodiscard]] iterator find(const value_type &value) {
- return constrained_find(value, value_to_bucket(value));
- }
- /*! @copydoc find */
- [[nodiscard]] const_iterator find(const value_type &value) const {
- return constrained_find(value, value_to_bucket(value));
- }
- /**
- * @brief Finds an element that compares _equivalent_ to a given value.
- * @tparam Other Type of an element to search for.
- * @param value Value of an element to search for.
- * @return An iterator to an element with the given value. If no such
- * element is found, a past-the-end iterator is returned.
- */
- template<typename Other>
- [[nodiscard]] std::enable_if_t<is_transparent_v<hasher> && is_transparent_v<key_equal>, std::conditional_t<false, Other, iterator>>
- find(const Other &value) {
- return constrained_find(value, value_to_bucket(value));
- }
- /*! @copydoc find */
- template<typename Other>
- [[nodiscard]] std::enable_if_t<is_transparent_v<hasher> && is_transparent_v<key_equal>, std::conditional_t<false, Other, const_iterator>>
- find(const Other &value) const {
- return constrained_find(value, value_to_bucket(value));
- }
- /**
- * @brief Returns a range containing all elements with a given value.
- * @param value Value of an element to search for.
- * @return A pair of iterators pointing to the first element and past the
- * last element of the range.
- */
- [[nodiscard]] std::pair<iterator, iterator> equal_range(const value_type &value) {
- const auto it = find(value);
- return {it, it + !(it == end())};
- }
- /*! @copydoc equal_range */
- [[nodiscard]] std::pair<const_iterator, const_iterator> equal_range(const value_type &value) const {
- const auto it = find(value);
- return {it, it + !(it == cend())};
- }
- /**
- * @brief Returns a range containing all elements that compare _equivalent_
- * to a given value.
- * @tparam Other Type of an element to search for.
- * @param value Value of an element to search for.
- * @return A pair of iterators pointing to the first element and past the
- * last element of the range.
- */
- template<typename Other>
- [[nodiscard]] std::enable_if_t<is_transparent_v<hasher> && is_transparent_v<key_equal>, std::conditional_t<false, Other, std::pair<iterator, iterator>>>
- equal_range(const Other &value) {
- const auto it = find(value);
- return {it, it + !(it == end())};
- }
- /*! @copydoc equal_range */
- template<typename Other>
- [[nodiscard]] std::enable_if_t<is_transparent_v<hasher> && is_transparent_v<key_equal>, std::conditional_t<false, Other, std::pair<const_iterator, const_iterator>>>
- equal_range(const Other &value) const {
- const auto it = find(value);
- return {it, it + !(it == cend())};
- }
- /**
- * @brief Checks if the container contains an element with a given value.
- * @param value Value of an element to search for.
- * @return True if there is such an element, false otherwise.
- */
- [[nodiscard]] bool contains(const value_type &value) const {
- return (find(value) != cend());
- }
- /**
- * @brief Checks if the container contains an element that compares
- * _equivalent_ to a given value.
- * @tparam Other Type of an element to search for.
- * @param value Value of an element to search for.
- * @return True if there is such an element, false otherwise.
- */
- template<typename Other>
- [[nodiscard]] std::enable_if_t<is_transparent_v<hasher> && is_transparent_v<key_equal>, std::conditional_t<false, Other, bool>>
- contains(const Other &value) const {
- return (find(value) != cend());
- }
- /**
- * @brief Returns an iterator to the beginning of a given bucket.
- * @param index An index of a bucket to access.
- * @return An iterator to the beginning of the given bucket.
- */
- [[nodiscard]] const_local_iterator cbegin(const size_type index) const {
- return {packed.first().begin(), sparse.first()[index]};
- }
- /**
- * @brief Returns an iterator to the beginning of a given bucket.
- * @param index An index of a bucket to access.
- * @return An iterator to the beginning of the given bucket.
- */
- [[nodiscard]] const_local_iterator begin(const size_type index) const {
- return cbegin(index);
- }
- /**
- * @brief Returns an iterator to the beginning of a given bucket.
- * @param index An index of a bucket to access.
- * @return An iterator to the beginning of the given bucket.
- */
- [[nodiscard]] local_iterator begin(const size_type index) {
- return {packed.first().begin(), sparse.first()[index]};
- }
- /**
- * @brief Returns an iterator to the end of a given bucket.
- * @param index An index of a bucket to access.
- * @return An iterator to the end of the given bucket.
- */
- [[nodiscard]] const_local_iterator cend([[maybe_unused]] const size_type index) const {
- return {};
- }
- /**
- * @brief Returns an iterator to the end of a given bucket.
- * @param index An index of a bucket to access.
- * @return An iterator to the end of the given bucket.
- */
- [[nodiscard]] const_local_iterator end(const size_type index) const {
- return cend(index);
- }
- /**
- * @brief Returns an iterator to the end of a given bucket.
- * @param index An index of a bucket to access.
- * @return An iterator to the end of the given bucket.
- */
- [[nodiscard]] local_iterator end([[maybe_unused]] const size_type index) {
- return {};
- }
- /**
- * @brief Returns the number of buckets.
- * @return The number of buckets.
- */
- [[nodiscard]] size_type bucket_count() const {
- return sparse.first().size();
- }
- /**
- * @brief Returns the maximum number of buckets.
- * @return The maximum number of buckets.
- */
- [[nodiscard]] size_type max_bucket_count() const {
- return sparse.first().max_size();
- }
- /**
- * @brief Returns the number of elements in a given bucket.
- * @param index The index of the bucket to examine.
- * @return The number of elements in the given bucket.
- */
- [[nodiscard]] size_type bucket_size(const size_type index) const {
- return static_cast<size_type>(std::distance(begin(index), end(index)));
- }
- /**
- * @brief Returns the bucket for a given element.
- * @param value The value of the element to examine.
- * @return The bucket for the given element.
- */
- [[nodiscard]] size_type bucket(const value_type &value) const {
- return value_to_bucket(value);
- }
- /**
- * @brief Returns the average number of elements per bucket.
- * @return The average number of elements per bucket.
- */
- [[nodiscard]] float load_factor() const {
- return static_cast<float>(size()) / static_cast<float>(bucket_count());
- }
- /**
- * @brief Returns the maximum average number of elements per bucket.
- * @return The maximum average number of elements per bucket.
- */
- [[nodiscard]] float max_load_factor() const {
- return threshold;
- }
- /**
- * @brief Sets the desired maximum average number of elements per bucket.
- * @param value A desired maximum average number of elements per bucket.
- */
- void max_load_factor(const float value) {
- ENTT_ASSERT(value > 0.f, "Invalid load factor");
- threshold = value;
- rehash(0u);
- }
- /**
- * @brief Reserves at least the specified number of buckets and regenerates
- * the hash table.
- * @param cnt New number of buckets.
- */
- void rehash(const size_type cnt) {
- auto value = cnt > minimum_capacity ? cnt : minimum_capacity;
- const auto cap = static_cast<size_type>(static_cast<float>(size()) / max_load_factor());
- value = value > cap ? value : cap;
- if(const auto sz = next_power_of_two(value); sz != bucket_count()) {
- sparse.first().resize(sz);
- for(auto &&elem: sparse.first()) {
- elem = placeholder_position;
- }
- for(size_type pos{}, last = size(); pos < last; ++pos) {
- const auto index = value_to_bucket(packed.first()[pos].second);
- packed.first()[pos].first = std::exchange(sparse.first()[index], pos);
- }
- }
- }
- /**
- * @brief Reserves space for at least the specified number of elements and
- * regenerates the hash table.
- * @param cnt New number of elements.
- */
- void reserve(const size_type cnt) {
- packed.first().reserve(cnt);
- rehash(static_cast<size_type>(std::ceil(static_cast<float>(cnt) / max_load_factor())));
- }
- /**
- * @brief Returns the function used to hash the elements.
- * @return The function used to hash the elements.
- */
- [[nodiscard]] hasher hash_function() const {
- return sparse.second();
- }
- /**
- * @brief Returns the function used to compare elements for equality.
- * @return The function used to compare elements for equality.
- */
- [[nodiscard]] key_equal key_eq() const {
- return packed.second();
- }
- private:
- compressed_pair<sparse_container_type, hasher> sparse;
- compressed_pair<packed_container_type, key_equal> packed;
- float threshold{default_threshold};
- };
- } // namespace entt
- #endif
- // #include "container/table.hpp"
- #ifndef ENTT_CONTAINER_TABLE_HPP
- #define ENTT_CONTAINER_TABLE_HPP
- #include <cstddef>
- #include <iterator>
- #include <tuple>
- #include <type_traits>
- #include <utility>
- // #include "../config/config.h"
- // #include "../core/iterator.hpp"
- // #include "fwd.hpp"
- namespace entt {
- /*! @cond TURN_OFF_DOXYGEN */
- namespace internal {
- template<typename... It>
- class table_iterator {
- template<typename...>
- friend class table_iterator;
- public:
- using value_type = decltype(std::forward_as_tuple(*std::declval<It>()...));
- using pointer = input_iterator_pointer<value_type>;
- using reference = value_type;
- using difference_type = std::ptrdiff_t;
- using iterator_category = std::input_iterator_tag;
- using iterator_concept = std::random_access_iterator_tag;
- constexpr table_iterator() noexcept
- : it{} {}
- constexpr table_iterator(It... from) noexcept
- : it{from...} {}
- template<typename... Other, typename = std::enable_if_t<(std::is_constructible_v<It, Other> && ...)>>
- constexpr table_iterator(const table_iterator<Other...> &other) noexcept
- : table_iterator{std::get<Other>(other.it)...} {}
- constexpr table_iterator &operator++() noexcept {
- return (++std::get<It>(it), ...), *this;
- }
- constexpr table_iterator operator++(int) noexcept {
- const table_iterator orig = *this;
- return ++(*this), orig;
- }
- constexpr table_iterator &operator--() noexcept {
- return (--std::get<It>(it), ...), *this;
- }
- constexpr table_iterator operator--(int) noexcept {
- const table_iterator orig = *this;
- return operator--(), orig;
- }
- constexpr table_iterator &operator+=(const difference_type value) noexcept {
- return ((std::get<It>(it) += value), ...), *this;
- }
- constexpr table_iterator operator+(const difference_type value) const noexcept {
- table_iterator copy = *this;
- return (copy += value);
- }
- constexpr table_iterator &operator-=(const difference_type value) noexcept {
- return (*this += -value);
- }
- constexpr table_iterator operator-(const difference_type value) const noexcept {
- return (*this + -value);
- }
- [[nodiscard]] constexpr reference operator[](const difference_type value) const noexcept {
- return std::forward_as_tuple(std::get<It>(it)[value]...);
- }
- [[nodiscard]] constexpr pointer operator->() const noexcept {
- return {operator[](0)};
- }
- [[nodiscard]] constexpr reference operator*() const noexcept {
- return operator[](0);
- }
- template<typename... Lhs, typename... Rhs>
- friend constexpr std::ptrdiff_t operator-(const table_iterator<Lhs...> &, const table_iterator<Rhs...> &) noexcept;
- template<typename... Lhs, typename... Rhs>
- friend constexpr bool operator==(const table_iterator<Lhs...> &, const table_iterator<Rhs...> &) noexcept;
- template<typename... Lhs, typename... Rhs>
- friend constexpr bool operator<(const table_iterator<Lhs...> &, const table_iterator<Rhs...> &) noexcept;
- private:
- std::tuple<It...> it;
- };
- template<typename... Lhs, typename... Rhs>
- [[nodiscard]] constexpr std::ptrdiff_t operator-(const table_iterator<Lhs...> &lhs, const table_iterator<Rhs...> &rhs) noexcept {
- return std::get<0>(lhs.it) - std::get<0>(rhs.it);
- }
- template<typename... Lhs, typename... Rhs>
- [[nodiscard]] constexpr bool operator==(const table_iterator<Lhs...> &lhs, const table_iterator<Rhs...> &rhs) noexcept {
- return std::get<0>(lhs.it) == std::get<0>(rhs.it);
- }
- template<typename... Lhs, typename... Rhs>
- [[nodiscard]] constexpr bool operator!=(const table_iterator<Lhs...> &lhs, const table_iterator<Rhs...> &rhs) noexcept {
- return !(lhs == rhs);
- }
- template<typename... Lhs, typename... Rhs>
- [[nodiscard]] constexpr bool operator<(const table_iterator<Lhs...> &lhs, const table_iterator<Rhs...> &rhs) noexcept {
- return std::get<0>(lhs.it) < std::get<0>(rhs.it);
- }
- template<typename... Lhs, typename... Rhs>
- [[nodiscard]] constexpr bool operator>(const table_iterator<Lhs...> &lhs, const table_iterator<Rhs...> &rhs) noexcept {
- return rhs < lhs;
- }
- template<typename... Lhs, typename... Rhs>
- [[nodiscard]] constexpr bool operator<=(const table_iterator<Lhs...> &lhs, const table_iterator<Rhs...> &rhs) noexcept {
- return !(lhs > rhs);
- }
- template<typename... Lhs, typename... Rhs>
- [[nodiscard]] constexpr bool operator>=(const table_iterator<Lhs...> &lhs, const table_iterator<Rhs...> &rhs) noexcept {
- return !(lhs < rhs);
- }
- } // namespace internal
- /*! @endcond */
- /**
- * @brief Basic table implementation.
- *
- * Internal data structures arrange elements to maximize performance. There are
- * no guarantees that objects are returned in the insertion order when iterate
- * a table. Do not make assumption on the order in any case.
- *
- * @tparam Container Sequence container row types.
- */
- template<typename... Container>
- class basic_table {
- using container_type = std::tuple<Container...>;
- public:
- /*! @brief Unsigned integer type. */
- using size_type = std::size_t;
- /*! @brief Signed integer type. */
- using difference_type = std::ptrdiff_t;
- /*! @brief Input iterator type. */
- using iterator = internal::table_iterator<typename Container::iterator...>;
- /*! @brief Constant input iterator type. */
- using const_iterator = internal::table_iterator<typename Container::const_iterator...>;
- /*! @brief Reverse iterator type. */
- using reverse_iterator = internal::table_iterator<typename Container::reverse_iterator...>;
- /*! @brief Constant reverse iterator type. */
- using const_reverse_iterator = internal::table_iterator<typename Container::const_reverse_iterator...>;
- /*! @brief Default constructor. */
- basic_table()
- : payload{} {
- }
- /**
- * @brief Copy constructs the underlying containers.
- * @param container The containers to copy from.
- */
- explicit basic_table(const Container &...container) noexcept
- : payload{container...} {
- ENTT_ASSERT((((std::get<Container>(payload).size() * sizeof...(Container)) == (std::get<Container>(payload).size() + ...)) && ...), "Unexpected container size");
- }
- /**
- * @brief Move constructs the underlying containers.
- * @param container The containers to move from.
- */
- explicit basic_table(Container &&...container) noexcept
- : payload{std::move(container)...} {
- ENTT_ASSERT((((std::get<Container>(payload).size() * sizeof...(Container)) == (std::get<Container>(payload).size() + ...)) && ...), "Unexpected container size");
- }
- /*! @brief Default copy constructor, deleted on purpose. */
- basic_table(const basic_table &) = delete;
- /**
- * @brief Move constructor.
- * @param other The instance to move from.
- */
- basic_table(basic_table &&other) noexcept
- : payload{std::move(other.payload)} {}
- /**
- * @brief Constructs the underlying containers using a given allocator.
- * @tparam Allocator Type of allocator.
- * @param allocator A valid allocator.
- */
- template<typename Allocator>
- explicit basic_table(const Allocator &allocator)
- : payload{Container{allocator}...} {}
- /**
- * @brief Copy constructs the underlying containers using a given allocator.
- * @tparam Allocator Type of allocator.
- * @param container The containers to copy from.
- * @param allocator A valid allocator.
- */
- template<class Allocator>
- basic_table(const Container &...container, const Allocator &allocator) noexcept
- : payload{Container{container, allocator}...} {
- ENTT_ASSERT((((std::get<Container>(payload).size() * sizeof...(Container)) == (std::get<Container>(payload).size() + ...)) && ...), "Unexpected container size");
- }
- /**
- * @brief Move constructs the underlying containers using a given allocator.
- * @tparam Allocator Type of allocator.
- * @param container The containers to move from.
- * @param allocator A valid allocator.
- */
- template<class Allocator>
- basic_table(Container &&...container, const Allocator &allocator) noexcept
- : payload{Container{std::move(container), allocator}...} {
- ENTT_ASSERT((((std::get<Container>(payload).size() * sizeof...(Container)) == (std::get<Container>(payload).size() + ...)) && ...), "Unexpected container size");
- }
- /**
- * @brief Allocator-extended move constructor.
- * @tparam Allocator Type of allocator.
- * @param other The instance to move from.
- * @param allocator The allocator to use.
- */
- template<class Allocator>
- basic_table(basic_table &&other, const Allocator &allocator)
- : payload{Container{std::move(std::get<Container>(other.payload)), allocator}...} {}
- /*! @brief Default destructor. */
- ~basic_table() = default;
- /**
- * @brief Default copy assignment operator, deleted on purpose.
- * @return This container.
- */
- basic_table &operator=(const basic_table &) = delete;
- /**
- * @brief Move assignment operator.
- * @param other The instance to move from.
- * @return This container.
- */
- basic_table &operator=(basic_table &&other) noexcept {
- swap(other);
- return *this;
- }
- /**
- * @brief Exchanges the contents with those of a given table.
- * @param other Table to exchange the content with.
- */
- void swap(basic_table &other) noexcept {
- using std::swap;
- swap(payload, other.payload);
- }
- /**
- * @brief Increases the capacity of a table.
- *
- * If the new capacity is greater than the current capacity, new storage is
- * allocated, otherwise the method does nothing.
- *
- * @param cap Desired capacity.
- */
- void reserve(const size_type cap) {
- (std::get<Container>(payload).reserve(cap), ...);
- }
- /**
- * @brief Returns the number of rows that a table has currently allocated
- * space for.
- * @return Capacity of the table.
- */
- [[nodiscard]] size_type capacity() const noexcept {
- return std::get<0>(payload).capacity();
- }
- /*! @brief Requests the removal of unused capacity. */
- void shrink_to_fit() {
- (std::get<Container>(payload).shrink_to_fit(), ...);
- }
- /**
- * @brief Returns the number of rows in a table.
- * @return Number of rows.
- */
- [[nodiscard]] size_type size() const noexcept {
- return std::get<0>(payload).size();
- }
- /**
- * @brief Checks whether a table is empty.
- * @return True if the table is empty, false otherwise.
- */
- [[nodiscard]] bool empty() const noexcept {
- return std::get<0>(payload).empty();
- }
- /**
- * @brief Returns an iterator to the beginning.
- *
- * If the table is empty, the returned iterator will be equal to `end()`.
- *
- * @return An iterator to the first row of the table.
- */
- [[nodiscard]] const_iterator cbegin() const noexcept {
- return {std::get<Container>(payload).cbegin()...};
- }
- /*! @copydoc cbegin */
- [[nodiscard]] const_iterator begin() const noexcept {
- return cbegin();
- }
- /*! @copydoc begin */
- [[nodiscard]] iterator begin() noexcept {
- return {std::get<Container>(payload).begin()...};
- }
- /**
- * @brief Returns an iterator to the end.
- * @return An iterator to the element following the last row of the table.
- */
- [[nodiscard]] const_iterator cend() const noexcept {
- return {std::get<Container>(payload).cend()...};
- }
- /*! @copydoc cend */
- [[nodiscard]] const_iterator end() const noexcept {
- return cend();
- }
- /*! @copydoc end */
- [[nodiscard]] iterator end() noexcept {
- return {std::get<Container>(payload).end()...};
- }
- /**
- * @brief Returns a reverse iterator to the beginning.
- *
- * If the table is empty, the returned iterator will be equal to `rend()`.
- *
- * @return An iterator to the first row of the reversed table.
- */
- [[nodiscard]] const_reverse_iterator crbegin() const noexcept {
- return {std::get<Container>(payload).crbegin()...};
- }
- /*! @copydoc crbegin */
- [[nodiscard]] const_reverse_iterator rbegin() const noexcept {
- return crbegin();
- }
- /*! @copydoc rbegin */
- [[nodiscard]] reverse_iterator rbegin() noexcept {
- return {std::get<Container>(payload).rbegin()...};
- }
- /**
- * @brief Returns a reverse iterator to the end.
- * @return An iterator to the element following the last row of the reversed
- * table.
- */
- [[nodiscard]] const_reverse_iterator crend() const noexcept {
- return {std::get<Container>(payload).crend()...};
- }
- /*! @copydoc crend */
- [[nodiscard]] const_reverse_iterator rend() const noexcept {
- return crend();
- }
- /*! @copydoc rend */
- [[nodiscard]] reverse_iterator rend() noexcept {
- return {std::get<Container>(payload).rend()...};
- }
- /**
- * @brief Appends a row to the end of a table.
- * @tparam Args Types of arguments to use to construct the row data.
- * @param args Parameters to use to construct the row data.
- * @return A reference to the newly created row data.
- */
- template<typename... Args>
- std::tuple<typename Container::value_type &...> emplace(Args &&...args) {
- if constexpr(sizeof...(Args) == 0u) {
- return std::forward_as_tuple(std::get<Container>(payload).emplace_back()...);
- } else {
- return std::forward_as_tuple(std::get<Container>(payload).emplace_back(std::forward<Args>(args))...);
- }
- }
- /**
- * @brief Removes a row from a table.
- * @param pos An iterator to the row to remove.
- * @return An iterator following the removed row.
- */
- iterator erase(const_iterator pos) {
- const auto diff = pos - begin();
- return {std::get<Container>(payload).erase(std::get<Container>(payload).begin() + diff)...};
- }
- /**
- * @brief Removes a row from a table.
- * @param pos Index of the row to remove.
- */
- void erase(const size_type pos) {
- ENTT_ASSERT(pos < size(), "Index out of bounds");
- erase(begin() + static_cast<difference_type>(pos));
- }
- /**
- * @brief Returns the row data at specified location.
- * @param pos The row for which to return the data.
- * @return The row data at specified location.
- */
- [[nodiscard]] std::tuple<const typename Container::value_type &...> operator[](const size_type pos) const {
- ENTT_ASSERT(pos < size(), "Index out of bounds");
- return std::forward_as_tuple(std::get<Container>(payload)[pos]...);
- }
- /*! @copydoc operator[] */
- [[nodiscard]] std::tuple<typename Container::value_type &...> operator[](const size_type pos) {
- ENTT_ASSERT(pos < size(), "Index out of bounds");
- return std::forward_as_tuple(std::get<Container>(payload)[pos]...);
- }
- /*! @brief Clears a table. */
- void clear() {
- (std::get<Container>(payload).clear(), ...);
- }
- private:
- container_type payload;
- };
- } // namespace entt
- /*! @cond TURN_OFF_DOXYGEN */
- namespace std {
- template<typename... Container, typename Allocator>
- struct uses_allocator<entt::basic_table<Container...>, Allocator>
- : std::bool_constant<(std::uses_allocator_v<Container, Allocator> && ...)> {};
- } // namespace std
- /*! @endcond */
- #endif
- // #include "core/algorithm.hpp"
- #ifndef ENTT_CORE_ALGORITHM_HPP
- #define ENTT_CORE_ALGORITHM_HPP
- #include <algorithm>
- #include <functional>
- #include <iterator>
- #include <utility>
- #include <vector>
- // #include "utility.hpp"
- #ifndef ENTT_CORE_UTILITY_HPP
- #define ENTT_CORE_UTILITY_HPP
- #include <type_traits>
- #include <utility>
- namespace entt {
- /*! @brief Identity function object (waiting for C++20). */
- struct identity {
- /*! @brief Indicates that this is a transparent function object. */
- using is_transparent = void;
- /**
- * @brief Returns its argument unchanged.
- * @tparam Type Type of the argument.
- * @param value The actual argument.
- * @return The submitted value as-is.
- */
- template<typename Type>
- [[nodiscard]] constexpr Type &&operator()(Type &&value) const noexcept {
- return std::forward<Type>(value);
- }
- };
- /**
- * @brief Constant utility to disambiguate overloaded members of a class.
- * @tparam Type Type of the desired overload.
- * @tparam Class Type of class to which the member belongs.
- * @param member A valid pointer to a member.
- * @return Pointer to the member.
- */
- template<typename Type, typename Class>
- [[nodiscard]] constexpr auto overload(Type Class::*member) noexcept {
- return member;
- }
- /**
- * @brief Constant utility to disambiguate overloaded functions.
- * @tparam Func Function type of the desired overload.
- * @param func A valid pointer to a function.
- * @return Pointer to the function.
- */
- template<typename Func>
- [[nodiscard]] constexpr auto overload(Func *func) noexcept {
- return func;
- }
- /**
- * @brief Helper type for visitors.
- * @tparam Func Types of function objects.
- */
- template<typename... Func>
- struct overloaded: Func... {
- using Func::operator()...;
- };
- /**
- * @brief Deduction guide.
- * @tparam Func Types of function objects.
- */
- template<typename... Func>
- overloaded(Func...) -> overloaded<Func...>;
- /**
- * @brief Basic implementation of a y-combinator.
- * @tparam Func Type of a potentially recursive function.
- */
- template<typename Func>
- struct y_combinator {
- /**
- * @brief Constructs a y-combinator from a given function.
- * @param recursive A potentially recursive function.
- */
- constexpr y_combinator(Func recursive) noexcept(std::is_nothrow_move_constructible_v<Func>)
- : func{std::move(recursive)} {}
- /**
- * @brief Invokes a y-combinator and therefore its underlying function.
- * @tparam Args Types of arguments to use to invoke the underlying function.
- * @param args Parameters to use to invoke the underlying function.
- * @return Return value of the underlying function, if any.
- */
- template<typename... Args>
- constexpr decltype(auto) operator()(Args &&...args) const noexcept(std::is_nothrow_invocable_v<Func, const y_combinator &, Args...>) {
- return func(*this, std::forward<Args>(args)...);
- }
- /*! @copydoc operator()() */
- template<typename... Args>
- constexpr decltype(auto) operator()(Args &&...args) noexcept(std::is_nothrow_invocable_v<Func, y_combinator &, Args...>) {
- return func(*this, std::forward<Args>(args)...);
- }
- private:
- Func func;
- };
- } // namespace entt
- #endif
- namespace entt {
- /**
- * @brief Function object to wrap `std::sort` in a class type.
- *
- * Unfortunately, `std::sort` cannot be passed as template argument to a class
- * template or a function template.<br/>
- * This class fills the gap by wrapping some flavors of `std::sort` in a
- * function object.
- */
- struct std_sort {
- /**
- * @brief Sorts the elements in a range.
- *
- * Sorts the elements in a range using the given binary comparison function.
- *
- * @tparam It Type of random access iterator.
- * @tparam Compare Type of comparison function object.
- * @tparam Args Types of arguments to forward to the sort function.
- * @param first An iterator to the first element of the range to sort.
- * @param last An iterator past the last element of the range to sort.
- * @param compare A valid comparison function object.
- * @param args Arguments to forward to the sort function, if any.
- */
- template<typename It, typename Compare = std::less<>, typename... Args>
- void operator()(It first, It last, Compare compare = Compare{}, Args &&...args) const {
- std::sort(std::forward<Args>(args)..., std::move(first), std::move(last), std::move(compare));
- }
- };
- /*! @brief Function object for performing insertion sort. */
- struct insertion_sort {
- /**
- * @brief Sorts the elements in a range.
- *
- * Sorts the elements in a range using the given binary comparison function.
- *
- * @tparam It Type of random access iterator.
- * @tparam Compare Type of comparison function object.
- * @param first An iterator to the first element of the range to sort.
- * @param last An iterator past the last element of the range to sort.
- * @param compare A valid comparison function object.
- */
- template<typename It, typename Compare = std::less<>>
- void operator()(It first, It last, Compare compare = Compare{}) const {
- if(first < last) {
- for(auto it = first + 1; it < last; ++it) {
- auto value = std::move(*it);
- auto pre = it;
- // NOLINTBEGIN(cppcoreguidelines-pro-bounds-pointer-arithmetic)
- for(; pre > first && compare(value, *(pre - 1)); --pre) {
- *pre = std::move(*(pre - 1));
- }
- // NOLINTEND(cppcoreguidelines-pro-bounds-pointer-arithmetic)
- *pre = std::move(value);
- }
- }
- }
- };
- /**
- * @brief Function object for performing LSD radix sort.
- * @tparam Bit Number of bits processed per pass.
- * @tparam N Maximum number of bits to sort.
- */
- template<std::size_t Bit, std::size_t N>
- struct radix_sort {
- static_assert((N % Bit) == 0, "The maximum number of bits to sort must be a multiple of the number of bits processed per pass");
- /**
- * @brief Sorts the elements in a range.
- *
- * Sorts the elements in a range using the given _getter_ to access the
- * actual data to be sorted.
- *
- * This implementation is inspired by the online book
- * [Physically Based Rendering](http://www.pbr-book.org/3ed-2018/Primitives_and_Intersection_Acceleration/Bounding_Volume_Hierarchies.html#RadixSort).
- *
- * @tparam It Type of random access iterator.
- * @tparam Getter Type of _getter_ function object.
- * @param first An iterator to the first element of the range to sort.
- * @param last An iterator past the last element of the range to sort.
- * @param getter A valid _getter_ function object.
- */
- template<typename It, typename Getter = identity>
- void operator()(It first, It last, Getter getter = Getter{}) const {
- if(first < last) {
- constexpr auto passes = N / Bit;
- using value_type = typename std::iterator_traits<It>::value_type;
- using difference_type = typename std::iterator_traits<It>::difference_type;
- std::vector<value_type> aux(static_cast<std::size_t>(std::distance(first, last)));
- auto part = [getter = std::move(getter)](auto from, auto to, auto out, auto start) {
- constexpr auto mask = (1 << Bit) - 1;
- constexpr auto buckets = 1 << Bit;
- // NOLINTNEXTLINE(cppcoreguidelines-avoid-c-arrays, modernize-avoid-c-arrays, misc-const-correctness)
- std::size_t count[buckets]{};
- for(auto it = from; it != to; ++it) {
- ++count[(getter(*it) >> start) & mask];
- }
- // NOLINTNEXTLINE(cppcoreguidelines-avoid-c-arrays, modernize-avoid-c-arrays)
- std::size_t index[buckets]{};
- for(std::size_t pos{}, end = buckets - 1u; pos < end; ++pos) {
- index[pos + 1u] = index[pos] + count[pos];
- }
- for(auto it = from; it != to; ++it) {
- const auto pos = index[(getter(*it) >> start) & mask]++;
- out[static_cast<difference_type>(pos)] = std::move(*it);
- }
- };
- for(std::size_t pass = 0; pass < (passes & ~1u); pass += 2) {
- part(first, last, aux.begin(), pass * Bit);
- part(aux.begin(), aux.end(), first, (pass + 1) * Bit);
- }
- if constexpr(passes & 1) {
- part(first, last, aux.begin(), (passes - 1) * Bit);
- std::move(aux.begin(), aux.end(), first);
- }
- }
- }
- };
- } // namespace entt
- #endif
- // #include "core/any.hpp"
- #ifndef ENTT_CORE_ANY_HPP
- #define ENTT_CORE_ANY_HPP
- #include <cstddef>
- #include <memory>
- #include <type_traits>
- #include <utility>
- // #include "../config/config.h"
- #ifndef ENTT_CONFIG_CONFIG_H
- #define ENTT_CONFIG_CONFIG_H
- // #include "version.h"
- #ifndef ENTT_CONFIG_VERSION_H
- #define ENTT_CONFIG_VERSION_H
- // #include "macro.h"
- #ifndef ENTT_CONFIG_MACRO_H
- #define ENTT_CONFIG_MACRO_H
- // NOLINTBEGIN(cppcoreguidelines-macro-usage)
- #define ENTT_STR(arg) #arg
- #define ENTT_XSTR(arg) ENTT_STR(arg)
- // NOLINTEND(cppcoreguidelines-macro-usage)
- #endif
- // NOLINTBEGIN(cppcoreguidelines-macro-*,modernize-macro-*)
- #define ENTT_VERSION_MAJOR 3
- #define ENTT_VERSION_MINOR 16
- #define ENTT_VERSION_PATCH 0
- #define ENTT_VERSION \
- ENTT_XSTR(ENTT_VERSION_MAJOR) \
- "." ENTT_XSTR(ENTT_VERSION_MINOR) "." ENTT_XSTR(ENTT_VERSION_PATCH)
- // NOLINTEND(cppcoreguidelines-macro-*,modernize-macro-*)
- #endif
- // NOLINTBEGIN(cppcoreguidelines-macro-usage)
- #if defined(__cpp_exceptions) && !defined(ENTT_NOEXCEPTION)
- # define ENTT_CONSTEXPR
- # define ENTT_THROW throw
- # define ENTT_TRY try
- # define ENTT_CATCH catch(...)
- #else
- # define ENTT_CONSTEXPR constexpr // use only with throwing functions (waiting for C++20)
- # define ENTT_THROW
- # define ENTT_TRY if(true)
- # define ENTT_CATCH if(false)
- #endif
- #if __has_include(<version>)
- # include <version>
- #
- # if defined(__cpp_consteval)
- # define ENTT_CONSTEVAL consteval
- # endif
- #endif
- #ifndef ENTT_CONSTEVAL
- # define ENTT_CONSTEVAL constexpr
- #endif
- #ifdef ENTT_USE_ATOMIC
- # include <atomic>
- # define ENTT_MAYBE_ATOMIC(Type) std::atomic<Type>
- #else
- # define ENTT_MAYBE_ATOMIC(Type) Type
- #endif
- #ifndef ENTT_ID_TYPE
- # include <cstdint>
- # define ENTT_ID_TYPE std::uint32_t
- #else
- # include <cstdint> // provides coverage for types in the std namespace
- #endif
- #ifndef ENTT_SPARSE_PAGE
- # define ENTT_SPARSE_PAGE 4096
- #endif
- #ifndef ENTT_PACKED_PAGE
- # define ENTT_PACKED_PAGE 1024
- #endif
- #ifdef ENTT_DISABLE_ASSERT
- # undef ENTT_ASSERT
- # define ENTT_ASSERT(condition, msg) (void(0))
- #elif !defined ENTT_ASSERT
- # include <cassert>
- # define ENTT_ASSERT(condition, msg) assert(((condition) && (msg)))
- #endif
- #ifdef ENTT_DISABLE_ASSERT
- # undef ENTT_ASSERT_CONSTEXPR
- # define ENTT_ASSERT_CONSTEXPR(condition, msg) (void(0))
- #elif !defined ENTT_ASSERT_CONSTEXPR
- # define ENTT_ASSERT_CONSTEXPR(condition, msg) ENTT_ASSERT(condition, msg)
- #endif
- #define ENTT_FAIL(msg) ENTT_ASSERT(false, msg);
- #ifdef ENTT_NO_ETO
- # define ENTT_ETO_TYPE(Type) void
- #else
- # define ENTT_ETO_TYPE(Type) Type
- #endif
- #ifdef ENTT_NO_MIXIN
- # define ENTT_STORAGE(Mixin, ...) __VA_ARGS__
- #else
- # define ENTT_STORAGE(Mixin, ...) Mixin<__VA_ARGS__>
- #endif
- #ifdef ENTT_STANDARD_CPP
- # define ENTT_NONSTD false
- #else
- # define ENTT_NONSTD true
- # if defined __clang__ || defined __GNUC__
- # define ENTT_PRETTY_FUNCTION __PRETTY_FUNCTION__
- # define ENTT_PRETTY_FUNCTION_PREFIX '='
- # define ENTT_PRETTY_FUNCTION_SUFFIX ']'
- # elif defined _MSC_VER
- # define ENTT_PRETTY_FUNCTION __FUNCSIG__
- # define ENTT_PRETTY_FUNCTION_PREFIX '<'
- # define ENTT_PRETTY_FUNCTION_SUFFIX '>'
- # endif
- #endif
- #ifndef ENTT_EXPORT
- # if defined _WIN32 || defined __CYGWIN__ || defined _MSC_VER
- # define ENTT_EXPORT __declspec(dllexport)
- # define ENTT_IMPORT __declspec(dllimport)
- # define ENTT_HIDDEN
- # elif defined __GNUC__ && __GNUC__ >= 4
- # define ENTT_EXPORT __attribute__((visibility("default")))
- # define ENTT_IMPORT __attribute__((visibility("default")))
- # define ENTT_HIDDEN __attribute__((visibility("hidden")))
- # else /* Unsupported compiler */
- # define ENTT_EXPORT
- # define ENTT_IMPORT
- # define ENTT_HIDDEN
- # endif
- #endif
- #ifndef ENTT_API
- # if defined ENTT_API_EXPORT
- # define ENTT_API ENTT_EXPORT
- # elif defined ENTT_API_IMPORT
- # define ENTT_API ENTT_IMPORT
- # else /* No API */
- # define ENTT_API
- # endif
- #endif
- #if defined _MSC_VER
- # pragma detect_mismatch("entt.version", ENTT_VERSION)
- # pragma detect_mismatch("entt.noexcept", ENTT_XSTR(ENTT_TRY))
- # pragma detect_mismatch("entt.id", ENTT_XSTR(ENTT_ID_TYPE))
- # pragma detect_mismatch("entt.nonstd", ENTT_XSTR(ENTT_NONSTD))
- #endif
- // NOLINTEND(cppcoreguidelines-macro-usage)
- #endif
- // #include "fwd.hpp"
- #ifndef ENTT_CORE_FWD_HPP
- #define ENTT_CORE_FWD_HPP
- #include <cstddef>
- #include <cstdint>
- // #include "../config/config.h"
- namespace entt {
- /*! @brief Possible modes of an any object. */
- enum class any_policy : std::uint8_t {
- /*! @brief Default mode, no element available. */
- empty,
- /*! @brief Owning mode, dynamically allocated element. */
- dynamic,
- /*! @brief Owning mode, embedded element. */
- embedded,
- /*! @brief Aliasing mode, non-const reference. */
- ref,
- /*! @brief Const aliasing mode, const reference. */
- cref
- };
- // NOLINTNEXTLINE(cppcoreguidelines-avoid-c-arrays, modernize-avoid-c-arrays)
- template<std::size_t Len = sizeof(double[2]), std::size_t = alignof(double[2])>
- class basic_any;
- /*! @brief Alias declaration for type identifiers. */
- using id_type = ENTT_ID_TYPE;
- /*! @brief Alias declaration for the most common use case. */
- using any = basic_any<>;
- template<typename, typename>
- class compressed_pair;
- template<typename>
- class basic_hashed_string;
- /*! @brief Aliases for common character types. */
- using hashed_string = basic_hashed_string<char>;
- /*! @brief Aliases for common character types. */
- using hashed_wstring = basic_hashed_string<wchar_t>;
- // NOLINTNEXTLINE(bugprone-forward-declaration-namespace)
- struct type_info;
- } // namespace entt
- #endif
- // #include "type_info.hpp"
- #ifndef ENTT_CORE_TYPE_INFO_HPP
- #define ENTT_CORE_TYPE_INFO_HPP
- #include <string_view>
- #include <type_traits>
- #include <utility>
- // #include "../config/config.h"
- // #include "fwd.hpp"
- // #include "hashed_string.hpp"
- #ifndef ENTT_CORE_HASHED_STRING_HPP
- #define ENTT_CORE_HASHED_STRING_HPP
- #include <cstddef>
- #include <cstdint>
- // #include "fwd.hpp"
- namespace entt {
- /*! @cond TURN_OFF_DOXYGEN */
- namespace internal {
- template<typename = id_type>
- struct fnv_1a_params;
- template<>
- struct fnv_1a_params<std::uint32_t> {
- static constexpr auto offset = 2166136261;
- static constexpr auto prime = 16777619;
- };
- template<>
- struct fnv_1a_params<std::uint64_t> {
- static constexpr auto offset = 14695981039346656037ull;
- static constexpr auto prime = 1099511628211ull;
- };
- template<typename Char>
- struct basic_hashed_string {
- using value_type = Char;
- using size_type = std::size_t;
- using hash_type = id_type;
- const value_type *repr{};
- hash_type hash{fnv_1a_params<>::offset};
- size_type length{};
- };
- } // namespace internal
- /*! @endcond */
- /**
- * @brief Zero overhead unique identifier.
- *
- * A hashed string is a compile-time tool that allows users to use
- * human-readable identifiers in the codebase while using their numeric
- * counterparts at runtime.<br/>
- * Because of that, a hashed string can also be used in constant expressions if
- * required.
- *
- * @warning
- * This class doesn't take ownership of user-supplied strings nor does it make a
- * copy of them.
- *
- * @tparam Char Character type.
- */
- template<typename Char>
- class basic_hashed_string: internal::basic_hashed_string<Char> {
- using base_type = internal::basic_hashed_string<Char>;
- using params = internal::fnv_1a_params<>;
- struct const_wrapper {
- // non-explicit constructor on purpose
- constexpr const_wrapper(const typename base_type::value_type *str) noexcept
- : repr{str} {}
- const typename base_type::value_type *repr;
- };
- public:
- /*! @brief Character type. */
- using value_type = typename base_type::value_type;
- /*! @brief Unsigned integer type. */
- using size_type = typename base_type::size_type;
- /*! @brief Unsigned integer type. */
- using hash_type = typename base_type::hash_type;
- /**
- * @brief Returns directly the numeric representation of a string view.
- * @param str Human-readable identifier.
- * @param len Length of the string to hash.
- * @return The numeric representation of the string.
- */
- [[nodiscard]] static constexpr hash_type value(const value_type *str, const size_type len) noexcept {
- return basic_hashed_string{str, len};
- }
- /**
- * @brief Returns directly the numeric representation of a string.
- * @tparam N Number of characters of the identifier.
- * @param str Human-readable identifier.
- * @return The numeric representation of the string.
- */
- template<std::size_t N>
- // NOLINTNEXTLINE(cppcoreguidelines-avoid-c-arrays, modernize-avoid-c-arrays)
- [[nodiscard]] static ENTT_CONSTEVAL hash_type value(const value_type (&str)[N]) noexcept {
- return basic_hashed_string{str};
- }
- /**
- * @brief Returns directly the numeric representation of a string.
- * @param wrapper Helps achieving the purpose by relying on overloading.
- * @return The numeric representation of the string.
- */
- [[nodiscard]] static constexpr hash_type value(const_wrapper wrapper) noexcept {
- return basic_hashed_string{wrapper};
- }
- /*! @brief Constructs an empty hashed string. */
- constexpr basic_hashed_string() noexcept
- : basic_hashed_string{nullptr, 0u} {}
- /**
- * @brief Constructs a hashed string from a string view.
- * @param str Human-readable identifier.
- * @param len Length of the string to hash.
- */
- constexpr basic_hashed_string(const value_type *str, const size_type len) noexcept
- // NOLINTNEXTLINE(cppcoreguidelines-pro-bounds-array-to-pointer-decay)
- : base_type{str} {
- // NOLINTBEGIN(cppcoreguidelines-pro-bounds-pointer-arithmetic)
- for(; base_type::length < len; ++base_type::length) {
- base_type::hash = (base_type::hash ^ static_cast<id_type>(str[base_type::length])) * params::prime;
- }
- // NOLINTEND(cppcoreguidelines-pro-bounds-pointer-arithmetic)
- }
- /**
- * @brief Constructs a hashed string from an array of const characters.
- * @tparam N Number of characters of the identifier.
- * @param str Human-readable identifier.
- */
- template<std::size_t N>
- // NOLINTNEXTLINE(cppcoreguidelines-avoid-c-arrays, modernize-avoid-c-arrays)
- ENTT_CONSTEVAL basic_hashed_string(const value_type (&str)[N]) noexcept
- // NOLINTNEXTLINE(cppcoreguidelines-pro-bounds-array-to-pointer-decay)
- : base_type{str} {
- for(; str[base_type::length]; ++base_type::length) {
- base_type::hash = (base_type::hash ^ static_cast<id_type>(str[base_type::length])) * params::prime;
- }
- }
- /**
- * @brief Explicit constructor on purpose to avoid constructing a hashed
- * string directly from a `const value_type *`.
- *
- * @warning
- * The lifetime of the string is not extended nor is it copied.
- *
- * @param wrapper Helps achieving the purpose by relying on overloading.
- */
- explicit constexpr basic_hashed_string(const_wrapper wrapper) noexcept
- : base_type{wrapper.repr} {
- // NOLINTBEGIN(cppcoreguidelines-pro-bounds-pointer-arithmetic)
- for(; wrapper.repr[base_type::length]; ++base_type::length) {
- base_type::hash = (base_type::hash ^ static_cast<id_type>(wrapper.repr[base_type::length])) * params::prime;
- }
- // NOLINTEND(cppcoreguidelines-pro-bounds-pointer-arithmetic)
- }
- /**
- * @brief Returns the size of a hashed string.
- * @return The size of the hashed string.
- */
- [[nodiscard]] constexpr size_type size() const noexcept {
- return base_type::length;
- }
- /**
- * @brief Returns the human-readable representation of a hashed string.
- * @return The string used to initialize the hashed string.
- */
- [[nodiscard]] constexpr const value_type *data() const noexcept {
- return base_type::repr;
- }
- /**
- * @brief Returns the numeric representation of a hashed string.
- * @return The numeric representation of the hashed string.
- */
- [[nodiscard]] constexpr hash_type value() const noexcept {
- return base_type::hash;
- }
- /*! @copydoc data */
- [[nodiscard]] explicit constexpr operator const value_type *() const noexcept {
- return data();
- }
- /**
- * @brief Returns the numeric representation of a hashed string.
- * @return The numeric representation of the hashed string.
- */
- [[nodiscard]] constexpr operator hash_type() const noexcept {
- return value();
- }
- };
- /**
- * @brief Deduction guide.
- * @tparam Char Character type.
- * @param str Human-readable identifier.
- * @param len Length of the string to hash.
- */
- template<typename Char>
- basic_hashed_string(const Char *str, std::size_t len) -> basic_hashed_string<Char>;
- /**
- * @brief Deduction guide.
- * @tparam Char Character type.
- * @tparam N Number of characters of the identifier.
- * @param str Human-readable identifier.
- */
- template<typename Char, std::size_t N>
- // NOLINTNEXTLINE(cppcoreguidelines-avoid-c-arrays, modernize-avoid-c-arrays)
- basic_hashed_string(const Char (&str)[N]) -> basic_hashed_string<Char>;
- /**
- * @brief Compares two hashed strings.
- * @tparam Char Character type.
- * @param lhs A valid hashed string.
- * @param rhs A valid hashed string.
- * @return True if the two hashed strings are identical, false otherwise.
- */
- template<typename Char>
- [[nodiscard]] constexpr bool operator==(const basic_hashed_string<Char> &lhs, const basic_hashed_string<Char> &rhs) noexcept {
- return lhs.value() == rhs.value();
- }
- /**
- * @brief Compares two hashed strings.
- * @tparam Char Character type.
- * @param lhs A valid hashed string.
- * @param rhs A valid hashed string.
- * @return True if the two hashed strings differ, false otherwise.
- */
- template<typename Char>
- [[nodiscard]] constexpr bool operator!=(const basic_hashed_string<Char> &lhs, const basic_hashed_string<Char> &rhs) noexcept {
- return !(lhs == rhs);
- }
- /**
- * @brief Compares two hashed strings.
- * @tparam Char Character type.
- * @param lhs A valid hashed string.
- * @param rhs A valid hashed string.
- * @return True if the first element is less than the second, false otherwise.
- */
- template<typename Char>
- [[nodiscard]] constexpr bool operator<(const basic_hashed_string<Char> &lhs, const basic_hashed_string<Char> &rhs) noexcept {
- return lhs.value() < rhs.value();
- }
- /**
- * @brief Compares two hashed strings.
- * @tparam Char Character type.
- * @param lhs A valid hashed string.
- * @param rhs A valid hashed string.
- * @return True if the first element is less than or equal to the second, false
- * otherwise.
- */
- template<typename Char>
- [[nodiscard]] constexpr bool operator<=(const basic_hashed_string<Char> &lhs, const basic_hashed_string<Char> &rhs) noexcept {
- return !(rhs < lhs);
- }
- /**
- * @brief Compares two hashed strings.
- * @tparam Char Character type.
- * @param lhs A valid hashed string.
- * @param rhs A valid hashed string.
- * @return True if the first element is greater than the second, false
- * otherwise.
- */
- template<typename Char>
- [[nodiscard]] constexpr bool operator>(const basic_hashed_string<Char> &lhs, const basic_hashed_string<Char> &rhs) noexcept {
- return rhs < lhs;
- }
- /**
- * @brief Compares two hashed strings.
- * @tparam Char Character type.
- * @param lhs A valid hashed string.
- * @param rhs A valid hashed string.
- * @return True if the first element is greater than or equal to the second,
- * false otherwise.
- */
- template<typename Char>
- [[nodiscard]] constexpr bool operator>=(const basic_hashed_string<Char> &lhs, const basic_hashed_string<Char> &rhs) noexcept {
- return !(lhs < rhs);
- }
- inline namespace literals {
- /**
- * @brief User defined literal for hashed strings.
- * @param str The literal without its suffix.
- * @return A properly initialized hashed string.
- */
- [[nodiscard]] ENTT_CONSTEVAL hashed_string operator""_hs(const char *str, std::size_t) noexcept {
- return hashed_string{str};
- }
- /**
- * @brief User defined literal for hashed wstrings.
- * @param str The literal without its suffix.
- * @return A properly initialized hashed wstring.
- */
- [[nodiscard]] ENTT_CONSTEVAL hashed_wstring operator""_hws(const wchar_t *str, std::size_t) noexcept {
- return hashed_wstring{str};
- }
- } // namespace literals
- } // namespace entt
- #endif
- namespace entt {
- /*! @cond TURN_OFF_DOXYGEN */
- namespace internal {
- struct ENTT_API type_index final {
- [[nodiscard]] static id_type next() noexcept {
- static ENTT_MAYBE_ATOMIC(id_type) value{};
- return value++;
- }
- };
- template<typename Type>
- [[nodiscard]] constexpr const char *pretty_function() noexcept {
- #if defined ENTT_PRETTY_FUNCTION
- return static_cast<const char *>(ENTT_PRETTY_FUNCTION);
- #else
- return "";
- #endif
- }
- template<typename Type>
- [[nodiscard]] constexpr auto stripped_type_name() noexcept {
- #if defined ENTT_PRETTY_FUNCTION
- const std::string_view full_name{pretty_function<Type>()};
- auto first = full_name.find_first_not_of(' ', full_name.find_first_of(ENTT_PRETTY_FUNCTION_PREFIX) + 1);
- auto value = full_name.substr(first, full_name.find_last_of(ENTT_PRETTY_FUNCTION_SUFFIX) - first);
- return value;
- #else
- return std::string_view{};
- #endif
- }
- template<typename Type, auto = stripped_type_name<Type>().find_first_of('.')>
- [[nodiscard]] constexpr std::string_view type_name(int) noexcept {
- constexpr auto value = stripped_type_name<Type>();
- return value;
- }
- template<typename Type>
- [[nodiscard]] std::string_view type_name(char) noexcept {
- static const auto value = stripped_type_name<Type>();
- return value;
- }
- template<typename Type, auto = stripped_type_name<Type>().find_first_of('.')>
- [[nodiscard]] constexpr id_type type_hash(int) noexcept {
- constexpr auto stripped = stripped_type_name<Type>();
- constexpr auto value = hashed_string::value(stripped.data(), stripped.size());
- return value;
- }
- template<typename Type>
- [[nodiscard]] id_type type_hash(char) noexcept {
- static const auto value = [](const auto stripped) {
- return hashed_string::value(stripped.data(), stripped.size());
- }(stripped_type_name<Type>());
- return value;
- }
- } // namespace internal
- /*! @endcond */
- /**
- * @brief Type sequential identifier.
- * @tparam Type Type for which to generate a sequential identifier.
- */
- template<typename Type, typename = void>
- struct ENTT_API type_index final {
- /**
- * @brief Returns the sequential identifier of a given type.
- * @return The sequential identifier of a given type.
- */
- [[nodiscard]] static id_type value() noexcept {
- static const id_type value = internal::type_index::next();
- return value;
- }
- /*! @copydoc value */
- [[nodiscard]] constexpr operator id_type() const noexcept {
- return value();
- }
- };
- /**
- * @brief Type hash.
- * @tparam Type Type for which to generate a hash value.
- */
- template<typename Type, typename = void>
- struct type_hash final {
- /**
- * @brief Returns the numeric representation of a given type.
- * @return The numeric representation of the given type.
- */
- #if defined ENTT_PRETTY_FUNCTION
- [[nodiscard]] static constexpr id_type value() noexcept {
- return internal::type_hash<Type>(0);
- #else
- [[nodiscard]] static constexpr id_type value() noexcept {
- return type_index<Type>::value();
- #endif
- }
- /*! @copydoc value */
- [[nodiscard]] constexpr operator id_type() const noexcept {
- return value();
- }
- };
- /**
- * @brief Type name.
- * @tparam Type Type for which to generate a name.
- */
- template<typename Type, typename = void>
- struct type_name final {
- /**
- * @brief Returns the name of a given type.
- * @return The name of the given type.
- */
- [[nodiscard]] static constexpr std::string_view value() noexcept {
- return internal::type_name<Type>(0);
- }
- /*! @copydoc value */
- [[nodiscard]] constexpr operator std::string_view() const noexcept {
- return value();
- }
- };
- /*! @brief Implementation specific information about a type. */
- struct type_info final {
- /**
- * @brief Constructs a type info object for a given type.
- * @tparam Type Type for which to construct a type info object.
- */
- template<typename Type>
- // NOLINTBEGIN(modernize-use-transparent-functors)
- constexpr type_info(std::in_place_type_t<Type>) noexcept
- : seq{type_index<std::remove_const_t<std::remove_reference_t<Type>>>::value()},
- identifier{type_hash<std::remove_const_t<std::remove_reference_t<Type>>>::value()},
- alias{type_name<std::remove_const_t<std::remove_reference_t<Type>>>::value()} {}
- // NOLINTEND(modernize-use-transparent-functors)
- /**
- * @brief Type index.
- * @return Type index.
- */
- [[nodiscard]] constexpr id_type index() const noexcept {
- return seq;
- }
- /**
- * @brief Type hash.
- * @return Type hash.
- */
- [[nodiscard]] constexpr id_type hash() const noexcept {
- return identifier;
- }
- /**
- * @brief Type name.
- * @return Type name.
- */
- [[nodiscard]] constexpr std::string_view name() const noexcept {
- return alias;
- }
- private:
- id_type seq;
- id_type identifier;
- std::string_view alias;
- };
- /**
- * @brief Compares the contents of two type info objects.
- * @param lhs A type info object.
- * @param rhs A type info object.
- * @return True if the two type info objects are identical, false otherwise.
- */
- [[nodiscard]] constexpr bool operator==(const type_info &lhs, const type_info &rhs) noexcept {
- return lhs.hash() == rhs.hash();
- }
- /**
- * @brief Compares the contents of two type info objects.
- * @param lhs A type info object.
- * @param rhs A type info object.
- * @return True if the two type info objects differ, false otherwise.
- */
- [[nodiscard]] constexpr bool operator!=(const type_info &lhs, const type_info &rhs) noexcept {
- return !(lhs == rhs);
- }
- /**
- * @brief Compares two type info objects.
- * @param lhs A valid type info object.
- * @param rhs A valid type info object.
- * @return True if the first element is less than the second, false otherwise.
- */
- [[nodiscard]] constexpr bool operator<(const type_info &lhs, const type_info &rhs) noexcept {
- return lhs.index() < rhs.index();
- }
- /**
- * @brief Compares two type info objects.
- * @param lhs A valid type info object.
- * @param rhs A valid type info object.
- * @return True if the first element is less than or equal to the second, false
- * otherwise.
- */
- [[nodiscard]] constexpr bool operator<=(const type_info &lhs, const type_info &rhs) noexcept {
- return !(rhs < lhs);
- }
- /**
- * @brief Compares two type info objects.
- * @param lhs A valid type info object.
- * @param rhs A valid type info object.
- * @return True if the first element is greater than the second, false
- * otherwise.
- */
- [[nodiscard]] constexpr bool operator>(const type_info &lhs, const type_info &rhs) noexcept {
- return rhs < lhs;
- }
- /**
- * @brief Compares two type info objects.
- * @param lhs A valid type info object.
- * @param rhs A valid type info object.
- * @return True if the first element is greater than or equal to the second,
- * false otherwise.
- */
- [[nodiscard]] constexpr bool operator>=(const type_info &lhs, const type_info &rhs) noexcept {
- return !(lhs < rhs);
- }
- /**
- * @brief Returns the type info object associated to a given type.
- *
- * The returned element refers to an object with static storage duration.<br/>
- * The type doesn't need to be a complete type. If the type is a reference, the
- * result refers to the referenced type. In all cases, top-level cv-qualifiers
- * are ignored.
- *
- * @tparam Type Type for which to generate a type info object.
- * @return A reference to a properly initialized type info object.
- */
- template<typename Type>
- [[nodiscard]] const type_info &type_id() noexcept {
- if constexpr(std::is_same_v<Type, std::remove_const_t<std::remove_reference_t<Type>>>) {
- static const type_info instance{std::in_place_type<Type>};
- return instance;
- } else {
- return type_id<std::remove_const_t<std::remove_reference_t<Type>>>();
- }
- }
- /*! @copydoc type_id */
- template<typename Type>
- // NOLINTNEXTLINE(cppcoreguidelines-missing-std-forward)
- [[nodiscard]] const type_info &type_id(Type &&) noexcept {
- return type_id<std::remove_const_t<std::remove_reference_t<Type>>>();
- }
- } // namespace entt
- #endif
- // #include "type_traits.hpp"
- #ifndef ENTT_CORE_TYPE_TRAITS_HPP
- #define ENTT_CORE_TYPE_TRAITS_HPP
- #include <cstddef>
- #include <iterator>
- #include <tuple>
- #include <type_traits>
- #include <utility>
- // #include "../config/config.h"
- // #include "fwd.hpp"
- namespace entt {
- /**
- * @brief Utility class to disambiguate overloaded functions.
- * @tparam N Number of choices available.
- */
- template<std::size_t N>
- struct choice_t
- // unfortunately, doxygen cannot parse such a construct
- : /*! @cond TURN_OFF_DOXYGEN */ choice_t<N - 1> /*! @endcond */
- {};
- /*! @copybrief choice_t */
- template<>
- struct choice_t<0> {};
- /**
- * @brief Variable template for the choice trick.
- * @tparam N Number of choices available.
- */
- template<std::size_t N>
- inline constexpr choice_t<N> choice{};
- /**
- * @brief Identity type trait.
- *
- * Useful to establish non-deduced contexts in template argument deduction
- * (waiting for C++20) or to provide types through function arguments.
- *
- * @tparam Type A type.
- */
- template<typename Type>
- struct type_identity {
- /*! @brief Identity type. */
- using type = Type;
- };
- /**
- * @brief Helper type.
- * @tparam Type A type.
- */
- template<typename Type>
- using type_identity_t = typename type_identity<Type>::type;
- /**
- * @brief A type-only `sizeof` wrapper that returns 0 where `sizeof` complains.
- * @tparam Type The type of which to return the size.
- */
- template<typename Type, typename = void>
- struct size_of: std::integral_constant<std::size_t, 0u> {};
- /*! @copydoc size_of */
- template<typename Type>
- struct size_of<Type, std::void_t<decltype(sizeof(Type))>>
- // NOLINTNEXTLINE(bugprone-sizeof-expression)
- : std::integral_constant<std::size_t, sizeof(Type)> {};
- /**
- * @brief Helper variable template.
- * @tparam Type The type of which to return the size.
- */
- template<typename Type>
- inline constexpr std::size_t size_of_v = size_of<Type>::value;
- /**
- * @brief Using declaration to be used to _repeat_ the same type a number of
- * times equal to the size of a given parameter pack.
- * @tparam Type A type to repeat.
- */
- template<typename Type, typename>
- using unpack_as_type = Type;
- /**
- * @brief Helper variable template to be used to _repeat_ the same value a
- * number of times equal to the size of a given parameter pack.
- * @tparam Value A value to repeat.
- */
- template<auto Value, typename>
- inline constexpr auto unpack_as_value = Value;
- /**
- * @brief Wraps a static constant.
- * @tparam Value A static constant.
- */
- template<auto Value>
- using integral_constant = std::integral_constant<decltype(Value), Value>;
- /**
- * @brief Alias template to facilitate the creation of named values.
- * @tparam Value A constant value at least convertible to `id_type`.
- */
- template<id_type Value>
- using tag = integral_constant<Value>;
- /**
- * @brief A class to use to push around lists of types, nothing more.
- * @tparam Type Types provided by the type list.
- */
- template<typename... Type>
- struct type_list {
- /*! @brief Type list type. */
- using type = type_list;
- /*! @brief Compile-time number of elements in the type list. */
- static constexpr auto size = sizeof...(Type);
- };
- /*! @brief Primary template isn't defined on purpose. */
- template<std::size_t, typename>
- struct type_list_element;
- /**
- * @brief Provides compile-time indexed access to the types of a type list.
- * @tparam Index Index of the type to return.
- * @tparam First First type provided by the type list.
- * @tparam Other Other types provided by the type list.
- */
- template<std::size_t Index, typename First, typename... Other>
- struct type_list_element<Index, type_list<First, Other...>>
- : type_list_element<Index - 1u, type_list<Other...>> {};
- /**
- * @brief Provides compile-time indexed access to the types of a type list.
- * @tparam First First type provided by the type list.
- * @tparam Other Other types provided by the type list.
- */
- template<typename First, typename... Other>
- struct type_list_element<0u, type_list<First, Other...>> {
- /*! @brief Searched type. */
- using type = First;
- };
- /**
- * @brief Helper type.
- * @tparam Index Index of the type to return.
- * @tparam List Type list to search into.
- */
- template<std::size_t Index, typename List>
- using type_list_element_t = typename type_list_element<Index, List>::type;
- /*! @brief Primary template isn't defined on purpose. */
- template<typename, typename>
- struct type_list_index;
- /**
- * @brief Provides compile-time type access to the types of a type list.
- * @tparam Type Type to look for and for which to return the index.
- * @tparam First First type provided by the type list.
- * @tparam Other Other types provided by the type list.
- */
- template<typename Type, typename First, typename... Other>
- struct type_list_index<Type, type_list<First, Other...>> {
- /*! @brief Unsigned integer type. */
- using value_type = std::size_t;
- /*! @brief Compile-time position of the given type in the sublist. */
- static constexpr value_type value = 1u + type_list_index<Type, type_list<Other...>>::value;
- };
- /**
- * @brief Provides compile-time type access to the types of a type list.
- * @tparam Type Type to look for and for which to return the index.
- * @tparam Other Other types provided by the type list.
- */
- template<typename Type, typename... Other>
- struct type_list_index<Type, type_list<Type, Other...>> {
- static_assert(type_list_index<Type, type_list<Other...>>::value == sizeof...(Other), "Non-unique type");
- /*! @brief Unsigned integer type. */
- using value_type = std::size_t;
- /*! @brief Compile-time position of the given type in the sublist. */
- static constexpr value_type value = 0u;
- };
- /**
- * @brief Provides compile-time type access to the types of a type list.
- * @tparam Type Type to look for and for which to return the index.
- */
- template<typename Type>
- struct type_list_index<Type, type_list<>> {
- /*! @brief Unsigned integer type. */
- using value_type = std::size_t;
- /*! @brief Compile-time position of the given type in the sublist. */
- static constexpr value_type value = 0u;
- };
- /**
- * @brief Helper variable template.
- * @tparam List Type list.
- * @tparam Type Type to look for and for which to return the index.
- */
- template<typename Type, typename List>
- inline constexpr std::size_t type_list_index_v = type_list_index<Type, List>::value;
- /**
- * @brief Concatenates multiple type lists.
- * @tparam Type Types provided by the first type list.
- * @tparam Other Types provided by the second type list.
- * @return A type list composed by the types of both the type lists.
- */
- template<typename... Type, typename... Other>
- constexpr type_list<Type..., Other...> operator+(type_list<Type...>, type_list<Other...>) {
- return {};
- }
- /*! @brief Primary template isn't defined on purpose. */
- template<typename...>
- struct type_list_cat;
- /*! @brief Concatenates multiple type lists. */
- template<>
- struct type_list_cat<> {
- /*! @brief A type list composed by the types of all the type lists. */
- using type = type_list<>;
- };
- /**
- * @brief Concatenates multiple type lists.
- * @tparam Type Types provided by the first type list.
- * @tparam Other Types provided by the second type list.
- * @tparam List Other type lists, if any.
- */
- template<typename... Type, typename... Other, typename... List>
- struct type_list_cat<type_list<Type...>, type_list<Other...>, List...> {
- /*! @brief A type list composed by the types of all the type lists. */
- using type = typename type_list_cat<type_list<Type..., Other...>, List...>::type;
- };
- /**
- * @brief Concatenates multiple type lists.
- * @tparam Type Types provided by the type list.
- */
- template<typename... Type>
- struct type_list_cat<type_list<Type...>> {
- /*! @brief A type list composed by the types of all the type lists. */
- using type = type_list<Type...>;
- };
- /**
- * @brief Helper type.
- * @tparam List Type lists to concatenate.
- */
- template<typename... List>
- using type_list_cat_t = typename type_list_cat<List...>::type;
- /*! @cond TURN_OFF_DOXYGEN */
- namespace internal {
- template<typename...>
- struct type_list_unique;
- template<typename First, typename... Other, typename... Type>
- struct type_list_unique<type_list<First, Other...>, Type...>
- : std::conditional_t<(std::is_same_v<First, Type> || ...), type_list_unique<type_list<Other...>, Type...>, type_list_unique<type_list<Other...>, Type..., First>> {};
- template<typename... Type>
- struct type_list_unique<type_list<>, Type...> {
- using type = type_list<Type...>;
- };
- } // namespace internal
- /*! @endcond */
- /**
- * @brief Removes duplicates types from a type list.
- * @tparam List Type list.
- */
- template<typename List>
- struct type_list_unique {
- /*! @brief A type list without duplicate types. */
- using type = typename internal::type_list_unique<List>::type;
- };
- /**
- * @brief Helper type.
- * @tparam List Type list.
- */
- template<typename List>
- using type_list_unique_t = typename type_list_unique<List>::type;
- /**
- * @brief Provides the member constant `value` to true if a type list contains a
- * given type, false otherwise.
- * @tparam List Type list.
- * @tparam Type Type to look for.
- */
- template<typename List, typename Type>
- struct type_list_contains;
- /**
- * @copybrief type_list_contains
- * @tparam Type Types provided by the type list.
- * @tparam Other Type to look for.
- */
- template<typename... Type, typename Other>
- struct type_list_contains<type_list<Type...>, Other>
- : std::bool_constant<(std::is_same_v<Type, Other> || ...)> {};
- /**
- * @brief Helper variable template.
- * @tparam List Type list.
- * @tparam Type Type to look for.
- */
- template<typename List, typename Type>
- inline constexpr bool type_list_contains_v = type_list_contains<List, Type>::value;
- /*! @brief Primary template isn't defined on purpose. */
- template<typename...>
- struct type_list_diff;
- /**
- * @brief Computes the difference between two type lists.
- * @tparam Type Types provided by the first type list.
- * @tparam Other Types provided by the second type list.
- */
- template<typename... Type, typename... Other>
- struct type_list_diff<type_list<Type...>, type_list<Other...>> {
- /*! @brief A type list that is the difference between the two type lists. */
- using type = type_list_cat_t<std::conditional_t<type_list_contains_v<type_list<Other...>, Type>, type_list<>, type_list<Type>>...>;
- };
- /**
- * @brief Helper type.
- * @tparam List Type lists between which to compute the difference.
- */
- template<typename... List>
- using type_list_diff_t = typename type_list_diff<List...>::type;
- /*! @brief Primary template isn't defined on purpose. */
- template<typename, template<typename...> class>
- struct type_list_transform;
- /**
- * @brief Applies a given _function_ to a type list and generate a new list.
- * @tparam Type Types provided by the type list.
- * @tparam Op Unary operation as template class with a type member named `type`.
- */
- template<typename... Type, template<typename...> class Op>
- struct type_list_transform<type_list<Type...>, Op> {
- /*! @brief Resulting type list after applying the transform function. */
- // NOLINTNEXTLINE(modernize-type-traits)
- using type = type_list<typename Op<Type>::type...>;
- };
- /**
- * @brief Helper type.
- * @tparam List Type list.
- * @tparam Op Unary operation as template class with a type member named `type`.
- */
- template<typename List, template<typename...> class Op>
- using type_list_transform_t = typename type_list_transform<List, Op>::type;
- /**
- * @brief A class to use to push around lists of constant values, nothing more.
- * @tparam Value Values provided by the value list.
- */
- template<auto... Value>
- struct value_list {
- /*! @brief Value list type. */
- using type = value_list;
- /*! @brief Compile-time number of elements in the value list. */
- static constexpr auto size = sizeof...(Value);
- };
- /*! @brief Primary template isn't defined on purpose. */
- template<std::size_t, typename>
- struct value_list_element;
- /**
- * @brief Provides compile-time indexed access to the values of a value list.
- * @tparam Index Index of the value to return.
- * @tparam Value First value provided by the value list.
- * @tparam Other Other values provided by the value list.
- */
- template<std::size_t Index, auto Value, auto... Other>
- struct value_list_element<Index, value_list<Value, Other...>>
- : value_list_element<Index - 1u, value_list<Other...>> {};
- /**
- * @brief Provides compile-time indexed access to the types of a type list.
- * @tparam Value First value provided by the value list.
- * @tparam Other Other values provided by the value list.
- */
- template<auto Value, auto... Other>
- struct value_list_element<0u, value_list<Value, Other...>> {
- /*! @brief Searched type. */
- using type = decltype(Value);
- /*! @brief Searched value. */
- static constexpr auto value = Value;
- };
- /**
- * @brief Helper type.
- * @tparam Index Index of the type to return.
- * @tparam List Value list to search into.
- */
- template<std::size_t Index, typename List>
- using value_list_element_t = typename value_list_element<Index, List>::type;
- /**
- * @brief Helper type.
- * @tparam Index Index of the value to return.
- * @tparam List Value list to search into.
- */
- template<std::size_t Index, typename List>
- inline constexpr auto value_list_element_v = value_list_element<Index, List>::value;
- /*! @brief Primary template isn't defined on purpose. */
- template<auto, typename>
- struct value_list_index;
- /**
- * @brief Provides compile-time type access to the values of a value list.
- * @tparam Value Value to look for and for which to return the index.
- * @tparam First First value provided by the value list.
- * @tparam Other Other values provided by the value list.
- */
- template<auto Value, auto First, auto... Other>
- struct value_list_index<Value, value_list<First, Other...>> {
- /*! @brief Unsigned integer type. */
- using value_type = std::size_t;
- /*! @brief Compile-time position of the given value in the sublist. */
- static constexpr value_type value = 1u + value_list_index<Value, value_list<Other...>>::value;
- };
- /**
- * @brief Provides compile-time type access to the values of a value list.
- * @tparam Value Value to look for and for which to return the index.
- * @tparam Other Other values provided by the value list.
- */
- template<auto Value, auto... Other>
- struct value_list_index<Value, value_list<Value, Other...>> {
- static_assert(value_list_index<Value, value_list<Other...>>::value == sizeof...(Other), "Non-unique type");
- /*! @brief Unsigned integer type. */
- using value_type = std::size_t;
- /*! @brief Compile-time position of the given value in the sublist. */
- static constexpr value_type value = 0u;
- };
- /**
- * @brief Provides compile-time type access to the values of a value list.
- * @tparam Value Value to look for and for which to return the index.
- */
- template<auto Value>
- struct value_list_index<Value, value_list<>> {
- /*! @brief Unsigned integer type. */
- using value_type = std::size_t;
- /*! @brief Compile-time position of the given type in the sublist. */
- static constexpr value_type value = 0u;
- };
- /**
- * @brief Helper variable template.
- * @tparam List Value list.
- * @tparam Value Value to look for and for which to return the index.
- */
- template<auto Value, typename List>
- inline constexpr std::size_t value_list_index_v = value_list_index<Value, List>::value;
- /**
- * @brief Concatenates multiple value lists.
- * @tparam Value Values provided by the first value list.
- * @tparam Other Values provided by the second value list.
- * @return A value list composed by the values of both the value lists.
- */
- template<auto... Value, auto... Other>
- constexpr value_list<Value..., Other...> operator+(value_list<Value...>, value_list<Other...>) {
- return {};
- }
- /*! @brief Primary template isn't defined on purpose. */
- template<typename...>
- struct value_list_cat;
- /*! @brief Concatenates multiple value lists. */
- template<>
- struct value_list_cat<> {
- /*! @brief A value list composed by the values of all the value lists. */
- using type = value_list<>;
- };
- /**
- * @brief Concatenates multiple value lists.
- * @tparam Value Values provided by the first value list.
- * @tparam Other Values provided by the second value list.
- * @tparam List Other value lists, if any.
- */
- template<auto... Value, auto... Other, typename... List>
- struct value_list_cat<value_list<Value...>, value_list<Other...>, List...> {
- /*! @brief A value list composed by the values of all the value lists. */
- using type = typename value_list_cat<value_list<Value..., Other...>, List...>::type;
- };
- /**
- * @brief Concatenates multiple value lists.
- * @tparam Value Values provided by the value list.
- */
- template<auto... Value>
- struct value_list_cat<value_list<Value...>> {
- /*! @brief A value list composed by the values of all the value lists. */
- using type = value_list<Value...>;
- };
- /**
- * @brief Helper type.
- * @tparam List Value lists to concatenate.
- */
- template<typename... List>
- using value_list_cat_t = typename value_list_cat<List...>::type;
- /*! @brief Primary template isn't defined on purpose. */
- template<typename>
- struct value_list_unique;
- /**
- * @brief Removes duplicates values from a value list.
- * @tparam Value One of the values provided by the given value list.
- * @tparam Other The other values provided by the given value list.
- */
- template<auto Value, auto... Other>
- struct value_list_unique<value_list<Value, Other...>> {
- /*! @brief A value list without duplicate types. */
- using type = std::conditional_t<
- ((Value == Other) || ...),
- typename value_list_unique<value_list<Other...>>::type,
- value_list_cat_t<value_list<Value>, typename value_list_unique<value_list<Other...>>::type>>;
- };
- /*! @brief Removes duplicates values from a value list. */
- template<>
- struct value_list_unique<value_list<>> {
- /*! @brief A value list without duplicate types. */
- using type = value_list<>;
- };
- /**
- * @brief Helper type.
- * @tparam Type A value list.
- */
- template<typename Type>
- using value_list_unique_t = typename value_list_unique<Type>::type;
- /**
- * @brief Provides the member constant `value` to true if a value list contains
- * a given value, false otherwise.
- * @tparam List Value list.
- * @tparam Value Value to look for.
- */
- template<typename List, auto Value>
- struct value_list_contains;
- /**
- * @copybrief value_list_contains
- * @tparam Value Values provided by the value list.
- * @tparam Other Value to look for.
- */
- template<auto... Value, auto Other>
- struct value_list_contains<value_list<Value...>, Other>
- : std::bool_constant<((Value == Other) || ...)> {};
- /**
- * @brief Helper variable template.
- * @tparam List Value list.
- * @tparam Value Value to look for.
- */
- template<typename List, auto Value>
- inline constexpr bool value_list_contains_v = value_list_contains<List, Value>::value;
- /*! @brief Primary template isn't defined on purpose. */
- template<typename...>
- struct value_list_diff;
- /**
- * @brief Computes the difference between two value lists.
- * @tparam Value Values provided by the first value list.
- * @tparam Other Values provided by the second value list.
- */
- template<auto... Value, auto... Other>
- struct value_list_diff<value_list<Value...>, value_list<Other...>> {
- /*! @brief A value list that is the difference between the two value lists. */
- using type = value_list_cat_t<std::conditional_t<value_list_contains_v<value_list<Other...>, Value>, value_list<>, value_list<Value>>...>;
- };
- /**
- * @brief Helper type.
- * @tparam List Value lists between which to compute the difference.
- */
- template<typename... List>
- using value_list_diff_t = typename value_list_diff<List...>::type;
- /*! @brief Same as std::is_invocable, but with tuples. */
- template<typename, typename>
- struct is_applicable: std::false_type {};
- /**
- * @copybrief is_applicable
- * @tparam Func A valid function type.
- * @tparam Tuple Tuple-like type.
- * @tparam Args The list of arguments to use to probe the function type.
- */
- template<typename Func, template<typename...> class Tuple, typename... Args>
- struct is_applicable<Func, Tuple<Args...>>: std::is_invocable<Func, Args...> {};
- /**
- * @copybrief is_applicable
- * @tparam Func A valid function type.
- * @tparam Tuple Tuple-like type.
- * @tparam Args The list of arguments to use to probe the function type.
- */
- template<typename Func, template<typename...> class Tuple, typename... Args>
- struct is_applicable<Func, const Tuple<Args...>>: std::is_invocable<Func, Args...> {};
- /**
- * @brief Helper variable template.
- * @tparam Func A valid function type.
- * @tparam Args The list of arguments to use to probe the function type.
- */
- template<typename Func, typename Args>
- inline constexpr bool is_applicable_v = is_applicable<Func, Args>::value;
- /*! @brief Same as std::is_invocable_r, but with tuples for arguments. */
- template<typename, typename, typename>
- struct is_applicable_r: std::false_type {};
- /**
- * @copybrief is_applicable_r
- * @tparam Ret The type to which the return type of the function should be
- * convertible.
- * @tparam Func A valid function type.
- * @tparam Args The list of arguments to use to probe the function type.
- */
- template<typename Ret, typename Func, typename... Args>
- struct is_applicable_r<Ret, Func, std::tuple<Args...>>: std::is_invocable_r<Ret, Func, Args...> {};
- /**
- * @brief Helper variable template.
- * @tparam Ret The type to which the return type of the function should be
- * convertible.
- * @tparam Func A valid function type.
- * @tparam Args The list of arguments to use to probe the function type.
- */
- template<typename Ret, typename Func, typename Args>
- inline constexpr bool is_applicable_r_v = is_applicable_r<Ret, Func, Args>::value;
- /**
- * @brief Provides the member constant `value` to true if a given type is
- * complete, false otherwise.
- * @tparam Type The type to test.
- */
- template<typename Type, typename = void>
- struct is_complete: std::false_type {};
- /*! @copydoc is_complete */
- template<typename Type>
- struct is_complete<Type, std::void_t<decltype(sizeof(Type))>>: std::true_type {};
- /**
- * @brief Helper variable template.
- * @tparam Type The type to test.
- */
- template<typename Type>
- inline constexpr bool is_complete_v = is_complete<Type>::value;
- /**
- * @brief Provides the member constant `value` to true if a given type is an
- * iterator, false otherwise.
- * @tparam Type The type to test.
- */
- template<typename Type, typename = void>
- struct is_iterator: std::false_type {};
- /*! @cond TURN_OFF_DOXYGEN */
- namespace internal {
- template<typename, typename = void>
- struct has_iterator_category: std::false_type {};
- template<typename Type>
- struct has_iterator_category<Type, std::void_t<typename std::iterator_traits<Type>::iterator_category>>: std::true_type {};
- } // namespace internal
- /*! @endcond */
- /*! @copydoc is_iterator */
- template<typename Type>
- struct is_iterator<Type, std::enable_if_t<!std::is_void_v<std::remove_const_t<std::remove_pointer_t<Type>>>>>
- : internal::has_iterator_category<Type> {};
- /**
- * @brief Helper variable template.
- * @tparam Type The type to test.
- */
- template<typename Type>
- inline constexpr bool is_iterator_v = is_iterator<Type>::value;
- /**
- * @brief Provides the member constant `value` to true if a given type is both
- * an empty and non-final class, false otherwise.
- * @tparam Type The type to test
- */
- template<typename Type>
- struct is_ebco_eligible
- : std::bool_constant<std::is_empty_v<Type> && !std::is_final_v<Type>> {};
- /**
- * @brief Helper variable template.
- * @tparam Type The type to test.
- */
- template<typename Type>
- inline constexpr bool is_ebco_eligible_v = is_ebco_eligible<Type>::value;
- /**
- * @brief Provides the member constant `value` to true if `Type::is_transparent`
- * is valid and denotes a type, false otherwise.
- * @tparam Type The type to test.
- */
- template<typename Type, typename = void>
- struct is_transparent: std::false_type {};
- /*! @copydoc is_transparent */
- template<typename Type>
- struct is_transparent<Type, std::void_t<typename Type::is_transparent>>: std::true_type {};
- /**
- * @brief Helper variable template.
- * @tparam Type The type to test.
- */
- template<typename Type>
- inline constexpr bool is_transparent_v = is_transparent<Type>::value;
- /*! @cond TURN_OFF_DOXYGEN */
- namespace internal {
- template<typename, typename = void>
- struct has_tuple_size_value: std::false_type {};
- template<typename Type>
- struct has_tuple_size_value<Type, std::void_t<decltype(std::tuple_size<const Type>::value)>>: std::true_type {};
- template<typename, typename = void>
- struct has_value_type: std::false_type {};
- template<typename Type>
- struct has_value_type<Type, std::void_t<typename Type::value_type>>: std::true_type {};
- template<typename>
- [[nodiscard]] constexpr bool dispatch_is_equality_comparable();
- template<typename Type, std::size_t... Index>
- [[nodiscard]] constexpr bool unpack_maybe_equality_comparable(std::index_sequence<Index...>) {
- return (dispatch_is_equality_comparable<std::tuple_element_t<Index, Type>>() && ...);
- }
- template<typename>
- [[nodiscard]] constexpr bool maybe_equality_comparable(char) {
- return false;
- }
- template<typename Type>
- [[nodiscard]] constexpr auto maybe_equality_comparable(int) -> decltype(std::declval<Type>() == std::declval<Type>()) {
- return true;
- }
- template<typename Type>
- [[nodiscard]] constexpr bool dispatch_is_equality_comparable() {
- // NOLINTBEGIN(modernize-use-transparent-functors)
- if constexpr(std::is_array_v<Type>) {
- return false;
- } else if constexpr(is_complete_v<std::tuple_size<std::remove_const_t<Type>>>) {
- if constexpr(has_tuple_size_value<Type>::value) {
- return maybe_equality_comparable<Type>(0) && unpack_maybe_equality_comparable<Type>(std::make_index_sequence<std::tuple_size<Type>::value>{});
- } else {
- return maybe_equality_comparable<Type>(0);
- }
- } else if constexpr(has_value_type<Type>::value) {
- if constexpr(is_iterator_v<Type> || std::is_same_v<typename Type::value_type, Type> || dispatch_is_equality_comparable<typename Type::value_type>()) {
- return maybe_equality_comparable<Type>(0);
- } else {
- return false;
- }
- } else {
- return maybe_equality_comparable<Type>(0);
- }
- // NOLINTEND(modernize-use-transparent-functors)
- }
- } // namespace internal
- /*! @endcond */
- /**
- * @brief Provides the member constant `value` to true if a given type is
- * equality comparable, false otherwise.
- * @tparam Type The type to test.
- */
- template<typename Type>
- struct is_equality_comparable: std::bool_constant<internal::dispatch_is_equality_comparable<Type>()> {};
- /*! @copydoc is_equality_comparable */
- template<typename Type>
- struct is_equality_comparable<const Type>: is_equality_comparable<Type> {};
- /**
- * @brief Helper variable template.
- * @tparam Type The type to test.
- */
- template<typename Type>
- inline constexpr bool is_equality_comparable_v = is_equality_comparable<Type>::value;
- /**
- * @brief Transcribes the constness of a type to another type.
- * @tparam To The type to which to transcribe the constness.
- * @tparam From The type from which to transcribe the constness.
- */
- template<typename To, typename From>
- struct constness_as {
- /*! @brief The type resulting from the transcription of the constness. */
- using type = std::remove_const_t<To>;
- };
- /*! @copydoc constness_as */
- template<typename To, typename From>
- struct constness_as<To, const From> {
- /*! @brief The type resulting from the transcription of the constness. */
- using type = const To;
- };
- /**
- * @brief Alias template to facilitate the transcription of the constness.
- * @tparam To The type to which to transcribe the constness.
- * @tparam From The type from which to transcribe the constness.
- */
- template<typename To, typename From>
- using constness_as_t = typename constness_as<To, From>::type;
- /**
- * @brief Extracts the class of a non-static member object or function.
- * @tparam Member A pointer to a non-static member object or function.
- */
- template<typename Member>
- class member_class {
- static_assert(std::is_member_pointer_v<Member>, "Invalid pointer type to non-static member object or function");
- template<typename Class, typename Ret, typename... Args>
- static Class *clazz(Ret (Class::*)(Args...));
- template<typename Class, typename Ret, typename... Args>
- static Class *clazz(Ret (Class::*)(Args...) const);
- template<typename Class, typename Type>
- static Class *clazz(Type Class::*);
- public:
- /*! @brief The class of the given non-static member object or function. */
- using type = std::remove_pointer_t<decltype(clazz(std::declval<Member>()))>;
- };
- /**
- * @brief Helper type.
- * @tparam Member A pointer to a non-static member object or function.
- */
- template<typename Member>
- using member_class_t = typename member_class<Member>::type;
- /**
- * @brief Extracts the n-th argument of a _callable_ type.
- * @tparam Index The index of the argument to extract.
- * @tparam Candidate A valid _callable_ type.
- */
- template<std::size_t Index, typename Candidate>
- class nth_argument {
- template<typename Ret, typename... Args>
- static constexpr type_list<Args...> pick_up(Ret (*)(Args...));
- template<typename Ret, typename Class, typename... Args>
- static constexpr type_list<Args...> pick_up(Ret (Class ::*)(Args...));
- template<typename Ret, typename Class, typename... Args>
- static constexpr type_list<Args...> pick_up(Ret (Class ::*)(Args...) const);
- template<typename Type, typename Class>
- static constexpr type_list<Type> pick_up(Type Class ::*);
- template<typename Type>
- static constexpr decltype(pick_up(&Type::operator())) pick_up(Type &&);
- public:
- /*! @brief N-th argument of the _callable_ type. */
- using type = type_list_element_t<Index, decltype(pick_up(std::declval<Candidate>()))>;
- };
- /**
- * @brief Helper type.
- * @tparam Index The index of the argument to extract.
- * @tparam Candidate A valid function, member function or data member type.
- */
- template<std::size_t Index, typename Candidate>
- using nth_argument_t = typename nth_argument<Index, Candidate>::type;
- } // namespace entt
- template<typename... Type>
- struct std::tuple_size<entt::type_list<Type...>>: std::integral_constant<std::size_t, entt::type_list<Type...>::size> {};
- template<std::size_t Index, typename... Type>
- struct std::tuple_element<Index, entt::type_list<Type...>>: entt::type_list_element<Index, entt::type_list<Type...>> {};
- template<auto... Value>
- struct std::tuple_size<entt::value_list<Value...>>: std::integral_constant<std::size_t, entt::value_list<Value...>::size> {};
- template<std::size_t Index, auto... Value>
- struct std::tuple_element<Index, entt::value_list<Value...>>: entt::value_list_element<Index, entt::value_list<Value...>> {};
- #endif
- // #include "utility.hpp"
- namespace entt {
- /*! @cond TURN_OFF_DOXYGEN */
- namespace internal {
- enum class any_request : std::uint8_t {
- info,
- transfer,
- assign,
- compare,
- copy,
- move
- };
- template<std::size_t Len, std::size_t Align>
- struct basic_any_storage {
- static constexpr bool has_buffer = true;
- union {
- const void *instance{};
- // NOLINTNEXTLINE(cppcoreguidelines-avoid-c-arrays, modernize-avoid-c-arrays)
- alignas(Align) std::byte buffer[Len];
- };
- };
- template<std::size_t Align>
- struct basic_any_storage<0u, Align> {
- static constexpr bool has_buffer = false;
- const void *instance{};
- };
- template<typename Type, std::size_t Len, std::size_t Align>
- // NOLINTNEXTLINE(bugprone-sizeof-expression)
- struct in_situ: std::bool_constant<(Len != 0u) && alignof(Type) <= Align && sizeof(Type) <= Len && std::is_nothrow_move_constructible_v<Type>> {};
- template<std::size_t Len, std::size_t Align>
- struct in_situ<void, Len, Align>: std::false_type {};
- } // namespace internal
- /*! @endcond */
- /**
- * @brief A SBO friendly, type-safe container for single values of any type.
- * @tparam Len Size of the buffer reserved for the small buffer optimization.
- * @tparam Align Optional alignment requirement.
- */
- template<std::size_t Len, std::size_t Align>
- class basic_any: private internal::basic_any_storage<Len, Align> {
- using request = internal::any_request;
- using base_type = internal::basic_any_storage<Len, Align>;
- using vtable_type = const void *(const request, const basic_any &, const void *);
- using deleter_type = void(const basic_any &);
- template<typename Type>
- static constexpr bool in_situ_v = internal::in_situ<Type, Len, Align>::value;
- template<typename Type>
- static const void *basic_vtable(const request req, const basic_any &value, const void *other) {
- static_assert(std::is_same_v<std::remove_const_t<std::remove_reference_t<Type>>, Type>, "Invalid type");
- switch(const auto *elem = static_cast<const Type *>(value.data()); req) {
- case request::info:
- return &type_id<Type>();
- case request::transfer:
- if constexpr(std::is_move_assignable_v<Type>) {
- // NOLINTNEXTLINE(bugprone-casting-through-void)
- *const_cast<Type *>(elem) = std::move(*static_cast<Type *>(const_cast<void *>(other)));
- return other;
- }
- [[fallthrough]];
- case request::assign:
- if constexpr(std::is_copy_assignable_v<Type>) {
- *const_cast<Type *>(elem) = *static_cast<const Type *>(other);
- return other;
- }
- break;
- case request::compare:
- if constexpr(!std::is_function_v<Type> && !std::is_array_v<Type> && is_equality_comparable_v<Type>) {
- return (*elem == *static_cast<const Type *>(other)) ? other : nullptr;
- } else {
- return (elem == other) ? other : nullptr;
- }
- case request::copy:
- if constexpr(std::is_copy_constructible_v<Type>) {
- // NOLINTNEXTLINE(bugprone-casting-through-void)
- static_cast<basic_any *>(const_cast<void *>(other))->initialize<Type>(*elem);
- }
- break;
- case request::move:
- ENTT_ASSERT(value.mode == any_policy::embedded, "Unexpected policy");
- if constexpr(in_situ_v<Type>) {
- // NOLINTNEXTLINE(bugprone-casting-through-void, bugprone-multi-level-implicit-pointer-conversion)
- return ::new(&static_cast<basic_any *>(const_cast<void *>(other))->buffer) Type{std::move(*const_cast<Type *>(elem))};
- }
- }
- return nullptr;
- }
- template<typename Type>
- static void basic_deleter(const basic_any &value) {
- static_assert(std::is_same_v<std::remove_const_t<std::remove_reference_t<Type>>, Type>, "Invalid type");
- ENTT_ASSERT((value.mode == any_policy::dynamic) || ((value.mode == any_policy::embedded) && !std::is_trivially_destructible_v<Type>), "Unexpected policy");
- const auto *elem = static_cast<const Type *>(value.data());
- if constexpr(in_situ_v<Type>) {
- (value.mode == any_policy::embedded) ? elem->~Type() : (delete elem);
- } else if constexpr(std::is_array_v<Type>) {
- delete[] elem;
- } else {
- delete elem;
- }
- }
- template<typename Type, typename... Args>
- void initialize([[maybe_unused]] Args &&...args) {
- using plain_type = std::remove_const_t<std::remove_reference_t<Type>>;
- vtable = basic_vtable<plain_type>;
- underlying_type = type_hash<plain_type>::value();
- if constexpr(std::is_void_v<Type>) {
- deleter = nullptr;
- mode = any_policy::empty;
- this->instance = nullptr;
- } else if constexpr(std::is_lvalue_reference_v<Type>) {
- deleter = nullptr;
- mode = std::is_const_v<std::remove_reference_t<Type>> ? any_policy::cref : any_policy::ref;
- static_assert((std::is_lvalue_reference_v<Args> && ...) && (sizeof...(Args) == 1u), "Invalid arguments");
- // NOLINTNEXTLINE(bugprone-multi-level-implicit-pointer-conversion)
- this->instance = (std::addressof(args), ...);
- } else if constexpr(in_situ_v<plain_type>) {
- if constexpr(std::is_trivially_destructible_v<plain_type>) {
- deleter = nullptr;
- } else {
- deleter = &basic_deleter<plain_type>;
- }
- mode = any_policy::embedded;
- if constexpr(std::is_aggregate_v<plain_type> && (sizeof...(Args) != 0u || !std::is_default_constructible_v<plain_type>)) {
- ::new(&this->buffer) plain_type{std::forward<Args>(args)...};
- } else {
- // NOLINTNEXTLINE(cppcoreguidelines-pro-bounds-array-to-pointer-decay)
- ::new(&this->buffer) plain_type(std::forward<Args>(args)...);
- }
- } else {
- deleter = &basic_deleter<plain_type>;
- mode = any_policy::dynamic;
- if constexpr(std::is_aggregate_v<plain_type> && (sizeof...(Args) != 0u || !std::is_default_constructible_v<plain_type>)) {
- this->instance = new plain_type{std::forward<Args>(args)...};
- } else if constexpr(std::is_array_v<plain_type>) {
- static_assert(sizeof...(Args) == 0u, "Invalid arguments");
- this->instance = new plain_type[std::extent_v<plain_type>]();
- } else {
- this->instance = new plain_type(std::forward<Args>(args)...);
- }
- }
- }
- void invoke_deleter_if_exists() {
- if(deleter != nullptr) {
- deleter(*this);
- }
- }
- public:
- /*! @brief Size of the internal buffer. */
- static constexpr auto length = Len;
- /*! @brief Alignment requirement. */
- static constexpr auto alignment = Align;
- /*! @brief Default constructor. */
- constexpr basic_any() noexcept
- : basic_any{std::in_place_type<void>} {}
- /**
- * @brief Constructs a wrapper by directly initializing the new object.
- * @tparam Type Type of object to use to initialize the wrapper.
- * @tparam Args Types of arguments to use to construct the new instance.
- * @param args Parameters to use to construct the instance.
- */
- template<typename Type, typename... Args>
- explicit basic_any(std::in_place_type_t<Type>, Args &&...args)
- : base_type{} {
- initialize<Type>(std::forward<Args>(args)...);
- }
- /**
- * @brief Constructs a wrapper taking ownership of the passed object.
- * @tparam Type Type of object to use to initialize the wrapper.
- * @param value A pointer to an object to take ownership of.
- */
- template<typename Type>
- explicit basic_any(std::in_place_t, Type *value)
- : base_type{} {
- static_assert(!std::is_const_v<Type> && !std::is_void_v<Type>, "Non-const non-void pointer required");
- if(value == nullptr) {
- initialize<void>();
- } else {
- initialize<Type &>(*value);
- deleter = &basic_deleter<Type>;
- mode = any_policy::dynamic;
- }
- }
- /**
- * @brief Constructs a wrapper from a given value.
- * @tparam Type Type of object to use to initialize the wrapper.
- * @param value An instance of an object to use to initialize the wrapper.
- */
- template<typename Type, typename = std::enable_if_t<!std::is_same_v<std::decay_t<Type>, basic_any>>>
- basic_any(Type &&value)
- : basic_any{std::in_place_type<std::decay_t<Type>>, std::forward<Type>(value)} {}
- /**
- * @brief Copy constructor.
- * @param other The instance to copy from.
- */
- basic_any(const basic_any &other)
- : basic_any{} {
- other.vtable(request::copy, other, this);
- }
- /**
- * @brief Move constructor.
- * @param other The instance to move from.
- */
- basic_any(basic_any &&other) noexcept
- : base_type{},
- vtable{other.vtable},
- deleter{other.deleter},
- underlying_type{other.underlying_type},
- mode{other.mode} {
- if(other.mode == any_policy::embedded) {
- other.vtable(request::move, other, this);
- } else if(other.mode != any_policy::empty) {
- this->instance = std::exchange(other.instance, nullptr);
- }
- }
- /*! @brief Frees the internal buffer, whatever it means. */
- ~basic_any() {
- invoke_deleter_if_exists();
- }
- /**
- * @brief Copy assignment operator.
- * @param other The instance to copy from.
- * @return This any object.
- */
- basic_any &operator=(const basic_any &other) {
- if(this != &other) {
- invoke_deleter_if_exists();
- if(other) {
- other.vtable(request::copy, other, this);
- } else {
- initialize<void>();
- }
- }
- return *this;
- }
- /**
- * @brief Move assignment operator.
- * @param other The instance to move from.
- * @return This any object.
- */
- basic_any &operator=(basic_any &&other) noexcept {
- if(this != &other) {
- invoke_deleter_if_exists();
- if(other.mode == any_policy::embedded) {
- other.vtable(request::move, other, this);
- } else if(other.mode != any_policy::empty) {
- this->instance = std::exchange(other.instance, nullptr);
- }
- vtable = other.vtable;
- deleter = other.deleter;
- underlying_type = other.underlying_type;
- mode = other.mode;
- }
- return *this;
- }
- /**
- * @brief Value assignment operator.
- * @tparam Type Type of object to use to initialize the wrapper.
- * @param value An instance of an object to use to initialize the wrapper.
- * @return This any object.
- */
- template<typename Type, typename = std::enable_if_t<!std::is_same_v<std::decay_t<Type>, basic_any>>>
- basic_any &operator=(Type &&value) {
- emplace<std::decay_t<Type>>(std::forward<Type>(value));
- return *this;
- }
- /**
- * @brief Returns false if a wrapper is empty, true otherwise.
- * @return False if the wrapper is empty, true otherwise.
- */
- [[nodiscard]] bool has_value() const noexcept {
- return (mode != any_policy::empty);
- }
- /**
- * @brief Returns false if the wrapper does not contain the expected type,
- * true otherwise.
- * @param req Expected type.
- * @return False if the wrapper does not contain the expected type, true
- * otherwise.
- */
- [[nodiscard]] bool has_value(const type_info &req) const noexcept {
- return (underlying_type == req.hash());
- }
- /**
- * @brief Returns false if the wrapper does not contain the expected type,
- * true otherwise.
- * @tparam Type Expected type.
- * @return False if the wrapper does not contain the expected type, true
- * otherwise.
- */
- template<typename Type>
- [[nodiscard]] bool has_value() const noexcept {
- static_assert(std::is_same_v<std::remove_const_t<Type>, Type>, "Invalid type");
- return (underlying_type == type_hash<Type>::value());
- }
- /**
- * @brief Returns the object type info if any, `type_id<void>()` otherwise.
- * @return The object type info if any, `type_id<void>()` otherwise.
- */
- [[nodiscard]] const type_info &info() const noexcept {
- return *static_cast<const type_info *>(vtable(request::info, *this, nullptr));
- }
- /*! @copydoc info */
- [[deprecated("use ::info instead")]] [[nodiscard]] const type_info &type() const noexcept {
- return info();
- }
- /**
- * @brief Returns an opaque pointer to the contained instance.
- * @return An opaque pointer the contained instance, if any.
- */
- [[nodiscard]] const void *data() const noexcept {
- if constexpr(base_type::has_buffer) {
- return (mode == any_policy::embedded) ? &this->buffer : this->instance;
- } else {
- return this->instance;
- }
- }
- /**
- * @brief Returns an opaque pointer to the contained instance.
- * @param req Expected type.
- * @return An opaque pointer the contained instance, if any.
- */
- [[nodiscard]] const void *data(const type_info &req) const noexcept {
- return has_value(req) ? data() : nullptr;
- }
- /**
- * @brief Returns an opaque pointer to the contained instance.
- * @tparam Type Expected type.
- * @return An opaque pointer the contained instance, if any.
- */
- template<typename Type>
- [[nodiscard]] const Type *data() const noexcept {
- return has_value<std::remove_const_t<Type>>() ? static_cast<const Type *>(data()) : nullptr;
- }
- /**
- * @brief Returns an opaque pointer to the contained instance.
- * @return An opaque pointer the contained instance, if any.
- */
- [[nodiscard]] void *data() noexcept {
- return (mode == any_policy::cref) ? nullptr : const_cast<void *>(std::as_const(*this).data());
- }
- /**
- * @brief Returns an opaque pointer to the contained instance.
- * @param req Expected type.
- * @return An opaque pointer the contained instance, if any.
- */
- [[nodiscard]] void *data(const type_info &req) noexcept {
- return (mode == any_policy::cref) ? nullptr : const_cast<void *>(std::as_const(*this).data(req));
- }
- /**
- * @brief Returns an opaque pointer to the contained instance.
- * @tparam Type Expected type.
- * @return An opaque pointer the contained instance, if any.
- */
- template<typename Type>
- [[nodiscard]] Type *data() noexcept {
- if constexpr(std::is_const_v<Type>) {
- return std::as_const(*this).template data<std::remove_const_t<Type>>();
- } else {
- return (mode == any_policy::cref) ? nullptr : const_cast<Type *>(std::as_const(*this).template data<std::remove_const_t<Type>>());
- }
- }
- /**
- * @brief Replaces the contained object by creating a new instance directly.
- * @tparam Type Type of object to use to initialize the wrapper.
- * @tparam Args Types of arguments to use to construct the new instance.
- * @param args Parameters to use to construct the instance.
- */
- template<typename Type, typename... Args>
- void emplace(Args &&...args) {
- invoke_deleter_if_exists();
- initialize<Type>(std::forward<Args>(args)...);
- }
- /**
- * @brief Assigns a value to the contained object without replacing it.
- * @param other The value to assign to the contained object.
- * @return True in case of success, false otherwise.
- */
- bool assign(const basic_any &other) {
- if(other && (mode != any_policy::cref) && (underlying_type == other.underlying_type)) {
- return (vtable(request::assign, *this, other.data()) != nullptr);
- }
- return false;
- }
- /*! @copydoc assign */
- // NOLINTNEXTLINE(cppcoreguidelines-rvalue-reference-param-not-moved)
- bool assign(basic_any &&other) {
- if(other && (mode != any_policy::cref) && (underlying_type == other.underlying_type)) {
- return (other.mode == any_policy::cref) ? (vtable(request::assign, *this, std::as_const(other).data()) != nullptr) : (vtable(request::transfer, *this, other.data()) != nullptr);
- }
- return false;
- }
- /*! @brief Destroys contained object */
- void reset() {
- invoke_deleter_if_exists();
- initialize<void>();
- }
- /**
- * @brief Returns false if a wrapper is empty, true otherwise.
- * @return False if the wrapper is empty, true otherwise.
- */
- [[nodiscard]] explicit operator bool() const noexcept {
- return has_value();
- }
- /**
- * @brief Checks if two wrappers differ in their content.
- * @param other Wrapper with which to compare.
- * @return False if the two objects differ in their content, true otherwise.
- */
- [[nodiscard]] bool operator==(const basic_any &other) const noexcept {
- if(other && (underlying_type == other.underlying_type)) {
- return (vtable(request::compare, *this, other.data()) != nullptr);
- }
- return (!*this && !other);
- }
- /**
- * @brief Checks if two wrappers differ in their content.
- * @param other Wrapper with which to compare.
- * @return True if the two objects differ in their content, false otherwise.
- */
- [[nodiscard]] bool operator!=(const basic_any &other) const noexcept {
- return !(*this == other);
- }
- /**
- * @brief Aliasing constructor.
- * @return A wrapper that shares a reference to an unmanaged object.
- */
- [[nodiscard]] basic_any as_ref() noexcept {
- basic_any other = std::as_const(*this).as_ref();
- other.mode = (mode == any_policy::cref ? any_policy::cref : any_policy::ref);
- return other;
- }
- /*! @copydoc as_ref */
- [[nodiscard]] basic_any as_ref() const noexcept {
- basic_any other{};
- other.instance = data();
- other.vtable = vtable;
- other.underlying_type = underlying_type;
- other.mode = any_policy::cref;
- return other;
- }
- /**
- * @brief Returns true if a wrapper owns its object, false otherwise.
- * @return True if the wrapper owns its object, false otherwise.
- */
- [[nodiscard]] bool owner() const noexcept {
- return (mode == any_policy::dynamic || mode == any_policy::embedded);
- }
- /**
- * @brief Returns the current mode of an any object.
- * @return The current mode of the any object.
- */
- [[nodiscard]] any_policy policy() const noexcept {
- return mode;
- }
- private:
- vtable_type *vtable{};
- deleter_type *deleter{};
- id_type underlying_type{};
- any_policy mode{};
- };
- /**
- * @brief Performs type-safe access to the contained object.
- * @tparam Type Type to which conversion is required.
- * @tparam Len Size of the buffer reserved for the small buffer optimization.
- * @tparam Align Alignment requirement.
- * @param data Target any object.
- * @return The element converted to the requested type.
- */
- template<typename Type, std::size_t Len, std::size_t Align>
- [[nodiscard]] std::remove_const_t<Type> any_cast(const basic_any<Len, Align> &data) noexcept {
- const auto *const instance = any_cast<std::remove_reference_t<Type>>(&data);
- ENTT_ASSERT(instance, "Invalid instance");
- return static_cast<Type>(*instance);
- }
- /*! @copydoc any_cast */
- template<typename Type, std::size_t Len, std::size_t Align>
- [[nodiscard]] std::remove_const_t<Type> any_cast(basic_any<Len, Align> &data) noexcept {
- // forces const on non-reference types to make them work also with wrappers for const references
- auto *const instance = any_cast<std::remove_reference_t<const Type>>(&data);
- ENTT_ASSERT(instance, "Invalid instance");
- return static_cast<Type>(*instance);
- }
- /*! @copydoc any_cast */
- template<typename Type, std::size_t Len, std::size_t Align>
- // NOLINTNEXTLINE(cppcoreguidelines-rvalue-reference-param-not-moved)
- [[nodiscard]] std::remove_const_t<Type> any_cast(basic_any<Len, Align> &&data) noexcept {
- if constexpr(std::is_copy_constructible_v<std::remove_const_t<std::remove_reference_t<Type>>>) {
- if(auto *const instance = any_cast<std::remove_reference_t<Type>>(&data); instance) {
- return static_cast<Type>(std::move(*instance));
- }
- return any_cast<Type>(data);
- } else {
- auto *const instance = any_cast<std::remove_reference_t<Type>>(&data);
- ENTT_ASSERT(instance, "Invalid instance");
- return static_cast<Type>(std::move(*instance));
- }
- }
- /*! @copydoc any_cast */
- template<typename Type, std::size_t Len, std::size_t Align>
- [[nodiscard]] const Type *any_cast(const basic_any<Len, Align> *data) noexcept {
- return data->template data<std::remove_const_t<Type>>();
- }
- /*! @copydoc any_cast */
- template<typename Type, std::size_t Len, std::size_t Align>
- [[nodiscard]] Type *any_cast(basic_any<Len, Align> *data) noexcept {
- if constexpr(std::is_const_v<Type>) {
- // last attempt to make wrappers for const references return their values
- return any_cast<Type>(&std::as_const(*data));
- } else {
- return data->template data<Type>();
- }
- }
- /**
- * @brief Constructs a wrapper from a given type, passing it all arguments.
- * @tparam Type Type of object to use to initialize the wrapper.
- * @tparam Len Size of the buffer reserved for the small buffer optimization.
- * @tparam Align Optional alignment requirement.
- * @tparam Args Types of arguments to use to construct the new instance.
- * @param args Parameters to use to construct the instance.
- * @return A properly initialized wrapper for an object of the given type.
- */
- template<typename Type, std::size_t Len = basic_any<>::length, std::size_t Align = basic_any<Len>::alignment, typename... Args>
- [[nodiscard]] basic_any<Len, Align> make_any(Args &&...args) {
- return basic_any<Len, Align>{std::in_place_type<Type>, std::forward<Args>(args)...};
- }
- /**
- * @brief Forwards its argument and avoids copies for lvalue references.
- * @tparam Len Size of the buffer reserved for the small buffer optimization.
- * @tparam Align Optional alignment requirement.
- * @tparam Type Type of argument to use to construct the new instance.
- * @param value Parameter to use to construct the instance.
- * @return A properly initialized and not necessarily owning wrapper.
- */
- template<std::size_t Len = basic_any<>::length, std::size_t Align = basic_any<Len>::alignment, typename Type>
- [[nodiscard]] basic_any<Len, Align> forward_as_any(Type &&value) {
- return basic_any<Len, Align>{std::in_place_type<Type &&>, std::forward<Type>(value)};
- }
- } // namespace entt
- #endif
- // #include "core/bit.hpp"
- #ifndef ENTT_CORE_BIT_HPP
- #define ENTT_CORE_BIT_HPP
- #include <cstddef>
- #include <limits>
- #include <type_traits>
- // #include "../config/config.h"
- namespace entt {
- /**
- * @brief Returns the number of set bits in a value (waiting for C++20 and
- * `std::popcount`).
- * @tparam Type Unsigned integer type.
- * @param value A value of unsigned integer type.
- * @return The number of set bits in the value.
- */
- template<typename Type>
- [[nodiscard]] constexpr std::enable_if_t<std::is_unsigned_v<Type>, int> popcount(const Type value) noexcept {
- return value ? (int(value & 1) + popcount(static_cast<Type>(value >> 1))) : 0;
- }
- /**
- * @brief Checks whether a value is a power of two or not (waiting for C++20 and
- * `std::has_single_bit`).
- * @tparam Type Unsigned integer type.
- * @param value A value of unsigned integer type.
- * @return True if the value is a power of two, false otherwise.
- */
- template<typename Type>
- [[nodiscard]] constexpr std::enable_if_t<std::is_unsigned_v<Type>, bool> has_single_bit(const Type value) noexcept {
- return value && ((value & (value - 1)) == 0);
- }
- /**
- * @brief Computes the smallest power of two greater than or equal to a value
- * (waiting for C++20 and `std::bit_ceil`).
- * @tparam Type Unsigned integer type.
- * @param value A value of unsigned integer type.
- * @return The smallest power of two greater than or equal to the given value.
- */
- template<typename Type>
- [[nodiscard]] constexpr std::enable_if_t<std::is_unsigned_v<Type>, Type> next_power_of_two(const Type value) noexcept {
- // NOLINTNEXTLINE(bugprone-assert-side-effect)
- ENTT_ASSERT_CONSTEXPR(value < (Type{1u} << (std::numeric_limits<Type>::digits - 1)), "Numeric limits exceeded");
- Type curr = value - (value != 0u);
- for(int next = 1; next < std::numeric_limits<Type>::digits; next = next * 2) {
- curr |= (curr >> next);
- }
- return ++curr;
- }
- /**
- * @brief Fast module utility function (powers of two only).
- * @tparam Type Unsigned integer type.
- * @param value A value of unsigned integer type.
- * @param mod _Modulus_, it must be a power of two.
- * @return The common remainder.
- */
- template<typename Type>
- [[nodiscard]] constexpr std::enable_if_t<std::is_unsigned_v<Type>, Type> fast_mod(const Type value, const std::size_t mod) noexcept {
- ENTT_ASSERT_CONSTEXPR(has_single_bit(mod), "Value must be a power of two");
- return static_cast<Type>(value & (mod - 1u));
- }
- } // namespace entt
- #endif
- // #include "core/compressed_pair.hpp"
- #ifndef ENTT_CORE_COMPRESSED_PAIR_HPP
- #define ENTT_CORE_COMPRESSED_PAIR_HPP
- #include <cstddef>
- #include <tuple>
- #include <type_traits>
- #include <utility>
- // #include "fwd.hpp"
- // #include "type_traits.hpp"
- namespace entt {
- /*! @cond TURN_OFF_DOXYGEN */
- namespace internal {
- template<typename Type, std::size_t, typename = void>
- struct compressed_pair_element {
- using reference = Type &;
- using const_reference = const Type &;
- template<typename Dummy = Type, typename = std::enable_if_t<std::is_default_constructible_v<Dummy>>>
- // NOLINTNEXTLINE(modernize-use-equals-default)
- constexpr compressed_pair_element() noexcept(std::is_nothrow_default_constructible_v<Type>) {}
- template<typename Arg, typename = std::enable_if_t<!std::is_same_v<std::remove_const_t<std::remove_reference_t<Arg>>, compressed_pair_element>>>
- constexpr compressed_pair_element(Arg &&arg) noexcept(std::is_nothrow_constructible_v<Type, Arg>)
- : value{std::forward<Arg>(arg)} {}
- template<typename... Args, std::size_t... Index>
- constexpr compressed_pair_element(std::tuple<Args...> args, std::index_sequence<Index...>) noexcept(std::is_nothrow_constructible_v<Type, Args...>)
- : value{std::forward<Args>(std::get<Index>(args))...} {}
- [[nodiscard]] constexpr reference get() noexcept {
- return value;
- }
- [[nodiscard]] constexpr const_reference get() const noexcept {
- return value;
- }
- private:
- Type value{};
- };
- template<typename Type, std::size_t Tag>
- struct compressed_pair_element<Type, Tag, std::enable_if_t<is_ebco_eligible_v<Type>>>: Type {
- using reference = Type &;
- using const_reference = const Type &;
- using base_type = Type;
- template<typename Dummy = Type, typename = std::enable_if_t<std::is_default_constructible_v<Dummy>>>
- constexpr compressed_pair_element() noexcept(std::is_nothrow_default_constructible_v<base_type>)
- : base_type{} {}
- template<typename Arg, typename = std::enable_if_t<!std::is_same_v<std::remove_const_t<std::remove_reference_t<Arg>>, compressed_pair_element>>>
- constexpr compressed_pair_element(Arg &&arg) noexcept(std::is_nothrow_constructible_v<base_type, Arg>)
- : base_type{std::forward<Arg>(arg)} {}
- template<typename... Args, std::size_t... Index>
- constexpr compressed_pair_element(std::tuple<Args...> args, std::index_sequence<Index...>) noexcept(std::is_nothrow_constructible_v<base_type, Args...>)
- : base_type{std::forward<Args>(std::get<Index>(args))...} {}
- [[nodiscard]] constexpr reference get() noexcept {
- return *this;
- }
- [[nodiscard]] constexpr const_reference get() const noexcept {
- return *this;
- }
- };
- } // namespace internal
- /*! @endcond */
- /**
- * @brief A compressed pair.
- *
- * A pair that exploits the _Empty Base Class Optimization_ (or _EBCO_) to
- * reduce its final size to a minimum.
- *
- * @tparam First The type of the first element that the pair stores.
- * @tparam Second The type of the second element that the pair stores.
- */
- template<typename First, typename Second>
- class compressed_pair final
- : internal::compressed_pair_element<First, 0u>,
- internal::compressed_pair_element<Second, 1u> {
- using first_base = internal::compressed_pair_element<First, 0u>;
- using second_base = internal::compressed_pair_element<Second, 1u>;
- public:
- /*! @brief The type of the first element that the pair stores. */
- using first_type = First;
- /*! @brief The type of the second element that the pair stores. */
- using second_type = Second;
- /**
- * @brief Default constructor, conditionally enabled.
- *
- * This constructor is only available when the types that the pair stores
- * are both at least default constructible.
- *
- * @tparam Dummy Dummy template parameter used for internal purposes.
- */
- template<bool Dummy = true, typename = std::enable_if_t<Dummy && std::is_default_constructible_v<first_type> && std::is_default_constructible_v<second_type>>>
- constexpr compressed_pair() noexcept(std::is_nothrow_default_constructible_v<first_base> && std::is_nothrow_default_constructible_v<second_base>)
- : first_base{},
- second_base{} {}
- /**
- * @brief Copy constructor.
- * @param other The instance to copy from.
- */
- constexpr compressed_pair(const compressed_pair &other) = default;
- /**
- * @brief Move constructor.
- * @param other The instance to move from.
- */
- constexpr compressed_pair(compressed_pair &&other) noexcept = default;
- /**
- * @brief Constructs a pair from its values.
- * @tparam Arg Type of value to use to initialize the first element.
- * @tparam Other Type of value to use to initialize the second element.
- * @param arg Value to use to initialize the first element.
- * @param other Value to use to initialize the second element.
- */
- template<typename Arg, typename Other>
- constexpr compressed_pair(Arg &&arg, Other &&other) noexcept(std::is_nothrow_constructible_v<first_base, Arg> && std::is_nothrow_constructible_v<second_base, Other>)
- : first_base{std::forward<Arg>(arg)},
- second_base{std::forward<Other>(other)} {}
- /**
- * @brief Constructs a pair by forwarding the arguments to its parts.
- * @tparam Args Types of arguments to use to initialize the first element.
- * @tparam Other Types of arguments to use to initialize the second element.
- * @param args Arguments to use to initialize the first element.
- * @param other Arguments to use to initialize the second element.
- */
- template<typename... Args, typename... Other>
- constexpr compressed_pair(std::piecewise_construct_t, std::tuple<Args...> args, std::tuple<Other...> other) noexcept(std::is_nothrow_constructible_v<first_base, Args...> && std::is_nothrow_constructible_v<second_base, Other...>)
- : first_base{std::move(args), std::index_sequence_for<Args...>{}},
- second_base{std::move(other), std::index_sequence_for<Other...>{}} {}
- /*! @brief Default destructor. */
- ~compressed_pair() = default;
- /**
- * @brief Copy assignment operator.
- * @param other The instance to copy from.
- * @return This compressed pair object.
- */
- constexpr compressed_pair &operator=(const compressed_pair &other) = default;
- /**
- * @brief Move assignment operator.
- * @param other The instance to move from.
- * @return This compressed pair object.
- */
- constexpr compressed_pair &operator=(compressed_pair &&other) noexcept = default;
- /**
- * @brief Returns the first element that a pair stores.
- * @return The first element that a pair stores.
- */
- [[nodiscard]] constexpr first_type &first() noexcept {
- return static_cast<first_base &>(*this).get();
- }
- /*! @copydoc first */
- [[nodiscard]] constexpr const first_type &first() const noexcept {
- return static_cast<const first_base &>(*this).get();
- }
- /**
- * @brief Returns the second element that a pair stores.
- * @return The second element that a pair stores.
- */
- [[nodiscard]] constexpr second_type &second() noexcept {
- return static_cast<second_base &>(*this).get();
- }
- /*! @copydoc second */
- [[nodiscard]] constexpr const second_type &second() const noexcept {
- return static_cast<const second_base &>(*this).get();
- }
- /**
- * @brief Swaps two compressed pair objects.
- * @param other The compressed pair to swap with.
- */
- constexpr void swap(compressed_pair &other) noexcept {
- using std::swap;
- swap(first(), other.first());
- swap(second(), other.second());
- }
- /**
- * @brief Extracts an element from the compressed pair.
- * @tparam Index An integer value that is either 0 or 1.
- * @return Returns a reference to the first element if `Index` is 0 and a
- * reference to the second element if `Index` is 1.
- */
- template<std::size_t Index>
- [[nodiscard]] constexpr decltype(auto) get() noexcept {
- if constexpr(Index == 0u) {
- return first();
- } else {
- static_assert(Index == 1u, "Index out of bounds");
- return second();
- }
- }
- /*! @copydoc get */
- template<std::size_t Index>
- [[nodiscard]] constexpr decltype(auto) get() const noexcept {
- if constexpr(Index == 0u) {
- return first();
- } else {
- static_assert(Index == 1u, "Index out of bounds");
- return second();
- }
- }
- };
- /**
- * @brief Deduction guide.
- * @tparam Type Type of value to use to initialize the first element.
- * @tparam Other Type of value to use to initialize the second element.
- */
- template<typename Type, typename Other>
- compressed_pair(Type &&, Other &&) -> compressed_pair<std::decay_t<Type>, std::decay_t<Other>>;
- /**
- * @brief Swaps two compressed pair objects.
- * @tparam First The type of the first element that the pairs store.
- * @tparam Second The type of the second element that the pairs store.
- * @param lhs A valid compressed pair object.
- * @param rhs A valid compressed pair object.
- */
- template<typename First, typename Second>
- constexpr void swap(compressed_pair<First, Second> &lhs, compressed_pair<First, Second> &rhs) noexcept {
- lhs.swap(rhs);
- }
- } // namespace entt
- namespace std {
- /**
- * @brief `std::tuple_size` specialization for `compressed_pair`s.
- * @tparam First The type of the first element that the pair stores.
- * @tparam Second The type of the second element that the pair stores.
- */
- template<typename First, typename Second>
- struct tuple_size<entt::compressed_pair<First, Second>>: integral_constant<size_t, 2u> {};
- /**
- * @brief `std::tuple_element` specialization for `compressed_pair`s.
- * @tparam Index The index of the type to return.
- * @tparam First The type of the first element that the pair stores.
- * @tparam Second The type of the second element that the pair stores.
- */
- template<size_t Index, typename First, typename Second>
- struct tuple_element<Index, entt::compressed_pair<First, Second>>: conditional<Index == 0u, First, Second> {
- static_assert(Index < 2u, "Index out of bounds");
- };
- } // namespace std
- #endif
- // #include "core/enum.hpp"
- #ifndef ENTT_CORE_ENUM_HPP
- #define ENTT_CORE_ENUM_HPP
- #include <type_traits>
- namespace entt {
- /**
- * @brief Enable bitmask support for enum classes.
- * @tparam Type The enum type for which to enable bitmask support.
- */
- template<typename Type, typename = void>
- struct enum_as_bitmask: std::false_type {};
- /*! @copydoc enum_as_bitmask */
- template<typename Type>
- struct enum_as_bitmask<Type, std::void_t<decltype(Type::_entt_enum_as_bitmask)>>: std::is_enum<Type> {};
- /**
- * @brief Helper variable template.
- * @tparam Type The enum class type for which to enable bitmask support.
- */
- template<typename Type>
- inline constexpr bool enum_as_bitmask_v = enum_as_bitmask<Type>::value;
- } // namespace entt
- /**
- * @brief Operator available for enums for which bitmask support is enabled.
- * @tparam Type Enum class type.
- * @param lhs The first value to use.
- * @param rhs The second value to use.
- * @return The result of invoking the operator on the underlying types of the
- * two values provided.
- */
- template<typename Type>
- [[nodiscard]] constexpr std::enable_if_t<entt::enum_as_bitmask_v<Type>, Type>
- operator|(const Type lhs, const Type rhs) noexcept {
- return static_cast<Type>(static_cast<std::underlying_type_t<Type>>(lhs) | static_cast<std::underlying_type_t<Type>>(rhs));
- }
- /*! @copydoc operator| */
- template<typename Type>
- [[nodiscard]] constexpr std::enable_if_t<entt::enum_as_bitmask_v<Type>, Type>
- operator&(const Type lhs, const Type rhs) noexcept {
- return static_cast<Type>(static_cast<std::underlying_type_t<Type>>(lhs) & static_cast<std::underlying_type_t<Type>>(rhs));
- }
- /*! @copydoc operator| */
- template<typename Type>
- [[nodiscard]] constexpr std::enable_if_t<entt::enum_as_bitmask_v<Type>, Type>
- operator^(const Type lhs, const Type rhs) noexcept {
- return static_cast<Type>(static_cast<std::underlying_type_t<Type>>(lhs) ^ static_cast<std::underlying_type_t<Type>>(rhs));
- }
- /**
- * @brief Operator available for enums for which bitmask support is enabled.
- * @tparam Type Enum class type.
- * @param value The value to use.
- * @return The result of invoking the operator on the underlying types of the
- * value provided.
- */
- template<typename Type>
- [[nodiscard]] constexpr std::enable_if_t<entt::enum_as_bitmask_v<Type>, Type>
- operator~(const Type value) noexcept {
- return static_cast<Type>(~static_cast<std::underlying_type_t<Type>>(value));
- }
- /*! @copydoc operator~ */
- template<typename Type>
- [[nodiscard]] constexpr std::enable_if_t<entt::enum_as_bitmask_v<Type>, bool>
- operator!(const Type value) noexcept {
- return !static_cast<std::underlying_type_t<Type>>(value);
- }
- /*! @copydoc operator| */
- template<typename Type>
- constexpr std::enable_if_t<entt::enum_as_bitmask_v<Type>, Type &>
- operator|=(Type &lhs, const Type rhs) noexcept {
- return (lhs = (lhs | rhs));
- }
- /*! @copydoc operator| */
- template<typename Type>
- constexpr std::enable_if_t<entt::enum_as_bitmask_v<Type>, Type &>
- operator&=(Type &lhs, const Type rhs) noexcept {
- return (lhs = (lhs & rhs));
- }
- /*! @copydoc operator| */
- template<typename Type>
- constexpr std::enable_if_t<entt::enum_as_bitmask_v<Type>, Type &>
- operator^=(Type &lhs, const Type rhs) noexcept {
- return (lhs = (lhs ^ rhs));
- }
- #endif
- // #include "core/family.hpp"
- #ifndef ENTT_CORE_FAMILY_HPP
- #define ENTT_CORE_FAMILY_HPP
- // #include "../config/config.h"
- // #include "fwd.hpp"
- namespace entt {
- /**
- * @brief Dynamic identifier generator.
- *
- * Utility class template that can be used to assign unique identifiers to types
- * at runtime. Use different specializations to create separate sets of
- * identifiers.
- */
- template<typename...>
- class family {
- static auto identifier() noexcept {
- static ENTT_MAYBE_ATOMIC(id_type) value{};
- return value++;
- }
- public:
- /*! @brief Unsigned integer type. */
- using value_type = id_type;
- /*! @brief Statically generated unique identifier for the given type. */
- template<typename... Type>
- // at the time I'm writing, clang crashes during compilation if auto is used instead of family_type
- inline static const value_type value = identifier();
- };
- } // namespace entt
- #endif
- // #include "core/hashed_string.hpp"
- #ifndef ENTT_CORE_HASHED_STRING_HPP
- #define ENTT_CORE_HASHED_STRING_HPP
- #include <cstddef>
- #include <cstdint>
- // #include "fwd.hpp"
- namespace entt {
- /*! @cond TURN_OFF_DOXYGEN */
- namespace internal {
- template<typename = id_type>
- struct fnv_1a_params;
- template<>
- struct fnv_1a_params<std::uint32_t> {
- static constexpr auto offset = 2166136261;
- static constexpr auto prime = 16777619;
- };
- template<>
- struct fnv_1a_params<std::uint64_t> {
- static constexpr auto offset = 14695981039346656037ull;
- static constexpr auto prime = 1099511628211ull;
- };
- template<typename Char>
- struct basic_hashed_string {
- using value_type = Char;
- using size_type = std::size_t;
- using hash_type = id_type;
- const value_type *repr{};
- hash_type hash{fnv_1a_params<>::offset};
- size_type length{};
- };
- } // namespace internal
- /*! @endcond */
- /**
- * @brief Zero overhead unique identifier.
- *
- * A hashed string is a compile-time tool that allows users to use
- * human-readable identifiers in the codebase while using their numeric
- * counterparts at runtime.<br/>
- * Because of that, a hashed string can also be used in constant expressions if
- * required.
- *
- * @warning
- * This class doesn't take ownership of user-supplied strings nor does it make a
- * copy of them.
- *
- * @tparam Char Character type.
- */
- template<typename Char>
- class basic_hashed_string: internal::basic_hashed_string<Char> {
- using base_type = internal::basic_hashed_string<Char>;
- using params = internal::fnv_1a_params<>;
- struct const_wrapper {
- // non-explicit constructor on purpose
- constexpr const_wrapper(const typename base_type::value_type *str) noexcept
- : repr{str} {}
- const typename base_type::value_type *repr;
- };
- public:
- /*! @brief Character type. */
- using value_type = typename base_type::value_type;
- /*! @brief Unsigned integer type. */
- using size_type = typename base_type::size_type;
- /*! @brief Unsigned integer type. */
- using hash_type = typename base_type::hash_type;
- /**
- * @brief Returns directly the numeric representation of a string view.
- * @param str Human-readable identifier.
- * @param len Length of the string to hash.
- * @return The numeric representation of the string.
- */
- [[nodiscard]] static constexpr hash_type value(const value_type *str, const size_type len) noexcept {
- return basic_hashed_string{str, len};
- }
- /**
- * @brief Returns directly the numeric representation of a string.
- * @tparam N Number of characters of the identifier.
- * @param str Human-readable identifier.
- * @return The numeric representation of the string.
- */
- template<std::size_t N>
- // NOLINTNEXTLINE(cppcoreguidelines-avoid-c-arrays, modernize-avoid-c-arrays)
- [[nodiscard]] static ENTT_CONSTEVAL hash_type value(const value_type (&str)[N]) noexcept {
- return basic_hashed_string{str};
- }
- /**
- * @brief Returns directly the numeric representation of a string.
- * @param wrapper Helps achieving the purpose by relying on overloading.
- * @return The numeric representation of the string.
- */
- [[nodiscard]] static constexpr hash_type value(const_wrapper wrapper) noexcept {
- return basic_hashed_string{wrapper};
- }
- /*! @brief Constructs an empty hashed string. */
- constexpr basic_hashed_string() noexcept
- : basic_hashed_string{nullptr, 0u} {}
- /**
- * @brief Constructs a hashed string from a string view.
- * @param str Human-readable identifier.
- * @param len Length of the string to hash.
- */
- constexpr basic_hashed_string(const value_type *str, const size_type len) noexcept
- // NOLINTNEXTLINE(cppcoreguidelines-pro-bounds-array-to-pointer-decay)
- : base_type{str} {
- // NOLINTBEGIN(cppcoreguidelines-pro-bounds-pointer-arithmetic)
- for(; base_type::length < len; ++base_type::length) {
- base_type::hash = (base_type::hash ^ static_cast<id_type>(str[base_type::length])) * params::prime;
- }
- // NOLINTEND(cppcoreguidelines-pro-bounds-pointer-arithmetic)
- }
- /**
- * @brief Constructs a hashed string from an array of const characters.
- * @tparam N Number of characters of the identifier.
- * @param str Human-readable identifier.
- */
- template<std::size_t N>
- // NOLINTNEXTLINE(cppcoreguidelines-avoid-c-arrays, modernize-avoid-c-arrays)
- ENTT_CONSTEVAL basic_hashed_string(const value_type (&str)[N]) noexcept
- // NOLINTNEXTLINE(cppcoreguidelines-pro-bounds-array-to-pointer-decay)
- : base_type{str} {
- for(; str[base_type::length]; ++base_type::length) {
- base_type::hash = (base_type::hash ^ static_cast<id_type>(str[base_type::length])) * params::prime;
- }
- }
- /**
- * @brief Explicit constructor on purpose to avoid constructing a hashed
- * string directly from a `const value_type *`.
- *
- * @warning
- * The lifetime of the string is not extended nor is it copied.
- *
- * @param wrapper Helps achieving the purpose by relying on overloading.
- */
- explicit constexpr basic_hashed_string(const_wrapper wrapper) noexcept
- : base_type{wrapper.repr} {
- // NOLINTBEGIN(cppcoreguidelines-pro-bounds-pointer-arithmetic)
- for(; wrapper.repr[base_type::length]; ++base_type::length) {
- base_type::hash = (base_type::hash ^ static_cast<id_type>(wrapper.repr[base_type::length])) * params::prime;
- }
- // NOLINTEND(cppcoreguidelines-pro-bounds-pointer-arithmetic)
- }
- /**
- * @brief Returns the size of a hashed string.
- * @return The size of the hashed string.
- */
- [[nodiscard]] constexpr size_type size() const noexcept {
- return base_type::length;
- }
- /**
- * @brief Returns the human-readable representation of a hashed string.
- * @return The string used to initialize the hashed string.
- */
- [[nodiscard]] constexpr const value_type *data() const noexcept {
- return base_type::repr;
- }
- /**
- * @brief Returns the numeric representation of a hashed string.
- * @return The numeric representation of the hashed string.
- */
- [[nodiscard]] constexpr hash_type value() const noexcept {
- return base_type::hash;
- }
- /*! @copydoc data */
- [[nodiscard]] explicit constexpr operator const value_type *() const noexcept {
- return data();
- }
- /**
- * @brief Returns the numeric representation of a hashed string.
- * @return The numeric representation of the hashed string.
- */
- [[nodiscard]] constexpr operator hash_type() const noexcept {
- return value();
- }
- };
- /**
- * @brief Deduction guide.
- * @tparam Char Character type.
- * @param str Human-readable identifier.
- * @param len Length of the string to hash.
- */
- template<typename Char>
- basic_hashed_string(const Char *str, std::size_t len) -> basic_hashed_string<Char>;
- /**
- * @brief Deduction guide.
- * @tparam Char Character type.
- * @tparam N Number of characters of the identifier.
- * @param str Human-readable identifier.
- */
- template<typename Char, std::size_t N>
- // NOLINTNEXTLINE(cppcoreguidelines-avoid-c-arrays, modernize-avoid-c-arrays)
- basic_hashed_string(const Char (&str)[N]) -> basic_hashed_string<Char>;
- /**
- * @brief Compares two hashed strings.
- * @tparam Char Character type.
- * @param lhs A valid hashed string.
- * @param rhs A valid hashed string.
- * @return True if the two hashed strings are identical, false otherwise.
- */
- template<typename Char>
- [[nodiscard]] constexpr bool operator==(const basic_hashed_string<Char> &lhs, const basic_hashed_string<Char> &rhs) noexcept {
- return lhs.value() == rhs.value();
- }
- /**
- * @brief Compares two hashed strings.
- * @tparam Char Character type.
- * @param lhs A valid hashed string.
- * @param rhs A valid hashed string.
- * @return True if the two hashed strings differ, false otherwise.
- */
- template<typename Char>
- [[nodiscard]] constexpr bool operator!=(const basic_hashed_string<Char> &lhs, const basic_hashed_string<Char> &rhs) noexcept {
- return !(lhs == rhs);
- }
- /**
- * @brief Compares two hashed strings.
- * @tparam Char Character type.
- * @param lhs A valid hashed string.
- * @param rhs A valid hashed string.
- * @return True if the first element is less than the second, false otherwise.
- */
- template<typename Char>
- [[nodiscard]] constexpr bool operator<(const basic_hashed_string<Char> &lhs, const basic_hashed_string<Char> &rhs) noexcept {
- return lhs.value() < rhs.value();
- }
- /**
- * @brief Compares two hashed strings.
- * @tparam Char Character type.
- * @param lhs A valid hashed string.
- * @param rhs A valid hashed string.
- * @return True if the first element is less than or equal to the second, false
- * otherwise.
- */
- template<typename Char>
- [[nodiscard]] constexpr bool operator<=(const basic_hashed_string<Char> &lhs, const basic_hashed_string<Char> &rhs) noexcept {
- return !(rhs < lhs);
- }
- /**
- * @brief Compares two hashed strings.
- * @tparam Char Character type.
- * @param lhs A valid hashed string.
- * @param rhs A valid hashed string.
- * @return True if the first element is greater than the second, false
- * otherwise.
- */
- template<typename Char>
- [[nodiscard]] constexpr bool operator>(const basic_hashed_string<Char> &lhs, const basic_hashed_string<Char> &rhs) noexcept {
- return rhs < lhs;
- }
- /**
- * @brief Compares two hashed strings.
- * @tparam Char Character type.
- * @param lhs A valid hashed string.
- * @param rhs A valid hashed string.
- * @return True if the first element is greater than or equal to the second,
- * false otherwise.
- */
- template<typename Char>
- [[nodiscard]] constexpr bool operator>=(const basic_hashed_string<Char> &lhs, const basic_hashed_string<Char> &rhs) noexcept {
- return !(lhs < rhs);
- }
- inline namespace literals {
- /**
- * @brief User defined literal for hashed strings.
- * @param str The literal without its suffix.
- * @return A properly initialized hashed string.
- */
- [[nodiscard]] ENTT_CONSTEVAL hashed_string operator""_hs(const char *str, std::size_t) noexcept {
- return hashed_string{str};
- }
- /**
- * @brief User defined literal for hashed wstrings.
- * @param str The literal without its suffix.
- * @return A properly initialized hashed wstring.
- */
- [[nodiscard]] ENTT_CONSTEVAL hashed_wstring operator""_hws(const wchar_t *str, std::size_t) noexcept {
- return hashed_wstring{str};
- }
- } // namespace literals
- } // namespace entt
- #endif
- // #include "core/ident.hpp"
- #ifndef ENTT_CORE_IDENT_HPP
- #define ENTT_CORE_IDENT_HPP
- #include <cstddef>
- #include <type_traits>
- #include <utility>
- // #include "fwd.hpp"
- // #include "type_traits.hpp"
- namespace entt {
- /**
- * @brief Type integral identifiers.
- * @tparam Type List of types for which to generate identifiers.
- */
- template<typename... Type>
- class ident {
- template<typename Curr, std::size_t... Index>
- [[nodiscard]] static constexpr id_type get(std::index_sequence<Index...>) noexcept {
- static_assert((std::is_same_v<Curr, Type> || ...), "Invalid type");
- return (0 + ... + (std::is_same_v<Curr, type_list_element_t<Index, type_list<std::decay_t<Type>...>>> ? id_type{Index} : id_type{}));
- }
- public:
- /*! @brief Unsigned integer type. */
- using value_type = id_type;
- /*! @brief Statically generated unique identifier for the given type. */
- template<typename Curr>
- static constexpr value_type value = get<std::decay_t<Curr>>(std::index_sequence_for<Type...>{});
- };
- } // namespace entt
- #endif
- // #include "core/iterator.hpp"
- #ifndef ENTT_CORE_ITERATOR_HPP
- #define ENTT_CORE_ITERATOR_HPP
- #include <iterator>
- #include <memory>
- #include <type_traits>
- #include <utility>
- namespace entt {
- /**
- * @brief Helper type to use as pointer with input iterators.
- * @tparam Type of wrapped value.
- */
- template<typename Type>
- struct input_iterator_pointer final {
- /*! @brief Value type. */
- using value_type = Type;
- /*! @brief Pointer type. */
- using pointer = Type *;
- /*! @brief Reference type. */
- using reference = Type &;
- /**
- * @brief Constructs a proxy object by move.
- * @param val Value to use to initialize the proxy object.
- */
- constexpr input_iterator_pointer(value_type &&val) noexcept(std::is_nothrow_move_constructible_v<value_type>)
- : value{std::move(val)} {}
- /**
- * @brief Access operator for accessing wrapped values.
- * @return A pointer to the wrapped value.
- */
- [[nodiscard]] constexpr pointer operator->() noexcept {
- return std::addressof(value);
- }
- /**
- * @brief Dereference operator for accessing wrapped values.
- * @return A reference to the wrapped value.
- */
- [[nodiscard]] constexpr reference operator*() noexcept {
- return value;
- }
- private:
- Type value;
- };
- /**
- * @brief Plain iota iterator (waiting for C++20).
- * @tparam Type Value type.
- */
- template<typename Type>
- class iota_iterator final {
- static_assert(std::is_integral_v<Type>, "Not an integral type");
- public:
- /*! @brief Value type, likely an integral one. */
- using value_type = Type;
- /*! @brief Invalid pointer type. */
- using pointer = void;
- /*! @brief Non-reference type, same as value type. */
- using reference = value_type;
- /*! @brief Difference type. */
- using difference_type = std::ptrdiff_t;
- /*! @brief Iterator category. */
- using iterator_category = std::input_iterator_tag;
- /*! @brief Default constructor. */
- constexpr iota_iterator() noexcept
- : current{} {}
- /**
- * @brief Constructs an iota iterator from a given value.
- * @param init The initial value assigned to the iota iterator.
- */
- constexpr iota_iterator(const value_type init) noexcept
- : current{init} {}
- /**
- * @brief Pre-increment operator.
- * @return This iota iterator.
- */
- constexpr iota_iterator &operator++() noexcept {
- return ++current, *this;
- }
- /**
- * @brief Post-increment operator.
- * @return This iota iterator.
- */
- constexpr iota_iterator operator++(int) noexcept {
- const iota_iterator orig = *this;
- return ++(*this), orig;
- }
- /**
- * @brief Dereference operator.
- * @return The underlying value.
- */
- [[nodiscard]] constexpr reference operator*() const noexcept {
- return current;
- }
- private:
- value_type current;
- };
- /**
- * @brief Comparison operator.
- * @tparam Type Value type of the iota iterator.
- * @param lhs A properly initialized iota iterator.
- * @param rhs A properly initialized iota iterator.
- * @return True if the two iterators are identical, false otherwise.
- */
- template<typename Type>
- [[nodiscard]] constexpr bool operator==(const iota_iterator<Type> &lhs, const iota_iterator<Type> &rhs) noexcept {
- return *lhs == *rhs;
- }
- /**
- * @brief Comparison operator.
- * @tparam Type Value type of the iota iterator.
- * @param lhs A properly initialized iota iterator.
- * @param rhs A properly initialized iota iterator.
- * @return True if the two iterators differ, false otherwise.
- */
- template<typename Type>
- [[nodiscard]] constexpr bool operator!=(const iota_iterator<Type> &lhs, const iota_iterator<Type> &rhs) noexcept {
- return !(lhs == rhs);
- }
- /**
- * @brief Utility class to create an iterable object from a pair of iterators.
- * @tparam It Type of iterator.
- * @tparam Sentinel Type of sentinel.
- */
- template<typename It, typename Sentinel = It>
- struct iterable_adaptor final {
- /*! @brief Value type. */
- using value_type = typename std::iterator_traits<It>::value_type;
- /*! @brief Iterator type. */
- using iterator = It;
- /*! @brief Sentinel type. */
- using sentinel = Sentinel;
- /*! @brief Default constructor. */
- constexpr iterable_adaptor() noexcept(std::is_nothrow_default_constructible_v<iterator> && std::is_nothrow_default_constructible_v<sentinel>)
- : first{},
- last{} {}
- /**
- * @brief Creates an iterable object from a pair of iterators.
- * @param from Begin iterator.
- * @param to End iterator.
- */
- constexpr iterable_adaptor(iterator from, sentinel to) noexcept(std::is_nothrow_move_constructible_v<iterator> && std::is_nothrow_move_constructible_v<sentinel>)
- : first{std::move(from)},
- last{std::move(to)} {}
- /**
- * @brief Returns an iterator to the beginning.
- * @return An iterator to the first element of the range.
- */
- [[nodiscard]] constexpr iterator begin() const noexcept {
- return first;
- }
- /**
- * @brief Returns an iterator to the end.
- * @return An iterator to the element following the last element of the
- * range.
- */
- [[nodiscard]] constexpr sentinel end() const noexcept {
- return last;
- }
- /*! @copydoc begin */
- [[nodiscard]] constexpr iterator cbegin() const noexcept {
- return begin();
- }
- /*! @copydoc end */
- [[nodiscard]] constexpr sentinel cend() const noexcept {
- return end();
- }
- private:
- It first;
- Sentinel last;
- };
- } // namespace entt
- #endif
- // #include "core/memory.hpp"
- #ifndef ENTT_CORE_MEMORY_HPP
- #define ENTT_CORE_MEMORY_HPP
- #include <cstddef>
- #include <memory>
- #include <tuple>
- #include <type_traits>
- #include <utility>
- // #include "../config/config.h"
- namespace entt {
- /**
- * @brief Unwraps fancy pointers, does nothing otherwise (waiting for C++20).
- * @tparam Type Pointer type.
- * @param ptr Fancy or raw pointer.
- * @return A raw pointer that represents the address of the original pointer.
- */
- template<typename Type>
- [[nodiscard]] constexpr auto to_address(Type &&ptr) noexcept {
- if constexpr(std::is_pointer_v<std::decay_t<Type>>) {
- return ptr;
- } else {
- return to_address(std::forward<Type>(ptr).operator->());
- }
- }
- /**
- * @brief Utility function to design allocation-aware containers.
- * @tparam Allocator Type of allocator.
- * @param lhs A valid allocator.
- * @param rhs Another valid allocator.
- */
- template<typename Allocator>
- constexpr void propagate_on_container_copy_assignment([[maybe_unused]] Allocator &lhs, [[maybe_unused]] Allocator &rhs) noexcept {
- if constexpr(std::allocator_traits<Allocator>::propagate_on_container_copy_assignment::value) {
- lhs = rhs;
- }
- }
- /**
- * @brief Utility function to design allocation-aware containers.
- * @tparam Allocator Type of allocator.
- * @param lhs A valid allocator.
- * @param rhs Another valid allocator.
- */
- template<typename Allocator>
- constexpr void propagate_on_container_move_assignment([[maybe_unused]] Allocator &lhs, [[maybe_unused]] Allocator &rhs) noexcept {
- if constexpr(std::allocator_traits<Allocator>::propagate_on_container_move_assignment::value) {
- lhs = std::move(rhs);
- }
- }
- /**
- * @brief Utility function to design allocation-aware containers.
- * @tparam Allocator Type of allocator.
- * @param lhs A valid allocator.
- * @param rhs Another valid allocator.
- */
- template<typename Allocator>
- constexpr void propagate_on_container_swap([[maybe_unused]] Allocator &lhs, [[maybe_unused]] Allocator &rhs) noexcept {
- if constexpr(std::allocator_traits<Allocator>::propagate_on_container_swap::value) {
- using std::swap;
- swap(lhs, rhs);
- } else {
- ENTT_ASSERT_CONSTEXPR(lhs == rhs, "Cannot swap the containers");
- }
- }
- /**
- * @brief Deleter for allocator-aware unique pointers (waiting for C++20).
- * @tparam Allocator Type of allocator used to manage memory and elements.
- */
- template<typename Allocator>
- struct allocation_deleter: private Allocator {
- /*! @brief Allocator type. */
- using allocator_type = Allocator;
- /*! @brief Pointer type. */
- using pointer = typename std::allocator_traits<Allocator>::pointer;
- /**
- * @brief Inherited constructors.
- * @param alloc The allocator to use.
- */
- constexpr allocation_deleter(const allocator_type &alloc) noexcept(std::is_nothrow_copy_constructible_v<allocator_type>)
- : Allocator{alloc} {}
- /**
- * @brief Destroys the pointed object and deallocates its memory.
- * @param ptr A valid pointer to an object of the given type.
- */
- constexpr void operator()(pointer ptr) noexcept(std::is_nothrow_destructible_v<typename allocator_type::value_type>) {
- using alloc_traits = std::allocator_traits<Allocator>;
- alloc_traits::destroy(*this, to_address(ptr));
- alloc_traits::deallocate(*this, ptr, 1u);
- }
- };
- /**
- * @brief Allows `std::unique_ptr` to use allocators (waiting for C++20).
- * @tparam Type Type of object to allocate for and to construct.
- * @tparam Allocator Type of allocator used to manage memory and elements.
- * @tparam Args Types of arguments to use to construct the object.
- * @param allocator The allocator to use.
- * @param args Parameters to use to construct the object.
- * @return A properly initialized unique pointer with a custom deleter.
- */
- template<typename Type, typename Allocator, typename... Args>
- ENTT_CONSTEXPR auto allocate_unique(Allocator &allocator, Args &&...args) {
- static_assert(!std::is_array_v<Type>, "Array types are not supported");
- using alloc_traits = typename std::allocator_traits<Allocator>::template rebind_traits<Type>;
- using allocator_type = typename alloc_traits::allocator_type;
- allocator_type alloc{allocator};
- auto ptr = alloc_traits::allocate(alloc, 1u);
- ENTT_TRY {
- alloc_traits::construct(alloc, to_address(ptr), std::forward<Args>(args)...);
- }
- ENTT_CATCH {
- alloc_traits::deallocate(alloc, ptr, 1u);
- ENTT_THROW;
- }
- return std::unique_ptr<Type, allocation_deleter<allocator_type>>{ptr, alloc};
- }
- /*! @cond TURN_OFF_DOXYGEN */
- namespace internal {
- template<typename Type>
- struct uses_allocator_construction {
- template<typename Allocator, typename... Params>
- static constexpr auto args([[maybe_unused]] const Allocator &allocator, Params &&...params) noexcept {
- if constexpr(!std::uses_allocator_v<Type, Allocator> && std::is_constructible_v<Type, Params...>) {
- return std::forward_as_tuple(std::forward<Params>(params)...);
- } else {
- static_assert(std::uses_allocator_v<Type, Allocator>, "Ill-formed request");
- if constexpr(std::is_constructible_v<Type, std::allocator_arg_t, const Allocator &, Params...>) {
- return std::tuple<std::allocator_arg_t, const Allocator &, Params &&...>{std::allocator_arg, allocator, std::forward<Params>(params)...};
- } else {
- static_assert(std::is_constructible_v<Type, Params..., const Allocator &>, "Ill-formed request");
- return std::forward_as_tuple(std::forward<Params>(params)..., allocator);
- }
- }
- }
- };
- template<typename Type, typename Other>
- struct uses_allocator_construction<std::pair<Type, Other>> {
- using type = std::pair<Type, Other>;
- template<typename Allocator, typename First, typename Second>
- static constexpr auto args(const Allocator &allocator, std::piecewise_construct_t, First &&first, Second &&second) noexcept {
- return std::make_tuple(
- std::piecewise_construct,
- std::apply([&allocator](auto &&...curr) { return uses_allocator_construction<Type>::args(allocator, std::forward<decltype(curr)>(curr)...); }, std::forward<First>(first)),
- std::apply([&allocator](auto &&...curr) { return uses_allocator_construction<Other>::args(allocator, std::forward<decltype(curr)>(curr)...); }, std::forward<Second>(second)));
- }
- template<typename Allocator>
- static constexpr auto args(const Allocator &allocator) noexcept {
- return uses_allocator_construction<type>::args(allocator, std::piecewise_construct, std::tuple<>{}, std::tuple<>{});
- }
- template<typename Allocator, typename First, typename Second>
- static constexpr auto args(const Allocator &allocator, First &&first, Second &&second) noexcept {
- return uses_allocator_construction<type>::args(allocator, std::piecewise_construct, std::forward_as_tuple(std::forward<First>(first)), std::forward_as_tuple(std::forward<Second>(second)));
- }
- template<typename Allocator, typename First, typename Second>
- static constexpr auto args(const Allocator &allocator, const std::pair<First, Second> &value) noexcept {
- return uses_allocator_construction<type>::args(allocator, std::piecewise_construct, std::forward_as_tuple(value.first), std::forward_as_tuple(value.second));
- }
- template<typename Allocator, typename First, typename Second>
- static constexpr auto args(const Allocator &allocator, std::pair<First, Second> &&value) noexcept {
- return uses_allocator_construction<type>::args(allocator, std::piecewise_construct, std::forward_as_tuple(std::move(value.first)), std::forward_as_tuple(std::move(value.second)));
- }
- };
- } // namespace internal
- /*! @endcond */
- /**
- * @brief Uses-allocator construction utility (waiting for C++20).
- *
- * Primarily intended for internal use. Prepares the argument list needed to
- * create an object of a given type by means of uses-allocator construction.
- *
- * @tparam Type Type to return arguments for.
- * @tparam Allocator Type of allocator used to manage memory and elements.
- * @tparam Args Types of arguments to use to construct the object.
- * @param allocator The allocator to use.
- * @param args Parameters to use to construct the object.
- * @return The arguments needed to create an object of the given type.
- */
- template<typename Type, typename Allocator, typename... Args>
- constexpr auto uses_allocator_construction_args(const Allocator &allocator, Args &&...args) noexcept {
- return internal::uses_allocator_construction<Type>::args(allocator, std::forward<Args>(args)...);
- }
- /**
- * @brief Uses-allocator construction utility (waiting for C++20).
- *
- * Primarily intended for internal use. Creates an object of a given type by
- * means of uses-allocator construction.
- *
- * @tparam Type Type of object to create.
- * @tparam Allocator Type of allocator used to manage memory and elements.
- * @tparam Args Types of arguments to use to construct the object.
- * @param allocator The allocator to use.
- * @param args Parameters to use to construct the object.
- * @return A newly created object of the given type.
- */
- template<typename Type, typename Allocator, typename... Args>
- constexpr Type make_obj_using_allocator(const Allocator &allocator, Args &&...args) {
- return std::make_from_tuple<Type>(internal::uses_allocator_construction<Type>::args(allocator, std::forward<Args>(args)...));
- }
- /**
- * @brief Uses-allocator construction utility (waiting for C++20).
- *
- * Primarily intended for internal use. Creates an object of a given type by
- * means of uses-allocator construction at an uninitialized memory location.
- *
- * @tparam Type Type of object to create.
- * @tparam Allocator Type of allocator used to manage memory and elements.
- * @tparam Args Types of arguments to use to construct the object.
- * @param value Memory location in which to place the object.
- * @param allocator The allocator to use.
- * @param args Parameters to use to construct the object.
- * @return A pointer to the newly created object of the given type.
- */
- template<typename Type, typename Allocator, typename... Args>
- constexpr Type *uninitialized_construct_using_allocator(Type *value, const Allocator &allocator, Args &&...args) {
- return std::apply([value](auto &&...curr) { return ::new(value) Type(std::forward<decltype(curr)>(curr)...); }, internal::uses_allocator_construction<Type>::args(allocator, std::forward<Args>(args)...));
- }
- } // namespace entt
- #endif
- // #include "core/monostate.hpp"
- #ifndef ENTT_CORE_MONOSTATE_HPP
- #define ENTT_CORE_MONOSTATE_HPP
- // #include "../config/config.h"
- // #include "fwd.hpp"
- namespace entt {
- /**
- * @brief Minimal implementation of the monostate pattern.
- *
- * A minimal, yet complete configuration system built on top of the monostate
- * pattern. Thread safe by design, it works only with basic types like `int`s or
- * `bool`s.<br/>
- * Multiple types and therefore more than one value can be associated with a
- * single key. Because of this, users must pay attention to use the same type
- * both during an assignment and when they try to read back their data.
- * Otherwise, they can incur in unexpected results.
- */
- template<id_type>
- struct monostate {
- /**
- * @brief Assigns a value of a specific type to a given key.
- * @tparam Type Type of the value to assign.
- * @param val User data to assign to the given key.
- * @return This monostate object.
- */
- template<typename Type>
- monostate &operator=(Type val) noexcept {
- value<Type> = val;
- return *this;
- }
- /**
- * @brief Gets a value of a specific type for a given key.
- * @tparam Type Type of the value to get.
- * @return Stored value, if any.
- */
- template<typename Type>
- operator Type() const noexcept {
- return value<Type>;
- }
- private:
- template<typename Type>
- // NOLINTNEXTLINE(cppcoreguidelines-avoid-non-const-global-variables)
- inline static ENTT_MAYBE_ATOMIC(Type) value{};
- };
- /**
- * @brief Helper variable template.
- * @tparam Value Value used to differentiate between different variables.
- */
- template<id_type Value>
- // NOLINTNEXTLINE(cppcoreguidelines-avoid-non-const-global-variables)
- inline monostate<Value> monostate_v{};
- } // namespace entt
- #endif
- // #include "core/ranges.hpp"
- #ifndef ENTT_CORE_RANGES_HPP
- #define ENTT_CORE_RANGES_HPP
- #if __has_include(<version>)
- # include <version>
- #
- # if defined(__cpp_lib_ranges)
- # include <ranges>
- // # include "iterator.hpp"
- #ifndef ENTT_CORE_ITERATOR_HPP
- #define ENTT_CORE_ITERATOR_HPP
- #include <iterator>
- #include <memory>
- #include <type_traits>
- #include <utility>
- namespace entt {
- /**
- * @brief Helper type to use as pointer with input iterators.
- * @tparam Type of wrapped value.
- */
- template<typename Type>
- struct input_iterator_pointer final {
- /*! @brief Value type. */
- using value_type = Type;
- /*! @brief Pointer type. */
- using pointer = Type *;
- /*! @brief Reference type. */
- using reference = Type &;
- /**
- * @brief Constructs a proxy object by move.
- * @param val Value to use to initialize the proxy object.
- */
- constexpr input_iterator_pointer(value_type &&val) noexcept(std::is_nothrow_move_constructible_v<value_type>)
- : value{std::move(val)} {}
- /**
- * @brief Access operator for accessing wrapped values.
- * @return A pointer to the wrapped value.
- */
- [[nodiscard]] constexpr pointer operator->() noexcept {
- return std::addressof(value);
- }
- /**
- * @brief Dereference operator for accessing wrapped values.
- * @return A reference to the wrapped value.
- */
- [[nodiscard]] constexpr reference operator*() noexcept {
- return value;
- }
- private:
- Type value;
- };
- /**
- * @brief Plain iota iterator (waiting for C++20).
- * @tparam Type Value type.
- */
- template<typename Type>
- class iota_iterator final {
- static_assert(std::is_integral_v<Type>, "Not an integral type");
- public:
- /*! @brief Value type, likely an integral one. */
- using value_type = Type;
- /*! @brief Invalid pointer type. */
- using pointer = void;
- /*! @brief Non-reference type, same as value type. */
- using reference = value_type;
- /*! @brief Difference type. */
- using difference_type = std::ptrdiff_t;
- /*! @brief Iterator category. */
- using iterator_category = std::input_iterator_tag;
- /*! @brief Default constructor. */
- constexpr iota_iterator() noexcept
- : current{} {}
- /**
- * @brief Constructs an iota iterator from a given value.
- * @param init The initial value assigned to the iota iterator.
- */
- constexpr iota_iterator(const value_type init) noexcept
- : current{init} {}
- /**
- * @brief Pre-increment operator.
- * @return This iota iterator.
- */
- constexpr iota_iterator &operator++() noexcept {
- return ++current, *this;
- }
- /**
- * @brief Post-increment operator.
- * @return This iota iterator.
- */
- constexpr iota_iterator operator++(int) noexcept {
- const iota_iterator orig = *this;
- return ++(*this), orig;
- }
- /**
- * @brief Dereference operator.
- * @return The underlying value.
- */
- [[nodiscard]] constexpr reference operator*() const noexcept {
- return current;
- }
- private:
- value_type current;
- };
- /**
- * @brief Comparison operator.
- * @tparam Type Value type of the iota iterator.
- * @param lhs A properly initialized iota iterator.
- * @param rhs A properly initialized iota iterator.
- * @return True if the two iterators are identical, false otherwise.
- */
- template<typename Type>
- [[nodiscard]] constexpr bool operator==(const iota_iterator<Type> &lhs, const iota_iterator<Type> &rhs) noexcept {
- return *lhs == *rhs;
- }
- /**
- * @brief Comparison operator.
- * @tparam Type Value type of the iota iterator.
- * @param lhs A properly initialized iota iterator.
- * @param rhs A properly initialized iota iterator.
- * @return True if the two iterators differ, false otherwise.
- */
- template<typename Type>
- [[nodiscard]] constexpr bool operator!=(const iota_iterator<Type> &lhs, const iota_iterator<Type> &rhs) noexcept {
- return !(lhs == rhs);
- }
- /**
- * @brief Utility class to create an iterable object from a pair of iterators.
- * @tparam It Type of iterator.
- * @tparam Sentinel Type of sentinel.
- */
- template<typename It, typename Sentinel = It>
- struct iterable_adaptor final {
- /*! @brief Value type. */
- using value_type = typename std::iterator_traits<It>::value_type;
- /*! @brief Iterator type. */
- using iterator = It;
- /*! @brief Sentinel type. */
- using sentinel = Sentinel;
- /*! @brief Default constructor. */
- constexpr iterable_adaptor() noexcept(std::is_nothrow_default_constructible_v<iterator> && std::is_nothrow_default_constructible_v<sentinel>)
- : first{},
- last{} {}
- /**
- * @brief Creates an iterable object from a pair of iterators.
- * @param from Begin iterator.
- * @param to End iterator.
- */
- constexpr iterable_adaptor(iterator from, sentinel to) noexcept(std::is_nothrow_move_constructible_v<iterator> && std::is_nothrow_move_constructible_v<sentinel>)
- : first{std::move(from)},
- last{std::move(to)} {}
- /**
- * @brief Returns an iterator to the beginning.
- * @return An iterator to the first element of the range.
- */
- [[nodiscard]] constexpr iterator begin() const noexcept {
- return first;
- }
- /**
- * @brief Returns an iterator to the end.
- * @return An iterator to the element following the last element of the
- * range.
- */
- [[nodiscard]] constexpr sentinel end() const noexcept {
- return last;
- }
- /*! @copydoc begin */
- [[nodiscard]] constexpr iterator cbegin() const noexcept {
- return begin();
- }
- /*! @copydoc end */
- [[nodiscard]] constexpr sentinel cend() const noexcept {
- return end();
- }
- private:
- It first;
- Sentinel last;
- };
- } // namespace entt
- #endif
- template<class... Args>
- inline constexpr bool std::ranges::enable_borrowed_range<entt::iterable_adaptor<Args...>>{true};
- template<class... Args>
- inline constexpr bool std::ranges::enable_view<entt::iterable_adaptor<Args...>>{true};
- # endif
- #endif
- #endif
- // #include "core/tuple.hpp"
- #ifndef ENTT_CORE_TUPLE_HPP
- #define ENTT_CORE_TUPLE_HPP
- #include <tuple>
- #include <type_traits>
- #include <utility>
- namespace entt {
- /**
- * @brief Provides the member constant `value` to true if a given type is a
- * tuple, false otherwise.
- * @tparam Type The type to test.
- */
- template<typename Type>
- struct is_tuple: std::false_type {};
- /**
- * @copybrief is_tuple
- * @tparam Args Tuple template arguments.
- */
- template<typename... Args>
- struct is_tuple<std::tuple<Args...>>: std::true_type {};
- /**
- * @brief Helper variable template.
- * @tparam Type The type to test.
- */
- template<typename Type>
- inline constexpr bool is_tuple_v = is_tuple<Type>::value;
- /**
- * @brief Utility function to unwrap tuples of a single element.
- * @tparam Type Tuple type of any sizes.
- * @param value A tuple object of the given type.
- * @return The tuple itself if it contains more than one element, the first
- * element otherwise.
- */
- template<typename Type>
- constexpr decltype(auto) unwrap_tuple(Type &&value) noexcept {
- if constexpr(std::tuple_size_v<std::remove_reference_t<Type>> == 1u) {
- return std::get<0>(std::forward<Type>(value));
- } else {
- return std::forward<Type>(value);
- }
- }
- /**
- * @brief Utility class to forward-and-apply tuple objects.
- * @tparam Func Type of underlying invocable object.
- */
- template<typename Func>
- struct forward_apply: private Func {
- /**
- * @brief Constructs a forward-and-apply object.
- * @tparam Args Types of arguments to use to construct the new instance.
- * @param args Parameters to use to construct the instance.
- */
- template<typename... Args>
- constexpr forward_apply(Args &&...args) noexcept(std::is_nothrow_constructible_v<Func, Args...>)
- : Func{std::forward<Args>(args)...} {}
- /**
- * @brief Forwards and applies the arguments with the underlying function.
- * @tparam Type Tuple-like type to forward to the underlying function.
- * @param args Parameters to forward to the underlying function.
- * @return Return value of the underlying function, if any.
- */
- template<typename Type>
- constexpr decltype(auto) operator()(Type &&args) noexcept(noexcept(std::apply(std::declval<Func &>(), args))) {
- return std::apply(static_cast<Func &>(*this), std::forward<Type>(args));
- }
- /*! @copydoc operator()() */
- template<typename Type>
- constexpr decltype(auto) operator()(Type &&args) const noexcept(noexcept(std::apply(std::declval<const Func &>(), args))) {
- return std::apply(static_cast<const Func &>(*this), std::forward<Type>(args));
- }
- };
- /**
- * @brief Deduction guide.
- * @tparam Func Type of underlying invocable object.
- */
- template<typename Func>
- forward_apply(Func) -> forward_apply<std::remove_reference_t<std::remove_const_t<Func>>>;
- } // namespace entt
- #endif
- // #include "core/type_info.hpp"
- #ifndef ENTT_CORE_TYPE_INFO_HPP
- #define ENTT_CORE_TYPE_INFO_HPP
- #include <string_view>
- #include <type_traits>
- #include <utility>
- // #include "../config/config.h"
- // #include "fwd.hpp"
- // #include "hashed_string.hpp"
- namespace entt {
- /*! @cond TURN_OFF_DOXYGEN */
- namespace internal {
- struct ENTT_API type_index final {
- [[nodiscard]] static id_type next() noexcept {
- static ENTT_MAYBE_ATOMIC(id_type) value{};
- return value++;
- }
- };
- template<typename Type>
- [[nodiscard]] constexpr const char *pretty_function() noexcept {
- #if defined ENTT_PRETTY_FUNCTION
- return static_cast<const char *>(ENTT_PRETTY_FUNCTION);
- #else
- return "";
- #endif
- }
- template<typename Type>
- [[nodiscard]] constexpr auto stripped_type_name() noexcept {
- #if defined ENTT_PRETTY_FUNCTION
- const std::string_view full_name{pretty_function<Type>()};
- auto first = full_name.find_first_not_of(' ', full_name.find_first_of(ENTT_PRETTY_FUNCTION_PREFIX) + 1);
- auto value = full_name.substr(first, full_name.find_last_of(ENTT_PRETTY_FUNCTION_SUFFIX) - first);
- return value;
- #else
- return std::string_view{};
- #endif
- }
- template<typename Type, auto = stripped_type_name<Type>().find_first_of('.')>
- [[nodiscard]] constexpr std::string_view type_name(int) noexcept {
- constexpr auto value = stripped_type_name<Type>();
- return value;
- }
- template<typename Type>
- [[nodiscard]] std::string_view type_name(char) noexcept {
- static const auto value = stripped_type_name<Type>();
- return value;
- }
- template<typename Type, auto = stripped_type_name<Type>().find_first_of('.')>
- [[nodiscard]] constexpr id_type type_hash(int) noexcept {
- constexpr auto stripped = stripped_type_name<Type>();
- constexpr auto value = hashed_string::value(stripped.data(), stripped.size());
- return value;
- }
- template<typename Type>
- [[nodiscard]] id_type type_hash(char) noexcept {
- static const auto value = [](const auto stripped) {
- return hashed_string::value(stripped.data(), stripped.size());
- }(stripped_type_name<Type>());
- return value;
- }
- } // namespace internal
- /*! @endcond */
- /**
- * @brief Type sequential identifier.
- * @tparam Type Type for which to generate a sequential identifier.
- */
- template<typename Type, typename = void>
- struct ENTT_API type_index final {
- /**
- * @brief Returns the sequential identifier of a given type.
- * @return The sequential identifier of a given type.
- */
- [[nodiscard]] static id_type value() noexcept {
- static const id_type value = internal::type_index::next();
- return value;
- }
- /*! @copydoc value */
- [[nodiscard]] constexpr operator id_type() const noexcept {
- return value();
- }
- };
- /**
- * @brief Type hash.
- * @tparam Type Type for which to generate a hash value.
- */
- template<typename Type, typename = void>
- struct type_hash final {
- /**
- * @brief Returns the numeric representation of a given type.
- * @return The numeric representation of the given type.
- */
- #if defined ENTT_PRETTY_FUNCTION
- [[nodiscard]] static constexpr id_type value() noexcept {
- return internal::type_hash<Type>(0);
- #else
- [[nodiscard]] static constexpr id_type value() noexcept {
- return type_index<Type>::value();
- #endif
- }
- /*! @copydoc value */
- [[nodiscard]] constexpr operator id_type() const noexcept {
- return value();
- }
- };
- /**
- * @brief Type name.
- * @tparam Type Type for which to generate a name.
- */
- template<typename Type, typename = void>
- struct type_name final {
- /**
- * @brief Returns the name of a given type.
- * @return The name of the given type.
- */
- [[nodiscard]] static constexpr std::string_view value() noexcept {
- return internal::type_name<Type>(0);
- }
- /*! @copydoc value */
- [[nodiscard]] constexpr operator std::string_view() const noexcept {
- return value();
- }
- };
- /*! @brief Implementation specific information about a type. */
- struct type_info final {
- /**
- * @brief Constructs a type info object for a given type.
- * @tparam Type Type for which to construct a type info object.
- */
- template<typename Type>
- // NOLINTBEGIN(modernize-use-transparent-functors)
- constexpr type_info(std::in_place_type_t<Type>) noexcept
- : seq{type_index<std::remove_const_t<std::remove_reference_t<Type>>>::value()},
- identifier{type_hash<std::remove_const_t<std::remove_reference_t<Type>>>::value()},
- alias{type_name<std::remove_const_t<std::remove_reference_t<Type>>>::value()} {}
- // NOLINTEND(modernize-use-transparent-functors)
- /**
- * @brief Type index.
- * @return Type index.
- */
- [[nodiscard]] constexpr id_type index() const noexcept {
- return seq;
- }
- /**
- * @brief Type hash.
- * @return Type hash.
- */
- [[nodiscard]] constexpr id_type hash() const noexcept {
- return identifier;
- }
- /**
- * @brief Type name.
- * @return Type name.
- */
- [[nodiscard]] constexpr std::string_view name() const noexcept {
- return alias;
- }
- private:
- id_type seq;
- id_type identifier;
- std::string_view alias;
- };
- /**
- * @brief Compares the contents of two type info objects.
- * @param lhs A type info object.
- * @param rhs A type info object.
- * @return True if the two type info objects are identical, false otherwise.
- */
- [[nodiscard]] constexpr bool operator==(const type_info &lhs, const type_info &rhs) noexcept {
- return lhs.hash() == rhs.hash();
- }
- /**
- * @brief Compares the contents of two type info objects.
- * @param lhs A type info object.
- * @param rhs A type info object.
- * @return True if the two type info objects differ, false otherwise.
- */
- [[nodiscard]] constexpr bool operator!=(const type_info &lhs, const type_info &rhs) noexcept {
- return !(lhs == rhs);
- }
- /**
- * @brief Compares two type info objects.
- * @param lhs A valid type info object.
- * @param rhs A valid type info object.
- * @return True if the first element is less than the second, false otherwise.
- */
- [[nodiscard]] constexpr bool operator<(const type_info &lhs, const type_info &rhs) noexcept {
- return lhs.index() < rhs.index();
- }
- /**
- * @brief Compares two type info objects.
- * @param lhs A valid type info object.
- * @param rhs A valid type info object.
- * @return True if the first element is less than or equal to the second, false
- * otherwise.
- */
- [[nodiscard]] constexpr bool operator<=(const type_info &lhs, const type_info &rhs) noexcept {
- return !(rhs < lhs);
- }
- /**
- * @brief Compares two type info objects.
- * @param lhs A valid type info object.
- * @param rhs A valid type info object.
- * @return True if the first element is greater than the second, false
- * otherwise.
- */
- [[nodiscard]] constexpr bool operator>(const type_info &lhs, const type_info &rhs) noexcept {
- return rhs < lhs;
- }
- /**
- * @brief Compares two type info objects.
- * @param lhs A valid type info object.
- * @param rhs A valid type info object.
- * @return True if the first element is greater than or equal to the second,
- * false otherwise.
- */
- [[nodiscard]] constexpr bool operator>=(const type_info &lhs, const type_info &rhs) noexcept {
- return !(lhs < rhs);
- }
- /**
- * @brief Returns the type info object associated to a given type.
- *
- * The returned element refers to an object with static storage duration.<br/>
- * The type doesn't need to be a complete type. If the type is a reference, the
- * result refers to the referenced type. In all cases, top-level cv-qualifiers
- * are ignored.
- *
- * @tparam Type Type for which to generate a type info object.
- * @return A reference to a properly initialized type info object.
- */
- template<typename Type>
- [[nodiscard]] const type_info &type_id() noexcept {
- if constexpr(std::is_same_v<Type, std::remove_const_t<std::remove_reference_t<Type>>>) {
- static const type_info instance{std::in_place_type<Type>};
- return instance;
- } else {
- return type_id<std::remove_const_t<std::remove_reference_t<Type>>>();
- }
- }
- /*! @copydoc type_id */
- template<typename Type>
- // NOLINTNEXTLINE(cppcoreguidelines-missing-std-forward)
- [[nodiscard]] const type_info &type_id(Type &&) noexcept {
- return type_id<std::remove_const_t<std::remove_reference_t<Type>>>();
- }
- } // namespace entt
- #endif
- // #include "core/type_traits.hpp"
- #ifndef ENTT_CORE_TYPE_TRAITS_HPP
- #define ENTT_CORE_TYPE_TRAITS_HPP
- #include <cstddef>
- #include <iterator>
- #include <tuple>
- #include <type_traits>
- #include <utility>
- // #include "../config/config.h"
- // #include "fwd.hpp"
- namespace entt {
- /**
- * @brief Utility class to disambiguate overloaded functions.
- * @tparam N Number of choices available.
- */
- template<std::size_t N>
- struct choice_t
- // unfortunately, doxygen cannot parse such a construct
- : /*! @cond TURN_OFF_DOXYGEN */ choice_t<N - 1> /*! @endcond */
- {};
- /*! @copybrief choice_t */
- template<>
- struct choice_t<0> {};
- /**
- * @brief Variable template for the choice trick.
- * @tparam N Number of choices available.
- */
- template<std::size_t N>
- inline constexpr choice_t<N> choice{};
- /**
- * @brief Identity type trait.
- *
- * Useful to establish non-deduced contexts in template argument deduction
- * (waiting for C++20) or to provide types through function arguments.
- *
- * @tparam Type A type.
- */
- template<typename Type>
- struct type_identity {
- /*! @brief Identity type. */
- using type = Type;
- };
- /**
- * @brief Helper type.
- * @tparam Type A type.
- */
- template<typename Type>
- using type_identity_t = typename type_identity<Type>::type;
- /**
- * @brief A type-only `sizeof` wrapper that returns 0 where `sizeof` complains.
- * @tparam Type The type of which to return the size.
- */
- template<typename Type, typename = void>
- struct size_of: std::integral_constant<std::size_t, 0u> {};
- /*! @copydoc size_of */
- template<typename Type>
- struct size_of<Type, std::void_t<decltype(sizeof(Type))>>
- // NOLINTNEXTLINE(bugprone-sizeof-expression)
- : std::integral_constant<std::size_t, sizeof(Type)> {};
- /**
- * @brief Helper variable template.
- * @tparam Type The type of which to return the size.
- */
- template<typename Type>
- inline constexpr std::size_t size_of_v = size_of<Type>::value;
- /**
- * @brief Using declaration to be used to _repeat_ the same type a number of
- * times equal to the size of a given parameter pack.
- * @tparam Type A type to repeat.
- */
- template<typename Type, typename>
- using unpack_as_type = Type;
- /**
- * @brief Helper variable template to be used to _repeat_ the same value a
- * number of times equal to the size of a given parameter pack.
- * @tparam Value A value to repeat.
- */
- template<auto Value, typename>
- inline constexpr auto unpack_as_value = Value;
- /**
- * @brief Wraps a static constant.
- * @tparam Value A static constant.
- */
- template<auto Value>
- using integral_constant = std::integral_constant<decltype(Value), Value>;
- /**
- * @brief Alias template to facilitate the creation of named values.
- * @tparam Value A constant value at least convertible to `id_type`.
- */
- template<id_type Value>
- using tag = integral_constant<Value>;
- /**
- * @brief A class to use to push around lists of types, nothing more.
- * @tparam Type Types provided by the type list.
- */
- template<typename... Type>
- struct type_list {
- /*! @brief Type list type. */
- using type = type_list;
- /*! @brief Compile-time number of elements in the type list. */
- static constexpr auto size = sizeof...(Type);
- };
- /*! @brief Primary template isn't defined on purpose. */
- template<std::size_t, typename>
- struct type_list_element;
- /**
- * @brief Provides compile-time indexed access to the types of a type list.
- * @tparam Index Index of the type to return.
- * @tparam First First type provided by the type list.
- * @tparam Other Other types provided by the type list.
- */
- template<std::size_t Index, typename First, typename... Other>
- struct type_list_element<Index, type_list<First, Other...>>
- : type_list_element<Index - 1u, type_list<Other...>> {};
- /**
- * @brief Provides compile-time indexed access to the types of a type list.
- * @tparam First First type provided by the type list.
- * @tparam Other Other types provided by the type list.
- */
- template<typename First, typename... Other>
- struct type_list_element<0u, type_list<First, Other...>> {
- /*! @brief Searched type. */
- using type = First;
- };
- /**
- * @brief Helper type.
- * @tparam Index Index of the type to return.
- * @tparam List Type list to search into.
- */
- template<std::size_t Index, typename List>
- using type_list_element_t = typename type_list_element<Index, List>::type;
- /*! @brief Primary template isn't defined on purpose. */
- template<typename, typename>
- struct type_list_index;
- /**
- * @brief Provides compile-time type access to the types of a type list.
- * @tparam Type Type to look for and for which to return the index.
- * @tparam First First type provided by the type list.
- * @tparam Other Other types provided by the type list.
- */
- template<typename Type, typename First, typename... Other>
- struct type_list_index<Type, type_list<First, Other...>> {
- /*! @brief Unsigned integer type. */
- using value_type = std::size_t;
- /*! @brief Compile-time position of the given type in the sublist. */
- static constexpr value_type value = 1u + type_list_index<Type, type_list<Other...>>::value;
- };
- /**
- * @brief Provides compile-time type access to the types of a type list.
- * @tparam Type Type to look for and for which to return the index.
- * @tparam Other Other types provided by the type list.
- */
- template<typename Type, typename... Other>
- struct type_list_index<Type, type_list<Type, Other...>> {
- static_assert(type_list_index<Type, type_list<Other...>>::value == sizeof...(Other), "Non-unique type");
- /*! @brief Unsigned integer type. */
- using value_type = std::size_t;
- /*! @brief Compile-time position of the given type in the sublist. */
- static constexpr value_type value = 0u;
- };
- /**
- * @brief Provides compile-time type access to the types of a type list.
- * @tparam Type Type to look for and for which to return the index.
- */
- template<typename Type>
- struct type_list_index<Type, type_list<>> {
- /*! @brief Unsigned integer type. */
- using value_type = std::size_t;
- /*! @brief Compile-time position of the given type in the sublist. */
- static constexpr value_type value = 0u;
- };
- /**
- * @brief Helper variable template.
- * @tparam List Type list.
- * @tparam Type Type to look for and for which to return the index.
- */
- template<typename Type, typename List>
- inline constexpr std::size_t type_list_index_v = type_list_index<Type, List>::value;
- /**
- * @brief Concatenates multiple type lists.
- * @tparam Type Types provided by the first type list.
- * @tparam Other Types provided by the second type list.
- * @return A type list composed by the types of both the type lists.
- */
- template<typename... Type, typename... Other>
- constexpr type_list<Type..., Other...> operator+(type_list<Type...>, type_list<Other...>) {
- return {};
- }
- /*! @brief Primary template isn't defined on purpose. */
- template<typename...>
- struct type_list_cat;
- /*! @brief Concatenates multiple type lists. */
- template<>
- struct type_list_cat<> {
- /*! @brief A type list composed by the types of all the type lists. */
- using type = type_list<>;
- };
- /**
- * @brief Concatenates multiple type lists.
- * @tparam Type Types provided by the first type list.
- * @tparam Other Types provided by the second type list.
- * @tparam List Other type lists, if any.
- */
- template<typename... Type, typename... Other, typename... List>
- struct type_list_cat<type_list<Type...>, type_list<Other...>, List...> {
- /*! @brief A type list composed by the types of all the type lists. */
- using type = typename type_list_cat<type_list<Type..., Other...>, List...>::type;
- };
- /**
- * @brief Concatenates multiple type lists.
- * @tparam Type Types provided by the type list.
- */
- template<typename... Type>
- struct type_list_cat<type_list<Type...>> {
- /*! @brief A type list composed by the types of all the type lists. */
- using type = type_list<Type...>;
- };
- /**
- * @brief Helper type.
- * @tparam List Type lists to concatenate.
- */
- template<typename... List>
- using type_list_cat_t = typename type_list_cat<List...>::type;
- /*! @cond TURN_OFF_DOXYGEN */
- namespace internal {
- template<typename...>
- struct type_list_unique;
- template<typename First, typename... Other, typename... Type>
- struct type_list_unique<type_list<First, Other...>, Type...>
- : std::conditional_t<(std::is_same_v<First, Type> || ...), type_list_unique<type_list<Other...>, Type...>, type_list_unique<type_list<Other...>, Type..., First>> {};
- template<typename... Type>
- struct type_list_unique<type_list<>, Type...> {
- using type = type_list<Type...>;
- };
- } // namespace internal
- /*! @endcond */
- /**
- * @brief Removes duplicates types from a type list.
- * @tparam List Type list.
- */
- template<typename List>
- struct type_list_unique {
- /*! @brief A type list without duplicate types. */
- using type = typename internal::type_list_unique<List>::type;
- };
- /**
- * @brief Helper type.
- * @tparam List Type list.
- */
- template<typename List>
- using type_list_unique_t = typename type_list_unique<List>::type;
- /**
- * @brief Provides the member constant `value` to true if a type list contains a
- * given type, false otherwise.
- * @tparam List Type list.
- * @tparam Type Type to look for.
- */
- template<typename List, typename Type>
- struct type_list_contains;
- /**
- * @copybrief type_list_contains
- * @tparam Type Types provided by the type list.
- * @tparam Other Type to look for.
- */
- template<typename... Type, typename Other>
- struct type_list_contains<type_list<Type...>, Other>
- : std::bool_constant<(std::is_same_v<Type, Other> || ...)> {};
- /**
- * @brief Helper variable template.
- * @tparam List Type list.
- * @tparam Type Type to look for.
- */
- template<typename List, typename Type>
- inline constexpr bool type_list_contains_v = type_list_contains<List, Type>::value;
- /*! @brief Primary template isn't defined on purpose. */
- template<typename...>
- struct type_list_diff;
- /**
- * @brief Computes the difference between two type lists.
- * @tparam Type Types provided by the first type list.
- * @tparam Other Types provided by the second type list.
- */
- template<typename... Type, typename... Other>
- struct type_list_diff<type_list<Type...>, type_list<Other...>> {
- /*! @brief A type list that is the difference between the two type lists. */
- using type = type_list_cat_t<std::conditional_t<type_list_contains_v<type_list<Other...>, Type>, type_list<>, type_list<Type>>...>;
- };
- /**
- * @brief Helper type.
- * @tparam List Type lists between which to compute the difference.
- */
- template<typename... List>
- using type_list_diff_t = typename type_list_diff<List...>::type;
- /*! @brief Primary template isn't defined on purpose. */
- template<typename, template<typename...> class>
- struct type_list_transform;
- /**
- * @brief Applies a given _function_ to a type list and generate a new list.
- * @tparam Type Types provided by the type list.
- * @tparam Op Unary operation as template class with a type member named `type`.
- */
- template<typename... Type, template<typename...> class Op>
- struct type_list_transform<type_list<Type...>, Op> {
- /*! @brief Resulting type list after applying the transform function. */
- // NOLINTNEXTLINE(modernize-type-traits)
- using type = type_list<typename Op<Type>::type...>;
- };
- /**
- * @brief Helper type.
- * @tparam List Type list.
- * @tparam Op Unary operation as template class with a type member named `type`.
- */
- template<typename List, template<typename...> class Op>
- using type_list_transform_t = typename type_list_transform<List, Op>::type;
- /**
- * @brief A class to use to push around lists of constant values, nothing more.
- * @tparam Value Values provided by the value list.
- */
- template<auto... Value>
- struct value_list {
- /*! @brief Value list type. */
- using type = value_list;
- /*! @brief Compile-time number of elements in the value list. */
- static constexpr auto size = sizeof...(Value);
- };
- /*! @brief Primary template isn't defined on purpose. */
- template<std::size_t, typename>
- struct value_list_element;
- /**
- * @brief Provides compile-time indexed access to the values of a value list.
- * @tparam Index Index of the value to return.
- * @tparam Value First value provided by the value list.
- * @tparam Other Other values provided by the value list.
- */
- template<std::size_t Index, auto Value, auto... Other>
- struct value_list_element<Index, value_list<Value, Other...>>
- : value_list_element<Index - 1u, value_list<Other...>> {};
- /**
- * @brief Provides compile-time indexed access to the types of a type list.
- * @tparam Value First value provided by the value list.
- * @tparam Other Other values provided by the value list.
- */
- template<auto Value, auto... Other>
- struct value_list_element<0u, value_list<Value, Other...>> {
- /*! @brief Searched type. */
- using type = decltype(Value);
- /*! @brief Searched value. */
- static constexpr auto value = Value;
- };
- /**
- * @brief Helper type.
- * @tparam Index Index of the type to return.
- * @tparam List Value list to search into.
- */
- template<std::size_t Index, typename List>
- using value_list_element_t = typename value_list_element<Index, List>::type;
- /**
- * @brief Helper type.
- * @tparam Index Index of the value to return.
- * @tparam List Value list to search into.
- */
- template<std::size_t Index, typename List>
- inline constexpr auto value_list_element_v = value_list_element<Index, List>::value;
- /*! @brief Primary template isn't defined on purpose. */
- template<auto, typename>
- struct value_list_index;
- /**
- * @brief Provides compile-time type access to the values of a value list.
- * @tparam Value Value to look for and for which to return the index.
- * @tparam First First value provided by the value list.
- * @tparam Other Other values provided by the value list.
- */
- template<auto Value, auto First, auto... Other>
- struct value_list_index<Value, value_list<First, Other...>> {
- /*! @brief Unsigned integer type. */
- using value_type = std::size_t;
- /*! @brief Compile-time position of the given value in the sublist. */
- static constexpr value_type value = 1u + value_list_index<Value, value_list<Other...>>::value;
- };
- /**
- * @brief Provides compile-time type access to the values of a value list.
- * @tparam Value Value to look for and for which to return the index.
- * @tparam Other Other values provided by the value list.
- */
- template<auto Value, auto... Other>
- struct value_list_index<Value, value_list<Value, Other...>> {
- static_assert(value_list_index<Value, value_list<Other...>>::value == sizeof...(Other), "Non-unique type");
- /*! @brief Unsigned integer type. */
- using value_type = std::size_t;
- /*! @brief Compile-time position of the given value in the sublist. */
- static constexpr value_type value = 0u;
- };
- /**
- * @brief Provides compile-time type access to the values of a value list.
- * @tparam Value Value to look for and for which to return the index.
- */
- template<auto Value>
- struct value_list_index<Value, value_list<>> {
- /*! @brief Unsigned integer type. */
- using value_type = std::size_t;
- /*! @brief Compile-time position of the given type in the sublist. */
- static constexpr value_type value = 0u;
- };
- /**
- * @brief Helper variable template.
- * @tparam List Value list.
- * @tparam Value Value to look for and for which to return the index.
- */
- template<auto Value, typename List>
- inline constexpr std::size_t value_list_index_v = value_list_index<Value, List>::value;
- /**
- * @brief Concatenates multiple value lists.
- * @tparam Value Values provided by the first value list.
- * @tparam Other Values provided by the second value list.
- * @return A value list composed by the values of both the value lists.
- */
- template<auto... Value, auto... Other>
- constexpr value_list<Value..., Other...> operator+(value_list<Value...>, value_list<Other...>) {
- return {};
- }
- /*! @brief Primary template isn't defined on purpose. */
- template<typename...>
- struct value_list_cat;
- /*! @brief Concatenates multiple value lists. */
- template<>
- struct value_list_cat<> {
- /*! @brief A value list composed by the values of all the value lists. */
- using type = value_list<>;
- };
- /**
- * @brief Concatenates multiple value lists.
- * @tparam Value Values provided by the first value list.
- * @tparam Other Values provided by the second value list.
- * @tparam List Other value lists, if any.
- */
- template<auto... Value, auto... Other, typename... List>
- struct value_list_cat<value_list<Value...>, value_list<Other...>, List...> {
- /*! @brief A value list composed by the values of all the value lists. */
- using type = typename value_list_cat<value_list<Value..., Other...>, List...>::type;
- };
- /**
- * @brief Concatenates multiple value lists.
- * @tparam Value Values provided by the value list.
- */
- template<auto... Value>
- struct value_list_cat<value_list<Value...>> {
- /*! @brief A value list composed by the values of all the value lists. */
- using type = value_list<Value...>;
- };
- /**
- * @brief Helper type.
- * @tparam List Value lists to concatenate.
- */
- template<typename... List>
- using value_list_cat_t = typename value_list_cat<List...>::type;
- /*! @brief Primary template isn't defined on purpose. */
- template<typename>
- struct value_list_unique;
- /**
- * @brief Removes duplicates values from a value list.
- * @tparam Value One of the values provided by the given value list.
- * @tparam Other The other values provided by the given value list.
- */
- template<auto Value, auto... Other>
- struct value_list_unique<value_list<Value, Other...>> {
- /*! @brief A value list without duplicate types. */
- using type = std::conditional_t<
- ((Value == Other) || ...),
- typename value_list_unique<value_list<Other...>>::type,
- value_list_cat_t<value_list<Value>, typename value_list_unique<value_list<Other...>>::type>>;
- };
- /*! @brief Removes duplicates values from a value list. */
- template<>
- struct value_list_unique<value_list<>> {
- /*! @brief A value list without duplicate types. */
- using type = value_list<>;
- };
- /**
- * @brief Helper type.
- * @tparam Type A value list.
- */
- template<typename Type>
- using value_list_unique_t = typename value_list_unique<Type>::type;
- /**
- * @brief Provides the member constant `value` to true if a value list contains
- * a given value, false otherwise.
- * @tparam List Value list.
- * @tparam Value Value to look for.
- */
- template<typename List, auto Value>
- struct value_list_contains;
- /**
- * @copybrief value_list_contains
- * @tparam Value Values provided by the value list.
- * @tparam Other Value to look for.
- */
- template<auto... Value, auto Other>
- struct value_list_contains<value_list<Value...>, Other>
- : std::bool_constant<((Value == Other) || ...)> {};
- /**
- * @brief Helper variable template.
- * @tparam List Value list.
- * @tparam Value Value to look for.
- */
- template<typename List, auto Value>
- inline constexpr bool value_list_contains_v = value_list_contains<List, Value>::value;
- /*! @brief Primary template isn't defined on purpose. */
- template<typename...>
- struct value_list_diff;
- /**
- * @brief Computes the difference between two value lists.
- * @tparam Value Values provided by the first value list.
- * @tparam Other Values provided by the second value list.
- */
- template<auto... Value, auto... Other>
- struct value_list_diff<value_list<Value...>, value_list<Other...>> {
- /*! @brief A value list that is the difference between the two value lists. */
- using type = value_list_cat_t<std::conditional_t<value_list_contains_v<value_list<Other...>, Value>, value_list<>, value_list<Value>>...>;
- };
- /**
- * @brief Helper type.
- * @tparam List Value lists between which to compute the difference.
- */
- template<typename... List>
- using value_list_diff_t = typename value_list_diff<List...>::type;
- /*! @brief Same as std::is_invocable, but with tuples. */
- template<typename, typename>
- struct is_applicable: std::false_type {};
- /**
- * @copybrief is_applicable
- * @tparam Func A valid function type.
- * @tparam Tuple Tuple-like type.
- * @tparam Args The list of arguments to use to probe the function type.
- */
- template<typename Func, template<typename...> class Tuple, typename... Args>
- struct is_applicable<Func, Tuple<Args...>>: std::is_invocable<Func, Args...> {};
- /**
- * @copybrief is_applicable
- * @tparam Func A valid function type.
- * @tparam Tuple Tuple-like type.
- * @tparam Args The list of arguments to use to probe the function type.
- */
- template<typename Func, template<typename...> class Tuple, typename... Args>
- struct is_applicable<Func, const Tuple<Args...>>: std::is_invocable<Func, Args...> {};
- /**
- * @brief Helper variable template.
- * @tparam Func A valid function type.
- * @tparam Args The list of arguments to use to probe the function type.
- */
- template<typename Func, typename Args>
- inline constexpr bool is_applicable_v = is_applicable<Func, Args>::value;
- /*! @brief Same as std::is_invocable_r, but with tuples for arguments. */
- template<typename, typename, typename>
- struct is_applicable_r: std::false_type {};
- /**
- * @copybrief is_applicable_r
- * @tparam Ret The type to which the return type of the function should be
- * convertible.
- * @tparam Func A valid function type.
- * @tparam Args The list of arguments to use to probe the function type.
- */
- template<typename Ret, typename Func, typename... Args>
- struct is_applicable_r<Ret, Func, std::tuple<Args...>>: std::is_invocable_r<Ret, Func, Args...> {};
- /**
- * @brief Helper variable template.
- * @tparam Ret The type to which the return type of the function should be
- * convertible.
- * @tparam Func A valid function type.
- * @tparam Args The list of arguments to use to probe the function type.
- */
- template<typename Ret, typename Func, typename Args>
- inline constexpr bool is_applicable_r_v = is_applicable_r<Ret, Func, Args>::value;
- /**
- * @brief Provides the member constant `value` to true if a given type is
- * complete, false otherwise.
- * @tparam Type The type to test.
- */
- template<typename Type, typename = void>
- struct is_complete: std::false_type {};
- /*! @copydoc is_complete */
- template<typename Type>
- struct is_complete<Type, std::void_t<decltype(sizeof(Type))>>: std::true_type {};
- /**
- * @brief Helper variable template.
- * @tparam Type The type to test.
- */
- template<typename Type>
- inline constexpr bool is_complete_v = is_complete<Type>::value;
- /**
- * @brief Provides the member constant `value` to true if a given type is an
- * iterator, false otherwise.
- * @tparam Type The type to test.
- */
- template<typename Type, typename = void>
- struct is_iterator: std::false_type {};
- /*! @cond TURN_OFF_DOXYGEN */
- namespace internal {
- template<typename, typename = void>
- struct has_iterator_category: std::false_type {};
- template<typename Type>
- struct has_iterator_category<Type, std::void_t<typename std::iterator_traits<Type>::iterator_category>>: std::true_type {};
- } // namespace internal
- /*! @endcond */
- /*! @copydoc is_iterator */
- template<typename Type>
- struct is_iterator<Type, std::enable_if_t<!std::is_void_v<std::remove_const_t<std::remove_pointer_t<Type>>>>>
- : internal::has_iterator_category<Type> {};
- /**
- * @brief Helper variable template.
- * @tparam Type The type to test.
- */
- template<typename Type>
- inline constexpr bool is_iterator_v = is_iterator<Type>::value;
- /**
- * @brief Provides the member constant `value` to true if a given type is both
- * an empty and non-final class, false otherwise.
- * @tparam Type The type to test
- */
- template<typename Type>
- struct is_ebco_eligible
- : std::bool_constant<std::is_empty_v<Type> && !std::is_final_v<Type>> {};
- /**
- * @brief Helper variable template.
- * @tparam Type The type to test.
- */
- template<typename Type>
- inline constexpr bool is_ebco_eligible_v = is_ebco_eligible<Type>::value;
- /**
- * @brief Provides the member constant `value` to true if `Type::is_transparent`
- * is valid and denotes a type, false otherwise.
- * @tparam Type The type to test.
- */
- template<typename Type, typename = void>
- struct is_transparent: std::false_type {};
- /*! @copydoc is_transparent */
- template<typename Type>
- struct is_transparent<Type, std::void_t<typename Type::is_transparent>>: std::true_type {};
- /**
- * @brief Helper variable template.
- * @tparam Type The type to test.
- */
- template<typename Type>
- inline constexpr bool is_transparent_v = is_transparent<Type>::value;
- /*! @cond TURN_OFF_DOXYGEN */
- namespace internal {
- template<typename, typename = void>
- struct has_tuple_size_value: std::false_type {};
- template<typename Type>
- struct has_tuple_size_value<Type, std::void_t<decltype(std::tuple_size<const Type>::value)>>: std::true_type {};
- template<typename, typename = void>
- struct has_value_type: std::false_type {};
- template<typename Type>
- struct has_value_type<Type, std::void_t<typename Type::value_type>>: std::true_type {};
- template<typename>
- [[nodiscard]] constexpr bool dispatch_is_equality_comparable();
- template<typename Type, std::size_t... Index>
- [[nodiscard]] constexpr bool unpack_maybe_equality_comparable(std::index_sequence<Index...>) {
- return (dispatch_is_equality_comparable<std::tuple_element_t<Index, Type>>() && ...);
- }
- template<typename>
- [[nodiscard]] constexpr bool maybe_equality_comparable(char) {
- return false;
- }
- template<typename Type>
- [[nodiscard]] constexpr auto maybe_equality_comparable(int) -> decltype(std::declval<Type>() == std::declval<Type>()) {
- return true;
- }
- template<typename Type>
- [[nodiscard]] constexpr bool dispatch_is_equality_comparable() {
- // NOLINTBEGIN(modernize-use-transparent-functors)
- if constexpr(std::is_array_v<Type>) {
- return false;
- } else if constexpr(is_complete_v<std::tuple_size<std::remove_const_t<Type>>>) {
- if constexpr(has_tuple_size_value<Type>::value) {
- return maybe_equality_comparable<Type>(0) && unpack_maybe_equality_comparable<Type>(std::make_index_sequence<std::tuple_size<Type>::value>{});
- } else {
- return maybe_equality_comparable<Type>(0);
- }
- } else if constexpr(has_value_type<Type>::value) {
- if constexpr(is_iterator_v<Type> || std::is_same_v<typename Type::value_type, Type> || dispatch_is_equality_comparable<typename Type::value_type>()) {
- return maybe_equality_comparable<Type>(0);
- } else {
- return false;
- }
- } else {
- return maybe_equality_comparable<Type>(0);
- }
- // NOLINTEND(modernize-use-transparent-functors)
- }
- } // namespace internal
- /*! @endcond */
- /**
- * @brief Provides the member constant `value` to true if a given type is
- * equality comparable, false otherwise.
- * @tparam Type The type to test.
- */
- template<typename Type>
- struct is_equality_comparable: std::bool_constant<internal::dispatch_is_equality_comparable<Type>()> {};
- /*! @copydoc is_equality_comparable */
- template<typename Type>
- struct is_equality_comparable<const Type>: is_equality_comparable<Type> {};
- /**
- * @brief Helper variable template.
- * @tparam Type The type to test.
- */
- template<typename Type>
- inline constexpr bool is_equality_comparable_v = is_equality_comparable<Type>::value;
- /**
- * @brief Transcribes the constness of a type to another type.
- * @tparam To The type to which to transcribe the constness.
- * @tparam From The type from which to transcribe the constness.
- */
- template<typename To, typename From>
- struct constness_as {
- /*! @brief The type resulting from the transcription of the constness. */
- using type = std::remove_const_t<To>;
- };
- /*! @copydoc constness_as */
- template<typename To, typename From>
- struct constness_as<To, const From> {
- /*! @brief The type resulting from the transcription of the constness. */
- using type = const To;
- };
- /**
- * @brief Alias template to facilitate the transcription of the constness.
- * @tparam To The type to which to transcribe the constness.
- * @tparam From The type from which to transcribe the constness.
- */
- template<typename To, typename From>
- using constness_as_t = typename constness_as<To, From>::type;
- /**
- * @brief Extracts the class of a non-static member object or function.
- * @tparam Member A pointer to a non-static member object or function.
- */
- template<typename Member>
- class member_class {
- static_assert(std::is_member_pointer_v<Member>, "Invalid pointer type to non-static member object or function");
- template<typename Class, typename Ret, typename... Args>
- static Class *clazz(Ret (Class::*)(Args...));
- template<typename Class, typename Ret, typename... Args>
- static Class *clazz(Ret (Class::*)(Args...) const);
- template<typename Class, typename Type>
- static Class *clazz(Type Class::*);
- public:
- /*! @brief The class of the given non-static member object or function. */
- using type = std::remove_pointer_t<decltype(clazz(std::declval<Member>()))>;
- };
- /**
- * @brief Helper type.
- * @tparam Member A pointer to a non-static member object or function.
- */
- template<typename Member>
- using member_class_t = typename member_class<Member>::type;
- /**
- * @brief Extracts the n-th argument of a _callable_ type.
- * @tparam Index The index of the argument to extract.
- * @tparam Candidate A valid _callable_ type.
- */
- template<std::size_t Index, typename Candidate>
- class nth_argument {
- template<typename Ret, typename... Args>
- static constexpr type_list<Args...> pick_up(Ret (*)(Args...));
- template<typename Ret, typename Class, typename... Args>
- static constexpr type_list<Args...> pick_up(Ret (Class ::*)(Args...));
- template<typename Ret, typename Class, typename... Args>
- static constexpr type_list<Args...> pick_up(Ret (Class ::*)(Args...) const);
- template<typename Type, typename Class>
- static constexpr type_list<Type> pick_up(Type Class ::*);
- template<typename Type>
- static constexpr decltype(pick_up(&Type::operator())) pick_up(Type &&);
- public:
- /*! @brief N-th argument of the _callable_ type. */
- using type = type_list_element_t<Index, decltype(pick_up(std::declval<Candidate>()))>;
- };
- /**
- * @brief Helper type.
- * @tparam Index The index of the argument to extract.
- * @tparam Candidate A valid function, member function or data member type.
- */
- template<std::size_t Index, typename Candidate>
- using nth_argument_t = typename nth_argument<Index, Candidate>::type;
- } // namespace entt
- template<typename... Type>
- struct std::tuple_size<entt::type_list<Type...>>: std::integral_constant<std::size_t, entt::type_list<Type...>::size> {};
- template<std::size_t Index, typename... Type>
- struct std::tuple_element<Index, entt::type_list<Type...>>: entt::type_list_element<Index, entt::type_list<Type...>> {};
- template<auto... Value>
- struct std::tuple_size<entt::value_list<Value...>>: std::integral_constant<std::size_t, entt::value_list<Value...>::size> {};
- template<std::size_t Index, auto... Value>
- struct std::tuple_element<Index, entt::value_list<Value...>>: entt::value_list_element<Index, entt::value_list<Value...>> {};
- #endif
- // #include "core/utility.hpp"
- #ifndef ENTT_CORE_UTILITY_HPP
- #define ENTT_CORE_UTILITY_HPP
- #include <type_traits>
- #include <utility>
- namespace entt {
- /*! @brief Identity function object (waiting for C++20). */
- struct identity {
- /*! @brief Indicates that this is a transparent function object. */
- using is_transparent = void;
- /**
- * @brief Returns its argument unchanged.
- * @tparam Type Type of the argument.
- * @param value The actual argument.
- * @return The submitted value as-is.
- */
- template<typename Type>
- [[nodiscard]] constexpr Type &&operator()(Type &&value) const noexcept {
- return std::forward<Type>(value);
- }
- };
- /**
- * @brief Constant utility to disambiguate overloaded members of a class.
- * @tparam Type Type of the desired overload.
- * @tparam Class Type of class to which the member belongs.
- * @param member A valid pointer to a member.
- * @return Pointer to the member.
- */
- template<typename Type, typename Class>
- [[nodiscard]] constexpr auto overload(Type Class::*member) noexcept {
- return member;
- }
- /**
- * @brief Constant utility to disambiguate overloaded functions.
- * @tparam Func Function type of the desired overload.
- * @param func A valid pointer to a function.
- * @return Pointer to the function.
- */
- template<typename Func>
- [[nodiscard]] constexpr auto overload(Func *func) noexcept {
- return func;
- }
- /**
- * @brief Helper type for visitors.
- * @tparam Func Types of function objects.
- */
- template<typename... Func>
- struct overloaded: Func... {
- using Func::operator()...;
- };
- /**
- * @brief Deduction guide.
- * @tparam Func Types of function objects.
- */
- template<typename... Func>
- overloaded(Func...) -> overloaded<Func...>;
- /**
- * @brief Basic implementation of a y-combinator.
- * @tparam Func Type of a potentially recursive function.
- */
- template<typename Func>
- struct y_combinator {
- /**
- * @brief Constructs a y-combinator from a given function.
- * @param recursive A potentially recursive function.
- */
- constexpr y_combinator(Func recursive) noexcept(std::is_nothrow_move_constructible_v<Func>)
- : func{std::move(recursive)} {}
- /**
- * @brief Invokes a y-combinator and therefore its underlying function.
- * @tparam Args Types of arguments to use to invoke the underlying function.
- * @param args Parameters to use to invoke the underlying function.
- * @return Return value of the underlying function, if any.
- */
- template<typename... Args>
- constexpr decltype(auto) operator()(Args &&...args) const noexcept(std::is_nothrow_invocable_v<Func, const y_combinator &, Args...>) {
- return func(*this, std::forward<Args>(args)...);
- }
- /*! @copydoc operator()() */
- template<typename... Args>
- constexpr decltype(auto) operator()(Args &&...args) noexcept(std::is_nothrow_invocable_v<Func, y_combinator &, Args...>) {
- return func(*this, std::forward<Args>(args)...);
- }
- private:
- Func func;
- };
- } // namespace entt
- #endif
- // #include "entity/component.hpp"
- #ifndef ENTT_ENTITY_COMPONENT_HPP
- #define ENTT_ENTITY_COMPONENT_HPP
- #include <cstddef>
- #include <type_traits>
- // #include "../config/config.h"
- #ifndef ENTT_CONFIG_CONFIG_H
- #define ENTT_CONFIG_CONFIG_H
- // #include "version.h"
- #ifndef ENTT_CONFIG_VERSION_H
- #define ENTT_CONFIG_VERSION_H
- // #include "macro.h"
- #ifndef ENTT_CONFIG_MACRO_H
- #define ENTT_CONFIG_MACRO_H
- // NOLINTBEGIN(cppcoreguidelines-macro-usage)
- #define ENTT_STR(arg) #arg
- #define ENTT_XSTR(arg) ENTT_STR(arg)
- // NOLINTEND(cppcoreguidelines-macro-usage)
- #endif
- // NOLINTBEGIN(cppcoreguidelines-macro-*,modernize-macro-*)
- #define ENTT_VERSION_MAJOR 3
- #define ENTT_VERSION_MINOR 16
- #define ENTT_VERSION_PATCH 0
- #define ENTT_VERSION \
- ENTT_XSTR(ENTT_VERSION_MAJOR) \
- "." ENTT_XSTR(ENTT_VERSION_MINOR) "." ENTT_XSTR(ENTT_VERSION_PATCH)
- // NOLINTEND(cppcoreguidelines-macro-*,modernize-macro-*)
- #endif
- // NOLINTBEGIN(cppcoreguidelines-macro-usage)
- #if defined(__cpp_exceptions) && !defined(ENTT_NOEXCEPTION)
- # define ENTT_CONSTEXPR
- # define ENTT_THROW throw
- # define ENTT_TRY try
- # define ENTT_CATCH catch(...)
- #else
- # define ENTT_CONSTEXPR constexpr // use only with throwing functions (waiting for C++20)
- # define ENTT_THROW
- # define ENTT_TRY if(true)
- # define ENTT_CATCH if(false)
- #endif
- #if __has_include(<version>)
- # include <version>
- #
- # if defined(__cpp_consteval)
- # define ENTT_CONSTEVAL consteval
- # endif
- #endif
- #ifndef ENTT_CONSTEVAL
- # define ENTT_CONSTEVAL constexpr
- #endif
- #ifdef ENTT_USE_ATOMIC
- # include <atomic>
- # define ENTT_MAYBE_ATOMIC(Type) std::atomic<Type>
- #else
- # define ENTT_MAYBE_ATOMIC(Type) Type
- #endif
- #ifndef ENTT_ID_TYPE
- # include <cstdint>
- # define ENTT_ID_TYPE std::uint32_t
- #else
- # include <cstdint> // provides coverage for types in the std namespace
- #endif
- #ifndef ENTT_SPARSE_PAGE
- # define ENTT_SPARSE_PAGE 4096
- #endif
- #ifndef ENTT_PACKED_PAGE
- # define ENTT_PACKED_PAGE 1024
- #endif
- #ifdef ENTT_DISABLE_ASSERT
- # undef ENTT_ASSERT
- # define ENTT_ASSERT(condition, msg) (void(0))
- #elif !defined ENTT_ASSERT
- # include <cassert>
- # define ENTT_ASSERT(condition, msg) assert(((condition) && (msg)))
- #endif
- #ifdef ENTT_DISABLE_ASSERT
- # undef ENTT_ASSERT_CONSTEXPR
- # define ENTT_ASSERT_CONSTEXPR(condition, msg) (void(0))
- #elif !defined ENTT_ASSERT_CONSTEXPR
- # define ENTT_ASSERT_CONSTEXPR(condition, msg) ENTT_ASSERT(condition, msg)
- #endif
- #define ENTT_FAIL(msg) ENTT_ASSERT(false, msg);
- #ifdef ENTT_NO_ETO
- # define ENTT_ETO_TYPE(Type) void
- #else
- # define ENTT_ETO_TYPE(Type) Type
- #endif
- #ifdef ENTT_NO_MIXIN
- # define ENTT_STORAGE(Mixin, ...) __VA_ARGS__
- #else
- # define ENTT_STORAGE(Mixin, ...) Mixin<__VA_ARGS__>
- #endif
- #ifdef ENTT_STANDARD_CPP
- # define ENTT_NONSTD false
- #else
- # define ENTT_NONSTD true
- # if defined __clang__ || defined __GNUC__
- # define ENTT_PRETTY_FUNCTION __PRETTY_FUNCTION__
- # define ENTT_PRETTY_FUNCTION_PREFIX '='
- # define ENTT_PRETTY_FUNCTION_SUFFIX ']'
- # elif defined _MSC_VER
- # define ENTT_PRETTY_FUNCTION __FUNCSIG__
- # define ENTT_PRETTY_FUNCTION_PREFIX '<'
- # define ENTT_PRETTY_FUNCTION_SUFFIX '>'
- # endif
- #endif
- #ifndef ENTT_EXPORT
- # if defined _WIN32 || defined __CYGWIN__ || defined _MSC_VER
- # define ENTT_EXPORT __declspec(dllexport)
- # define ENTT_IMPORT __declspec(dllimport)
- # define ENTT_HIDDEN
- # elif defined __GNUC__ && __GNUC__ >= 4
- # define ENTT_EXPORT __attribute__((visibility("default")))
- # define ENTT_IMPORT __attribute__((visibility("default")))
- # define ENTT_HIDDEN __attribute__((visibility("hidden")))
- # else /* Unsupported compiler */
- # define ENTT_EXPORT
- # define ENTT_IMPORT
- # define ENTT_HIDDEN
- # endif
- #endif
- #ifndef ENTT_API
- # if defined ENTT_API_EXPORT
- # define ENTT_API ENTT_EXPORT
- # elif defined ENTT_API_IMPORT
- # define ENTT_API ENTT_IMPORT
- # else /* No API */
- # define ENTT_API
- # endif
- #endif
- #if defined _MSC_VER
- # pragma detect_mismatch("entt.version", ENTT_VERSION)
- # pragma detect_mismatch("entt.noexcept", ENTT_XSTR(ENTT_TRY))
- # pragma detect_mismatch("entt.id", ENTT_XSTR(ENTT_ID_TYPE))
- # pragma detect_mismatch("entt.nonstd", ENTT_XSTR(ENTT_NONSTD))
- #endif
- // NOLINTEND(cppcoreguidelines-macro-usage)
- #endif
- // #include "fwd.hpp"
- #ifndef ENTT_ENTITY_FWD_HPP
- #define ENTT_ENTITY_FWD_HPP
- #include <cstdint>
- #include <memory>
- #include <type_traits>
- // #include "../config/config.h"
- // #include "../core/fwd.hpp"
- #ifndef ENTT_CORE_FWD_HPP
- #define ENTT_CORE_FWD_HPP
- #include <cstddef>
- #include <cstdint>
- // #include "../config/config.h"
- #ifndef ENTT_CONFIG_CONFIG_H
- #define ENTT_CONFIG_CONFIG_H
- // #include "version.h"
- #ifndef ENTT_CONFIG_VERSION_H
- #define ENTT_CONFIG_VERSION_H
- // #include "macro.h"
- #ifndef ENTT_CONFIG_MACRO_H
- #define ENTT_CONFIG_MACRO_H
- // NOLINTBEGIN(cppcoreguidelines-macro-usage)
- #define ENTT_STR(arg) #arg
- #define ENTT_XSTR(arg) ENTT_STR(arg)
- // NOLINTEND(cppcoreguidelines-macro-usage)
- #endif
- // NOLINTBEGIN(cppcoreguidelines-macro-*,modernize-macro-*)
- #define ENTT_VERSION_MAJOR 3
- #define ENTT_VERSION_MINOR 16
- #define ENTT_VERSION_PATCH 0
- #define ENTT_VERSION \
- ENTT_XSTR(ENTT_VERSION_MAJOR) \
- "." ENTT_XSTR(ENTT_VERSION_MINOR) "." ENTT_XSTR(ENTT_VERSION_PATCH)
- // NOLINTEND(cppcoreguidelines-macro-*,modernize-macro-*)
- #endif
- // NOLINTBEGIN(cppcoreguidelines-macro-usage)
- #if defined(__cpp_exceptions) && !defined(ENTT_NOEXCEPTION)
- # define ENTT_CONSTEXPR
- # define ENTT_THROW throw
- # define ENTT_TRY try
- # define ENTT_CATCH catch(...)
- #else
- # define ENTT_CONSTEXPR constexpr // use only with throwing functions (waiting for C++20)
- # define ENTT_THROW
- # define ENTT_TRY if(true)
- # define ENTT_CATCH if(false)
- #endif
- #if __has_include(<version>)
- # include <version>
- #
- # if defined(__cpp_consteval)
- # define ENTT_CONSTEVAL consteval
- # endif
- #endif
- #ifndef ENTT_CONSTEVAL
- # define ENTT_CONSTEVAL constexpr
- #endif
- #ifdef ENTT_USE_ATOMIC
- # include <atomic>
- # define ENTT_MAYBE_ATOMIC(Type) std::atomic<Type>
- #else
- # define ENTT_MAYBE_ATOMIC(Type) Type
- #endif
- #ifndef ENTT_ID_TYPE
- # include <cstdint>
- # define ENTT_ID_TYPE std::uint32_t
- #else
- # include <cstdint> // provides coverage for types in the std namespace
- #endif
- #ifndef ENTT_SPARSE_PAGE
- # define ENTT_SPARSE_PAGE 4096
- #endif
- #ifndef ENTT_PACKED_PAGE
- # define ENTT_PACKED_PAGE 1024
- #endif
- #ifdef ENTT_DISABLE_ASSERT
- # undef ENTT_ASSERT
- # define ENTT_ASSERT(condition, msg) (void(0))
- #elif !defined ENTT_ASSERT
- # include <cassert>
- # define ENTT_ASSERT(condition, msg) assert(((condition) && (msg)))
- #endif
- #ifdef ENTT_DISABLE_ASSERT
- # undef ENTT_ASSERT_CONSTEXPR
- # define ENTT_ASSERT_CONSTEXPR(condition, msg) (void(0))
- #elif !defined ENTT_ASSERT_CONSTEXPR
- # define ENTT_ASSERT_CONSTEXPR(condition, msg) ENTT_ASSERT(condition, msg)
- #endif
- #define ENTT_FAIL(msg) ENTT_ASSERT(false, msg);
- #ifdef ENTT_NO_ETO
- # define ENTT_ETO_TYPE(Type) void
- #else
- # define ENTT_ETO_TYPE(Type) Type
- #endif
- #ifdef ENTT_NO_MIXIN
- # define ENTT_STORAGE(Mixin, ...) __VA_ARGS__
- #else
- # define ENTT_STORAGE(Mixin, ...) Mixin<__VA_ARGS__>
- #endif
- #ifdef ENTT_STANDARD_CPP
- # define ENTT_NONSTD false
- #else
- # define ENTT_NONSTD true
- # if defined __clang__ || defined __GNUC__
- # define ENTT_PRETTY_FUNCTION __PRETTY_FUNCTION__
- # define ENTT_PRETTY_FUNCTION_PREFIX '='
- # define ENTT_PRETTY_FUNCTION_SUFFIX ']'
- # elif defined _MSC_VER
- # define ENTT_PRETTY_FUNCTION __FUNCSIG__
- # define ENTT_PRETTY_FUNCTION_PREFIX '<'
- # define ENTT_PRETTY_FUNCTION_SUFFIX '>'
- # endif
- #endif
- #ifndef ENTT_EXPORT
- # if defined _WIN32 || defined __CYGWIN__ || defined _MSC_VER
- # define ENTT_EXPORT __declspec(dllexport)
- # define ENTT_IMPORT __declspec(dllimport)
- # define ENTT_HIDDEN
- # elif defined __GNUC__ && __GNUC__ >= 4
- # define ENTT_EXPORT __attribute__((visibility("default")))
- # define ENTT_IMPORT __attribute__((visibility("default")))
- # define ENTT_HIDDEN __attribute__((visibility("hidden")))
- # else /* Unsupported compiler */
- # define ENTT_EXPORT
- # define ENTT_IMPORT
- # define ENTT_HIDDEN
- # endif
- #endif
- #ifndef ENTT_API
- # if defined ENTT_API_EXPORT
- # define ENTT_API ENTT_EXPORT
- # elif defined ENTT_API_IMPORT
- # define ENTT_API ENTT_IMPORT
- # else /* No API */
- # define ENTT_API
- # endif
- #endif
- #if defined _MSC_VER
- # pragma detect_mismatch("entt.version", ENTT_VERSION)
- # pragma detect_mismatch("entt.noexcept", ENTT_XSTR(ENTT_TRY))
- # pragma detect_mismatch("entt.id", ENTT_XSTR(ENTT_ID_TYPE))
- # pragma detect_mismatch("entt.nonstd", ENTT_XSTR(ENTT_NONSTD))
- #endif
- // NOLINTEND(cppcoreguidelines-macro-usage)
- #endif
- namespace entt {
- /*! @brief Possible modes of an any object. */
- enum class any_policy : std::uint8_t {
- /*! @brief Default mode, no element available. */
- empty,
- /*! @brief Owning mode, dynamically allocated element. */
- dynamic,
- /*! @brief Owning mode, embedded element. */
- embedded,
- /*! @brief Aliasing mode, non-const reference. */
- ref,
- /*! @brief Const aliasing mode, const reference. */
- cref
- };
- // NOLINTNEXTLINE(cppcoreguidelines-avoid-c-arrays, modernize-avoid-c-arrays)
- template<std::size_t Len = sizeof(double[2]), std::size_t = alignof(double[2])>
- class basic_any;
- /*! @brief Alias declaration for type identifiers. */
- using id_type = ENTT_ID_TYPE;
- /*! @brief Alias declaration for the most common use case. */
- using any = basic_any<>;
- template<typename, typename>
- class compressed_pair;
- template<typename>
- class basic_hashed_string;
- /*! @brief Aliases for common character types. */
- using hashed_string = basic_hashed_string<char>;
- /*! @brief Aliases for common character types. */
- using hashed_wstring = basic_hashed_string<wchar_t>;
- // NOLINTNEXTLINE(bugprone-forward-declaration-namespace)
- struct type_info;
- } // namespace entt
- #endif
- // #include "../core/type_traits.hpp"
- #ifndef ENTT_CORE_TYPE_TRAITS_HPP
- #define ENTT_CORE_TYPE_TRAITS_HPP
- #include <cstddef>
- #include <iterator>
- #include <tuple>
- #include <type_traits>
- #include <utility>
- // #include "../config/config.h"
- // #include "fwd.hpp"
- #ifndef ENTT_CORE_FWD_HPP
- #define ENTT_CORE_FWD_HPP
- #include <cstddef>
- #include <cstdint>
- // #include "../config/config.h"
- namespace entt {
- /*! @brief Possible modes of an any object. */
- enum class any_policy : std::uint8_t {
- /*! @brief Default mode, no element available. */
- empty,
- /*! @brief Owning mode, dynamically allocated element. */
- dynamic,
- /*! @brief Owning mode, embedded element. */
- embedded,
- /*! @brief Aliasing mode, non-const reference. */
- ref,
- /*! @brief Const aliasing mode, const reference. */
- cref
- };
- // NOLINTNEXTLINE(cppcoreguidelines-avoid-c-arrays, modernize-avoid-c-arrays)
- template<std::size_t Len = sizeof(double[2]), std::size_t = alignof(double[2])>
- class basic_any;
- /*! @brief Alias declaration for type identifiers. */
- using id_type = ENTT_ID_TYPE;
- /*! @brief Alias declaration for the most common use case. */
- using any = basic_any<>;
- template<typename, typename>
- class compressed_pair;
- template<typename>
- class basic_hashed_string;
- /*! @brief Aliases for common character types. */
- using hashed_string = basic_hashed_string<char>;
- /*! @brief Aliases for common character types. */
- using hashed_wstring = basic_hashed_string<wchar_t>;
- // NOLINTNEXTLINE(bugprone-forward-declaration-namespace)
- struct type_info;
- } // namespace entt
- #endif
- namespace entt {
- /**
- * @brief Utility class to disambiguate overloaded functions.
- * @tparam N Number of choices available.
- */
- template<std::size_t N>
- struct choice_t
- // unfortunately, doxygen cannot parse such a construct
- : /*! @cond TURN_OFF_DOXYGEN */ choice_t<N - 1> /*! @endcond */
- {};
- /*! @copybrief choice_t */
- template<>
- struct choice_t<0> {};
- /**
- * @brief Variable template for the choice trick.
- * @tparam N Number of choices available.
- */
- template<std::size_t N>
- inline constexpr choice_t<N> choice{};
- /**
- * @brief Identity type trait.
- *
- * Useful to establish non-deduced contexts in template argument deduction
- * (waiting for C++20) or to provide types through function arguments.
- *
- * @tparam Type A type.
- */
- template<typename Type>
- struct type_identity {
- /*! @brief Identity type. */
- using type = Type;
- };
- /**
- * @brief Helper type.
- * @tparam Type A type.
- */
- template<typename Type>
- using type_identity_t = typename type_identity<Type>::type;
- /**
- * @brief A type-only `sizeof` wrapper that returns 0 where `sizeof` complains.
- * @tparam Type The type of which to return the size.
- */
- template<typename Type, typename = void>
- struct size_of: std::integral_constant<std::size_t, 0u> {};
- /*! @copydoc size_of */
- template<typename Type>
- struct size_of<Type, std::void_t<decltype(sizeof(Type))>>
- // NOLINTNEXTLINE(bugprone-sizeof-expression)
- : std::integral_constant<std::size_t, sizeof(Type)> {};
- /**
- * @brief Helper variable template.
- * @tparam Type The type of which to return the size.
- */
- template<typename Type>
- inline constexpr std::size_t size_of_v = size_of<Type>::value;
- /**
- * @brief Using declaration to be used to _repeat_ the same type a number of
- * times equal to the size of a given parameter pack.
- * @tparam Type A type to repeat.
- */
- template<typename Type, typename>
- using unpack_as_type = Type;
- /**
- * @brief Helper variable template to be used to _repeat_ the same value a
- * number of times equal to the size of a given parameter pack.
- * @tparam Value A value to repeat.
- */
- template<auto Value, typename>
- inline constexpr auto unpack_as_value = Value;
- /**
- * @brief Wraps a static constant.
- * @tparam Value A static constant.
- */
- template<auto Value>
- using integral_constant = std::integral_constant<decltype(Value), Value>;
- /**
- * @brief Alias template to facilitate the creation of named values.
- * @tparam Value A constant value at least convertible to `id_type`.
- */
- template<id_type Value>
- using tag = integral_constant<Value>;
- /**
- * @brief A class to use to push around lists of types, nothing more.
- * @tparam Type Types provided by the type list.
- */
- template<typename... Type>
- struct type_list {
- /*! @brief Type list type. */
- using type = type_list;
- /*! @brief Compile-time number of elements in the type list. */
- static constexpr auto size = sizeof...(Type);
- };
- /*! @brief Primary template isn't defined on purpose. */
- template<std::size_t, typename>
- struct type_list_element;
- /**
- * @brief Provides compile-time indexed access to the types of a type list.
- * @tparam Index Index of the type to return.
- * @tparam First First type provided by the type list.
- * @tparam Other Other types provided by the type list.
- */
- template<std::size_t Index, typename First, typename... Other>
- struct type_list_element<Index, type_list<First, Other...>>
- : type_list_element<Index - 1u, type_list<Other...>> {};
- /**
- * @brief Provides compile-time indexed access to the types of a type list.
- * @tparam First First type provided by the type list.
- * @tparam Other Other types provided by the type list.
- */
- template<typename First, typename... Other>
- struct type_list_element<0u, type_list<First, Other...>> {
- /*! @brief Searched type. */
- using type = First;
- };
- /**
- * @brief Helper type.
- * @tparam Index Index of the type to return.
- * @tparam List Type list to search into.
- */
- template<std::size_t Index, typename List>
- using type_list_element_t = typename type_list_element<Index, List>::type;
- /*! @brief Primary template isn't defined on purpose. */
- template<typename, typename>
- struct type_list_index;
- /**
- * @brief Provides compile-time type access to the types of a type list.
- * @tparam Type Type to look for and for which to return the index.
- * @tparam First First type provided by the type list.
- * @tparam Other Other types provided by the type list.
- */
- template<typename Type, typename First, typename... Other>
- struct type_list_index<Type, type_list<First, Other...>> {
- /*! @brief Unsigned integer type. */
- using value_type = std::size_t;
- /*! @brief Compile-time position of the given type in the sublist. */
- static constexpr value_type value = 1u + type_list_index<Type, type_list<Other...>>::value;
- };
- /**
- * @brief Provides compile-time type access to the types of a type list.
- * @tparam Type Type to look for and for which to return the index.
- * @tparam Other Other types provided by the type list.
- */
- template<typename Type, typename... Other>
- struct type_list_index<Type, type_list<Type, Other...>> {
- static_assert(type_list_index<Type, type_list<Other...>>::value == sizeof...(Other), "Non-unique type");
- /*! @brief Unsigned integer type. */
- using value_type = std::size_t;
- /*! @brief Compile-time position of the given type in the sublist. */
- static constexpr value_type value = 0u;
- };
- /**
- * @brief Provides compile-time type access to the types of a type list.
- * @tparam Type Type to look for and for which to return the index.
- */
- template<typename Type>
- struct type_list_index<Type, type_list<>> {
- /*! @brief Unsigned integer type. */
- using value_type = std::size_t;
- /*! @brief Compile-time position of the given type in the sublist. */
- static constexpr value_type value = 0u;
- };
- /**
- * @brief Helper variable template.
- * @tparam List Type list.
- * @tparam Type Type to look for and for which to return the index.
- */
- template<typename Type, typename List>
- inline constexpr std::size_t type_list_index_v = type_list_index<Type, List>::value;
- /**
- * @brief Concatenates multiple type lists.
- * @tparam Type Types provided by the first type list.
- * @tparam Other Types provided by the second type list.
- * @return A type list composed by the types of both the type lists.
- */
- template<typename... Type, typename... Other>
- constexpr type_list<Type..., Other...> operator+(type_list<Type...>, type_list<Other...>) {
- return {};
- }
- /*! @brief Primary template isn't defined on purpose. */
- template<typename...>
- struct type_list_cat;
- /*! @brief Concatenates multiple type lists. */
- template<>
- struct type_list_cat<> {
- /*! @brief A type list composed by the types of all the type lists. */
- using type = type_list<>;
- };
- /**
- * @brief Concatenates multiple type lists.
- * @tparam Type Types provided by the first type list.
- * @tparam Other Types provided by the second type list.
- * @tparam List Other type lists, if any.
- */
- template<typename... Type, typename... Other, typename... List>
- struct type_list_cat<type_list<Type...>, type_list<Other...>, List...> {
- /*! @brief A type list composed by the types of all the type lists. */
- using type = typename type_list_cat<type_list<Type..., Other...>, List...>::type;
- };
- /**
- * @brief Concatenates multiple type lists.
- * @tparam Type Types provided by the type list.
- */
- template<typename... Type>
- struct type_list_cat<type_list<Type...>> {
- /*! @brief A type list composed by the types of all the type lists. */
- using type = type_list<Type...>;
- };
- /**
- * @brief Helper type.
- * @tparam List Type lists to concatenate.
- */
- template<typename... List>
- using type_list_cat_t = typename type_list_cat<List...>::type;
- /*! @cond TURN_OFF_DOXYGEN */
- namespace internal {
- template<typename...>
- struct type_list_unique;
- template<typename First, typename... Other, typename... Type>
- struct type_list_unique<type_list<First, Other...>, Type...>
- : std::conditional_t<(std::is_same_v<First, Type> || ...), type_list_unique<type_list<Other...>, Type...>, type_list_unique<type_list<Other...>, Type..., First>> {};
- template<typename... Type>
- struct type_list_unique<type_list<>, Type...> {
- using type = type_list<Type...>;
- };
- } // namespace internal
- /*! @endcond */
- /**
- * @brief Removes duplicates types from a type list.
- * @tparam List Type list.
- */
- template<typename List>
- struct type_list_unique {
- /*! @brief A type list without duplicate types. */
- using type = typename internal::type_list_unique<List>::type;
- };
- /**
- * @brief Helper type.
- * @tparam List Type list.
- */
- template<typename List>
- using type_list_unique_t = typename type_list_unique<List>::type;
- /**
- * @brief Provides the member constant `value` to true if a type list contains a
- * given type, false otherwise.
- * @tparam List Type list.
- * @tparam Type Type to look for.
- */
- template<typename List, typename Type>
- struct type_list_contains;
- /**
- * @copybrief type_list_contains
- * @tparam Type Types provided by the type list.
- * @tparam Other Type to look for.
- */
- template<typename... Type, typename Other>
- struct type_list_contains<type_list<Type...>, Other>
- : std::bool_constant<(std::is_same_v<Type, Other> || ...)> {};
- /**
- * @brief Helper variable template.
- * @tparam List Type list.
- * @tparam Type Type to look for.
- */
- template<typename List, typename Type>
- inline constexpr bool type_list_contains_v = type_list_contains<List, Type>::value;
- /*! @brief Primary template isn't defined on purpose. */
- template<typename...>
- struct type_list_diff;
- /**
- * @brief Computes the difference between two type lists.
- * @tparam Type Types provided by the first type list.
- * @tparam Other Types provided by the second type list.
- */
- template<typename... Type, typename... Other>
- struct type_list_diff<type_list<Type...>, type_list<Other...>> {
- /*! @brief A type list that is the difference between the two type lists. */
- using type = type_list_cat_t<std::conditional_t<type_list_contains_v<type_list<Other...>, Type>, type_list<>, type_list<Type>>...>;
- };
- /**
- * @brief Helper type.
- * @tparam List Type lists between which to compute the difference.
- */
- template<typename... List>
- using type_list_diff_t = typename type_list_diff<List...>::type;
- /*! @brief Primary template isn't defined on purpose. */
- template<typename, template<typename...> class>
- struct type_list_transform;
- /**
- * @brief Applies a given _function_ to a type list and generate a new list.
- * @tparam Type Types provided by the type list.
- * @tparam Op Unary operation as template class with a type member named `type`.
- */
- template<typename... Type, template<typename...> class Op>
- struct type_list_transform<type_list<Type...>, Op> {
- /*! @brief Resulting type list after applying the transform function. */
- // NOLINTNEXTLINE(modernize-type-traits)
- using type = type_list<typename Op<Type>::type...>;
- };
- /**
- * @brief Helper type.
- * @tparam List Type list.
- * @tparam Op Unary operation as template class with a type member named `type`.
- */
- template<typename List, template<typename...> class Op>
- using type_list_transform_t = typename type_list_transform<List, Op>::type;
- /**
- * @brief A class to use to push around lists of constant values, nothing more.
- * @tparam Value Values provided by the value list.
- */
- template<auto... Value>
- struct value_list {
- /*! @brief Value list type. */
- using type = value_list;
- /*! @brief Compile-time number of elements in the value list. */
- static constexpr auto size = sizeof...(Value);
- };
- /*! @brief Primary template isn't defined on purpose. */
- template<std::size_t, typename>
- struct value_list_element;
- /**
- * @brief Provides compile-time indexed access to the values of a value list.
- * @tparam Index Index of the value to return.
- * @tparam Value First value provided by the value list.
- * @tparam Other Other values provided by the value list.
- */
- template<std::size_t Index, auto Value, auto... Other>
- struct value_list_element<Index, value_list<Value, Other...>>
- : value_list_element<Index - 1u, value_list<Other...>> {};
- /**
- * @brief Provides compile-time indexed access to the types of a type list.
- * @tparam Value First value provided by the value list.
- * @tparam Other Other values provided by the value list.
- */
- template<auto Value, auto... Other>
- struct value_list_element<0u, value_list<Value, Other...>> {
- /*! @brief Searched type. */
- using type = decltype(Value);
- /*! @brief Searched value. */
- static constexpr auto value = Value;
- };
- /**
- * @brief Helper type.
- * @tparam Index Index of the type to return.
- * @tparam List Value list to search into.
- */
- template<std::size_t Index, typename List>
- using value_list_element_t = typename value_list_element<Index, List>::type;
- /**
- * @brief Helper type.
- * @tparam Index Index of the value to return.
- * @tparam List Value list to search into.
- */
- template<std::size_t Index, typename List>
- inline constexpr auto value_list_element_v = value_list_element<Index, List>::value;
- /*! @brief Primary template isn't defined on purpose. */
- template<auto, typename>
- struct value_list_index;
- /**
- * @brief Provides compile-time type access to the values of a value list.
- * @tparam Value Value to look for and for which to return the index.
- * @tparam First First value provided by the value list.
- * @tparam Other Other values provided by the value list.
- */
- template<auto Value, auto First, auto... Other>
- struct value_list_index<Value, value_list<First, Other...>> {
- /*! @brief Unsigned integer type. */
- using value_type = std::size_t;
- /*! @brief Compile-time position of the given value in the sublist. */
- static constexpr value_type value = 1u + value_list_index<Value, value_list<Other...>>::value;
- };
- /**
- * @brief Provides compile-time type access to the values of a value list.
- * @tparam Value Value to look for and for which to return the index.
- * @tparam Other Other values provided by the value list.
- */
- template<auto Value, auto... Other>
- struct value_list_index<Value, value_list<Value, Other...>> {
- static_assert(value_list_index<Value, value_list<Other...>>::value == sizeof...(Other), "Non-unique type");
- /*! @brief Unsigned integer type. */
- using value_type = std::size_t;
- /*! @brief Compile-time position of the given value in the sublist. */
- static constexpr value_type value = 0u;
- };
- /**
- * @brief Provides compile-time type access to the values of a value list.
- * @tparam Value Value to look for and for which to return the index.
- */
- template<auto Value>
- struct value_list_index<Value, value_list<>> {
- /*! @brief Unsigned integer type. */
- using value_type = std::size_t;
- /*! @brief Compile-time position of the given type in the sublist. */
- static constexpr value_type value = 0u;
- };
- /**
- * @brief Helper variable template.
- * @tparam List Value list.
- * @tparam Value Value to look for and for which to return the index.
- */
- template<auto Value, typename List>
- inline constexpr std::size_t value_list_index_v = value_list_index<Value, List>::value;
- /**
- * @brief Concatenates multiple value lists.
- * @tparam Value Values provided by the first value list.
- * @tparam Other Values provided by the second value list.
- * @return A value list composed by the values of both the value lists.
- */
- template<auto... Value, auto... Other>
- constexpr value_list<Value..., Other...> operator+(value_list<Value...>, value_list<Other...>) {
- return {};
- }
- /*! @brief Primary template isn't defined on purpose. */
- template<typename...>
- struct value_list_cat;
- /*! @brief Concatenates multiple value lists. */
- template<>
- struct value_list_cat<> {
- /*! @brief A value list composed by the values of all the value lists. */
- using type = value_list<>;
- };
- /**
- * @brief Concatenates multiple value lists.
- * @tparam Value Values provided by the first value list.
- * @tparam Other Values provided by the second value list.
- * @tparam List Other value lists, if any.
- */
- template<auto... Value, auto... Other, typename... List>
- struct value_list_cat<value_list<Value...>, value_list<Other...>, List...> {
- /*! @brief A value list composed by the values of all the value lists. */
- using type = typename value_list_cat<value_list<Value..., Other...>, List...>::type;
- };
- /**
- * @brief Concatenates multiple value lists.
- * @tparam Value Values provided by the value list.
- */
- template<auto... Value>
- struct value_list_cat<value_list<Value...>> {
- /*! @brief A value list composed by the values of all the value lists. */
- using type = value_list<Value...>;
- };
- /**
- * @brief Helper type.
- * @tparam List Value lists to concatenate.
- */
- template<typename... List>
- using value_list_cat_t = typename value_list_cat<List...>::type;
- /*! @brief Primary template isn't defined on purpose. */
- template<typename>
- struct value_list_unique;
- /**
- * @brief Removes duplicates values from a value list.
- * @tparam Value One of the values provided by the given value list.
- * @tparam Other The other values provided by the given value list.
- */
- template<auto Value, auto... Other>
- struct value_list_unique<value_list<Value, Other...>> {
- /*! @brief A value list without duplicate types. */
- using type = std::conditional_t<
- ((Value == Other) || ...),
- typename value_list_unique<value_list<Other...>>::type,
- value_list_cat_t<value_list<Value>, typename value_list_unique<value_list<Other...>>::type>>;
- };
- /*! @brief Removes duplicates values from a value list. */
- template<>
- struct value_list_unique<value_list<>> {
- /*! @brief A value list without duplicate types. */
- using type = value_list<>;
- };
- /**
- * @brief Helper type.
- * @tparam Type A value list.
- */
- template<typename Type>
- using value_list_unique_t = typename value_list_unique<Type>::type;
- /**
- * @brief Provides the member constant `value` to true if a value list contains
- * a given value, false otherwise.
- * @tparam List Value list.
- * @tparam Value Value to look for.
- */
- template<typename List, auto Value>
- struct value_list_contains;
- /**
- * @copybrief value_list_contains
- * @tparam Value Values provided by the value list.
- * @tparam Other Value to look for.
- */
- template<auto... Value, auto Other>
- struct value_list_contains<value_list<Value...>, Other>
- : std::bool_constant<((Value == Other) || ...)> {};
- /**
- * @brief Helper variable template.
- * @tparam List Value list.
- * @tparam Value Value to look for.
- */
- template<typename List, auto Value>
- inline constexpr bool value_list_contains_v = value_list_contains<List, Value>::value;
- /*! @brief Primary template isn't defined on purpose. */
- template<typename...>
- struct value_list_diff;
- /**
- * @brief Computes the difference between two value lists.
- * @tparam Value Values provided by the first value list.
- * @tparam Other Values provided by the second value list.
- */
- template<auto... Value, auto... Other>
- struct value_list_diff<value_list<Value...>, value_list<Other...>> {
- /*! @brief A value list that is the difference between the two value lists. */
- using type = value_list_cat_t<std::conditional_t<value_list_contains_v<value_list<Other...>, Value>, value_list<>, value_list<Value>>...>;
- };
- /**
- * @brief Helper type.
- * @tparam List Value lists between which to compute the difference.
- */
- template<typename... List>
- using value_list_diff_t = typename value_list_diff<List...>::type;
- /*! @brief Same as std::is_invocable, but with tuples. */
- template<typename, typename>
- struct is_applicable: std::false_type {};
- /**
- * @copybrief is_applicable
- * @tparam Func A valid function type.
- * @tparam Tuple Tuple-like type.
- * @tparam Args The list of arguments to use to probe the function type.
- */
- template<typename Func, template<typename...> class Tuple, typename... Args>
- struct is_applicable<Func, Tuple<Args...>>: std::is_invocable<Func, Args...> {};
- /**
- * @copybrief is_applicable
- * @tparam Func A valid function type.
- * @tparam Tuple Tuple-like type.
- * @tparam Args The list of arguments to use to probe the function type.
- */
- template<typename Func, template<typename...> class Tuple, typename... Args>
- struct is_applicable<Func, const Tuple<Args...>>: std::is_invocable<Func, Args...> {};
- /**
- * @brief Helper variable template.
- * @tparam Func A valid function type.
- * @tparam Args The list of arguments to use to probe the function type.
- */
- template<typename Func, typename Args>
- inline constexpr bool is_applicable_v = is_applicable<Func, Args>::value;
- /*! @brief Same as std::is_invocable_r, but with tuples for arguments. */
- template<typename, typename, typename>
- struct is_applicable_r: std::false_type {};
- /**
- * @copybrief is_applicable_r
- * @tparam Ret The type to which the return type of the function should be
- * convertible.
- * @tparam Func A valid function type.
- * @tparam Args The list of arguments to use to probe the function type.
- */
- template<typename Ret, typename Func, typename... Args>
- struct is_applicable_r<Ret, Func, std::tuple<Args...>>: std::is_invocable_r<Ret, Func, Args...> {};
- /**
- * @brief Helper variable template.
- * @tparam Ret The type to which the return type of the function should be
- * convertible.
- * @tparam Func A valid function type.
- * @tparam Args The list of arguments to use to probe the function type.
- */
- template<typename Ret, typename Func, typename Args>
- inline constexpr bool is_applicable_r_v = is_applicable_r<Ret, Func, Args>::value;
- /**
- * @brief Provides the member constant `value` to true if a given type is
- * complete, false otherwise.
- * @tparam Type The type to test.
- */
- template<typename Type, typename = void>
- struct is_complete: std::false_type {};
- /*! @copydoc is_complete */
- template<typename Type>
- struct is_complete<Type, std::void_t<decltype(sizeof(Type))>>: std::true_type {};
- /**
- * @brief Helper variable template.
- * @tparam Type The type to test.
- */
- template<typename Type>
- inline constexpr bool is_complete_v = is_complete<Type>::value;
- /**
- * @brief Provides the member constant `value` to true if a given type is an
- * iterator, false otherwise.
- * @tparam Type The type to test.
- */
- template<typename Type, typename = void>
- struct is_iterator: std::false_type {};
- /*! @cond TURN_OFF_DOXYGEN */
- namespace internal {
- template<typename, typename = void>
- struct has_iterator_category: std::false_type {};
- template<typename Type>
- struct has_iterator_category<Type, std::void_t<typename std::iterator_traits<Type>::iterator_category>>: std::true_type {};
- } // namespace internal
- /*! @endcond */
- /*! @copydoc is_iterator */
- template<typename Type>
- struct is_iterator<Type, std::enable_if_t<!std::is_void_v<std::remove_const_t<std::remove_pointer_t<Type>>>>>
- : internal::has_iterator_category<Type> {};
- /**
- * @brief Helper variable template.
- * @tparam Type The type to test.
- */
- template<typename Type>
- inline constexpr bool is_iterator_v = is_iterator<Type>::value;
- /**
- * @brief Provides the member constant `value` to true if a given type is both
- * an empty and non-final class, false otherwise.
- * @tparam Type The type to test
- */
- template<typename Type>
- struct is_ebco_eligible
- : std::bool_constant<std::is_empty_v<Type> && !std::is_final_v<Type>> {};
- /**
- * @brief Helper variable template.
- * @tparam Type The type to test.
- */
- template<typename Type>
- inline constexpr bool is_ebco_eligible_v = is_ebco_eligible<Type>::value;
- /**
- * @brief Provides the member constant `value` to true if `Type::is_transparent`
- * is valid and denotes a type, false otherwise.
- * @tparam Type The type to test.
- */
- template<typename Type, typename = void>
- struct is_transparent: std::false_type {};
- /*! @copydoc is_transparent */
- template<typename Type>
- struct is_transparent<Type, std::void_t<typename Type::is_transparent>>: std::true_type {};
- /**
- * @brief Helper variable template.
- * @tparam Type The type to test.
- */
- template<typename Type>
- inline constexpr bool is_transparent_v = is_transparent<Type>::value;
- /*! @cond TURN_OFF_DOXYGEN */
- namespace internal {
- template<typename, typename = void>
- struct has_tuple_size_value: std::false_type {};
- template<typename Type>
- struct has_tuple_size_value<Type, std::void_t<decltype(std::tuple_size<const Type>::value)>>: std::true_type {};
- template<typename, typename = void>
- struct has_value_type: std::false_type {};
- template<typename Type>
- struct has_value_type<Type, std::void_t<typename Type::value_type>>: std::true_type {};
- template<typename>
- [[nodiscard]] constexpr bool dispatch_is_equality_comparable();
- template<typename Type, std::size_t... Index>
- [[nodiscard]] constexpr bool unpack_maybe_equality_comparable(std::index_sequence<Index...>) {
- return (dispatch_is_equality_comparable<std::tuple_element_t<Index, Type>>() && ...);
- }
- template<typename>
- [[nodiscard]] constexpr bool maybe_equality_comparable(char) {
- return false;
- }
- template<typename Type>
- [[nodiscard]] constexpr auto maybe_equality_comparable(int) -> decltype(std::declval<Type>() == std::declval<Type>()) {
- return true;
- }
- template<typename Type>
- [[nodiscard]] constexpr bool dispatch_is_equality_comparable() {
- // NOLINTBEGIN(modernize-use-transparent-functors)
- if constexpr(std::is_array_v<Type>) {
- return false;
- } else if constexpr(is_complete_v<std::tuple_size<std::remove_const_t<Type>>>) {
- if constexpr(has_tuple_size_value<Type>::value) {
- return maybe_equality_comparable<Type>(0) && unpack_maybe_equality_comparable<Type>(std::make_index_sequence<std::tuple_size<Type>::value>{});
- } else {
- return maybe_equality_comparable<Type>(0);
- }
- } else if constexpr(has_value_type<Type>::value) {
- if constexpr(is_iterator_v<Type> || std::is_same_v<typename Type::value_type, Type> || dispatch_is_equality_comparable<typename Type::value_type>()) {
- return maybe_equality_comparable<Type>(0);
- } else {
- return false;
- }
- } else {
- return maybe_equality_comparable<Type>(0);
- }
- // NOLINTEND(modernize-use-transparent-functors)
- }
- } // namespace internal
- /*! @endcond */
- /**
- * @brief Provides the member constant `value` to true if a given type is
- * equality comparable, false otherwise.
- * @tparam Type The type to test.
- */
- template<typename Type>
- struct is_equality_comparable: std::bool_constant<internal::dispatch_is_equality_comparable<Type>()> {};
- /*! @copydoc is_equality_comparable */
- template<typename Type>
- struct is_equality_comparable<const Type>: is_equality_comparable<Type> {};
- /**
- * @brief Helper variable template.
- * @tparam Type The type to test.
- */
- template<typename Type>
- inline constexpr bool is_equality_comparable_v = is_equality_comparable<Type>::value;
- /**
- * @brief Transcribes the constness of a type to another type.
- * @tparam To The type to which to transcribe the constness.
- * @tparam From The type from which to transcribe the constness.
- */
- template<typename To, typename From>
- struct constness_as {
- /*! @brief The type resulting from the transcription of the constness. */
- using type = std::remove_const_t<To>;
- };
- /*! @copydoc constness_as */
- template<typename To, typename From>
- struct constness_as<To, const From> {
- /*! @brief The type resulting from the transcription of the constness. */
- using type = const To;
- };
- /**
- * @brief Alias template to facilitate the transcription of the constness.
- * @tparam To The type to which to transcribe the constness.
- * @tparam From The type from which to transcribe the constness.
- */
- template<typename To, typename From>
- using constness_as_t = typename constness_as<To, From>::type;
- /**
- * @brief Extracts the class of a non-static member object or function.
- * @tparam Member A pointer to a non-static member object or function.
- */
- template<typename Member>
- class member_class {
- static_assert(std::is_member_pointer_v<Member>, "Invalid pointer type to non-static member object or function");
- template<typename Class, typename Ret, typename... Args>
- static Class *clazz(Ret (Class::*)(Args...));
- template<typename Class, typename Ret, typename... Args>
- static Class *clazz(Ret (Class::*)(Args...) const);
- template<typename Class, typename Type>
- static Class *clazz(Type Class::*);
- public:
- /*! @brief The class of the given non-static member object or function. */
- using type = std::remove_pointer_t<decltype(clazz(std::declval<Member>()))>;
- };
- /**
- * @brief Helper type.
- * @tparam Member A pointer to a non-static member object or function.
- */
- template<typename Member>
- using member_class_t = typename member_class<Member>::type;
- /**
- * @brief Extracts the n-th argument of a _callable_ type.
- * @tparam Index The index of the argument to extract.
- * @tparam Candidate A valid _callable_ type.
- */
- template<std::size_t Index, typename Candidate>
- class nth_argument {
- template<typename Ret, typename... Args>
- static constexpr type_list<Args...> pick_up(Ret (*)(Args...));
- template<typename Ret, typename Class, typename... Args>
- static constexpr type_list<Args...> pick_up(Ret (Class ::*)(Args...));
- template<typename Ret, typename Class, typename... Args>
- static constexpr type_list<Args...> pick_up(Ret (Class ::*)(Args...) const);
- template<typename Type, typename Class>
- static constexpr type_list<Type> pick_up(Type Class ::*);
- template<typename Type>
- static constexpr decltype(pick_up(&Type::operator())) pick_up(Type &&);
- public:
- /*! @brief N-th argument of the _callable_ type. */
- using type = type_list_element_t<Index, decltype(pick_up(std::declval<Candidate>()))>;
- };
- /**
- * @brief Helper type.
- * @tparam Index The index of the argument to extract.
- * @tparam Candidate A valid function, member function or data member type.
- */
- template<std::size_t Index, typename Candidate>
- using nth_argument_t = typename nth_argument<Index, Candidate>::type;
- } // namespace entt
- template<typename... Type>
- struct std::tuple_size<entt::type_list<Type...>>: std::integral_constant<std::size_t, entt::type_list<Type...>::size> {};
- template<std::size_t Index, typename... Type>
- struct std::tuple_element<Index, entt::type_list<Type...>>: entt::type_list_element<Index, entt::type_list<Type...>> {};
- template<auto... Value>
- struct std::tuple_size<entt::value_list<Value...>>: std::integral_constant<std::size_t, entt::value_list<Value...>::size> {};
- template<std::size_t Index, auto... Value>
- struct std::tuple_element<Index, entt::value_list<Value...>>: entt::value_list_element<Index, entt::value_list<Value...>> {};
- #endif
- namespace entt {
- /*! @brief Default entity identifier. */
- enum class entity : id_type {};
- /*! @brief Storage deletion policy. */
- enum class deletion_policy : std::uint8_t {
- /*! @brief Swap-and-pop deletion policy. */
- swap_and_pop = 0u,
- /*! @brief In-place deletion policy. */
- in_place = 1u,
- /*! @brief Swap-only deletion policy. */
- swap_only = 2u,
- /*! @brief Unspecified deletion policy. */
- unspecified = swap_and_pop
- };
- template<typename Type, typename Entity = entity, typename = void>
- struct component_traits;
- template<typename Entity = entity, typename = std::allocator<Entity>>
- class basic_sparse_set;
- template<typename Type, typename = entity, typename = std::allocator<Type>, typename = void>
- class basic_storage;
- template<typename, typename>
- class basic_sigh_mixin;
- template<typename, typename>
- class basic_reactive_mixin;
- template<typename Entity = entity, typename = std::allocator<Entity>>
- class basic_registry;
- template<typename, typename, typename = void>
- class basic_view;
- template<typename Type, typename = std::allocator<Type *>>
- class basic_runtime_view;
- template<typename, typename, typename>
- class basic_group;
- template<typename>
- class basic_organizer;
- template<typename, typename...>
- class basic_handle;
- template<typename>
- class basic_snapshot;
- template<typename>
- class basic_snapshot_loader;
- template<typename>
- class basic_continuous_loader;
- /*! @brief Alias declaration for the most common use case. */
- using sparse_set = basic_sparse_set<>;
- /**
- * @brief Alias declaration for the most common use case.
- * @tparam Type Element type.
- */
- template<typename Type>
- using storage = basic_storage<Type>;
- /**
- * @brief Alias declaration for the most common use case.
- * @tparam Type Underlying storage type.
- */
- template<typename Type>
- using sigh_mixin = basic_sigh_mixin<Type, basic_registry<typename Type::entity_type, typename Type::base_type::allocator_type>>;
- /**
- * @brief Alias declaration for the most common use case.
- * @tparam Type Underlying storage type.
- */
- template<typename Type>
- using reactive_mixin = basic_reactive_mixin<Type, basic_registry<typename Type::entity_type, typename Type::base_type::allocator_type>>;
- /*! @brief Alias declaration for the most common use case. */
- using registry = basic_registry<>;
- /*! @brief Alias declaration for the most common use case. */
- using organizer = basic_organizer<registry>;
- /*! @brief Alias declaration for the most common use case. */
- using handle = basic_handle<registry>;
- /*! @brief Alias declaration for the most common use case. */
- using const_handle = basic_handle<const registry>;
- /**
- * @brief Alias declaration for the most common use case.
- * @tparam Args Other template parameters.
- */
- template<typename... Args>
- using handle_view = basic_handle<registry, Args...>;
- /**
- * @brief Alias declaration for the most common use case.
- * @tparam Args Other template parameters.
- */
- template<typename... Args>
- using const_handle_view = basic_handle<const registry, Args...>;
- /*! @brief Alias declaration for the most common use case. */
- using snapshot = basic_snapshot<registry>;
- /*! @brief Alias declaration for the most common use case. */
- using snapshot_loader = basic_snapshot_loader<registry>;
- /*! @brief Alias declaration for the most common use case. */
- using continuous_loader = basic_continuous_loader<registry>;
- /*! @brief Alias declaration for the most common use case. */
- using runtime_view = basic_runtime_view<sparse_set>;
- /*! @brief Alias declaration for the most common use case. */
- using const_runtime_view = basic_runtime_view<const sparse_set>;
- /**
- * @brief Alias for exclusion lists.
- * @tparam Type List of types.
- */
- template<typename... Type>
- struct exclude_t final: type_list<Type...> {
- /*! @brief Default constructor. */
- explicit constexpr exclude_t() = default;
- };
- /**
- * @brief Variable template for exclusion lists.
- * @tparam Type List of types.
- */
- template<typename... Type>
- inline constexpr exclude_t<Type...> exclude{};
- /**
- * @brief Alias for lists of observed elements.
- * @tparam Type List of types.
- */
- template<typename... Type>
- struct get_t final: type_list<Type...> {
- /*! @brief Default constructor. */
- explicit constexpr get_t() = default;
- };
- /**
- * @brief Variable template for lists of observed elements.
- * @tparam Type List of types.
- */
- template<typename... Type>
- inline constexpr get_t<Type...> get{};
- /**
- * @brief Alias for lists of owned elements.
- * @tparam Type List of types.
- */
- template<typename... Type>
- struct owned_t final: type_list<Type...> {
- /*! @brief Default constructor. */
- explicit constexpr owned_t() = default;
- };
- /**
- * @brief Variable template for lists of owned elements.
- * @tparam Type List of types.
- */
- template<typename... Type>
- inline constexpr owned_t<Type...> owned{};
- /**
- * @brief Applies a given _function_ to a get list and generate a new list.
- * @tparam Type Types provided by the get list.
- * @tparam Op Unary operation as template class with a type member named `type`.
- */
- template<typename... Type, template<typename...> class Op>
- struct type_list_transform<get_t<Type...>, Op> {
- /*! @brief Resulting get list after applying the transform function. */
- using type = get_t<typename Op<Type>::type...>;
- };
- /**
- * @brief Applies a given _function_ to an exclude list and generate a new list.
- * @tparam Type Types provided by the exclude list.
- * @tparam Op Unary operation as template class with a type member named `type`.
- */
- template<typename... Type, template<typename...> class Op>
- struct type_list_transform<exclude_t<Type...>, Op> {
- /*! @brief Resulting exclude list after applying the transform function. */
- using type = exclude_t<typename Op<Type>::type...>;
- };
- /**
- * @brief Applies a given _function_ to an owned list and generate a new list.
- * @tparam Type Types provided by the owned list.
- * @tparam Op Unary operation as template class with a type member named `type`.
- */
- template<typename... Type, template<typename...> class Op>
- struct type_list_transform<owned_t<Type...>, Op> {
- /*! @brief Resulting owned list after applying the transform function. */
- using type = owned_t<typename Op<Type>::type...>;
- };
- /**
- * @brief Provides a common way to define storage types.
- * @tparam Type Storage value type.
- * @tparam Entity A valid entity type.
- * @tparam Allocator Type of allocator used to manage memory and elements.
- */
- template<typename Type, typename Entity = entity, typename Allocator = std::allocator<Type>, typename = void>
- struct storage_type {
- /*! @brief Type-to-storage conversion result. */
- using type = ENTT_STORAGE(sigh_mixin, basic_storage<Type, Entity, Allocator>);
- };
- /*! @brief Empty value type for reactive storage types. */
- struct reactive final {};
- /**
- * @ brief Partial specialization for reactive storage types.
- * @tparam Entity A valid entity type.
- * @tparam Allocator Type of allocator used to manage memory and elements.
- */
- template<typename Entity, typename Allocator>
- struct storage_type<reactive, Entity, Allocator> {
- /*! @brief Type-to-storage conversion result. */
- using type = ENTT_STORAGE(reactive_mixin, basic_storage<reactive, Entity, Allocator>);
- };
- /**
- * @brief Helper type.
- * @tparam Args Arguments to forward.
- */
- template<typename... Args>
- using storage_type_t = typename storage_type<Args...>::type;
- /**
- * Type-to-storage conversion utility that preserves constness.
- * @tparam Type Storage value type, eventually const.
- * @tparam Entity A valid entity type.
- * @tparam Allocator Type of allocator used to manage memory and elements.
- */
- template<typename Type, typename Entity = entity, typename Allocator = std::allocator<std::remove_const_t<Type>>>
- struct storage_for {
- /*! @brief Type-to-storage conversion result. */
- using type = constness_as_t<storage_type_t<std::remove_const_t<Type>, Entity, Allocator>, Type>;
- };
- /**
- * @brief Helper type.
- * @tparam Args Arguments to forward.
- */
- template<typename... Args>
- using storage_for_t = typename storage_for<Args...>::type;
- /**
- * @brief Alias declaration for the most common use case.
- * @tparam Get Types of storage iterated by the view.
- * @tparam Exclude Types of storage used to filter the view.
- */
- template<typename Get, typename Exclude = exclude_t<>>
- using view = basic_view<type_list_transform_t<Get, storage_for>, type_list_transform_t<Exclude, storage_for>>;
- /**
- * @brief Alias declaration for the most common use case.
- * @tparam Owned Types of storage _owned_ by the group.
- * @tparam Get Types of storage _observed_ by the group.
- * @tparam Exclude Types of storage used to filter the group.
- */
- template<typename Owned, typename Get = get_t<>, typename Exclude = exclude_t<>>
- using group = basic_group<type_list_transform_t<Owned, storage_for>, type_list_transform_t<Get, storage_for>, type_list_transform_t<Exclude, storage_for>>;
- } // namespace entt
- #endif
- namespace entt {
- /*! @cond TURN_OFF_DOXYGEN */
- namespace internal {
- template<typename Type, typename = void>
- struct in_place_delete: std::bool_constant<!(std::is_move_constructible_v<Type> && std::is_move_assignable_v<Type>)> {};
- template<>
- struct in_place_delete<void>: std::false_type {};
- template<typename Type>
- struct in_place_delete<Type, std::enable_if_t<Type::in_place_delete>>
- : std::true_type {};
- template<typename Type, typename = void>
- struct page_size: std::integral_constant<std::size_t, !std::is_empty_v<ENTT_ETO_TYPE(Type)> * ENTT_PACKED_PAGE> {};
- template<>
- struct page_size<void>: std::integral_constant<std::size_t, 0u> {};
- template<typename Type>
- struct page_size<Type, std::void_t<decltype(Type::page_size)>>
- : std::integral_constant<std::size_t, Type::page_size> {};
- } // namespace internal
- /*! @endcond */
- /**
- * @brief Common way to access various properties of components.
- * @tparam Type Element type.
- * @tparam Entity A valid entity type.
- */
- template<typename Type, typename Entity, typename>
- struct component_traits {
- static_assert(std::is_same_v<std::decay_t<Type>, Type>, "Unsupported type");
- /*! @brief Element type. */
- using element_type = Type;
- /*! @brief Underlying entity identifier. */
- using entity_type = Entity;
- /*! @brief Pointer stability, default is `false`. */
- static constexpr bool in_place_delete = internal::in_place_delete<Type>::value;
- /*! @brief Page size, default is `ENTT_PACKED_PAGE` for non-empty types. */
- static constexpr std::size_t page_size = internal::page_size<Type>::value;
- };
- } // namespace entt
- #endif
- // #include "entity/entity.hpp"
- #ifndef ENTT_ENTITY_ENTITY_HPP
- #define ENTT_ENTITY_ENTITY_HPP
- #include <cstddef>
- #include <cstdint>
- #include <type_traits>
- // #include "../config/config.h"
- // #include "../core/bit.hpp"
- #ifndef ENTT_CORE_BIT_HPP
- #define ENTT_CORE_BIT_HPP
- #include <cstddef>
- #include <limits>
- #include <type_traits>
- // #include "../config/config.h"
- namespace entt {
- /**
- * @brief Returns the number of set bits in a value (waiting for C++20 and
- * `std::popcount`).
- * @tparam Type Unsigned integer type.
- * @param value A value of unsigned integer type.
- * @return The number of set bits in the value.
- */
- template<typename Type>
- [[nodiscard]] constexpr std::enable_if_t<std::is_unsigned_v<Type>, int> popcount(const Type value) noexcept {
- return value ? (int(value & 1) + popcount(static_cast<Type>(value >> 1))) : 0;
- }
- /**
- * @brief Checks whether a value is a power of two or not (waiting for C++20 and
- * `std::has_single_bit`).
- * @tparam Type Unsigned integer type.
- * @param value A value of unsigned integer type.
- * @return True if the value is a power of two, false otherwise.
- */
- template<typename Type>
- [[nodiscard]] constexpr std::enable_if_t<std::is_unsigned_v<Type>, bool> has_single_bit(const Type value) noexcept {
- return value && ((value & (value - 1)) == 0);
- }
- /**
- * @brief Computes the smallest power of two greater than or equal to a value
- * (waiting for C++20 and `std::bit_ceil`).
- * @tparam Type Unsigned integer type.
- * @param value A value of unsigned integer type.
- * @return The smallest power of two greater than or equal to the given value.
- */
- template<typename Type>
- [[nodiscard]] constexpr std::enable_if_t<std::is_unsigned_v<Type>, Type> next_power_of_two(const Type value) noexcept {
- // NOLINTNEXTLINE(bugprone-assert-side-effect)
- ENTT_ASSERT_CONSTEXPR(value < (Type{1u} << (std::numeric_limits<Type>::digits - 1)), "Numeric limits exceeded");
- Type curr = value - (value != 0u);
- for(int next = 1; next < std::numeric_limits<Type>::digits; next = next * 2) {
- curr |= (curr >> next);
- }
- return ++curr;
- }
- /**
- * @brief Fast module utility function (powers of two only).
- * @tparam Type Unsigned integer type.
- * @param value A value of unsigned integer type.
- * @param mod _Modulus_, it must be a power of two.
- * @return The common remainder.
- */
- template<typename Type>
- [[nodiscard]] constexpr std::enable_if_t<std::is_unsigned_v<Type>, Type> fast_mod(const Type value, const std::size_t mod) noexcept {
- ENTT_ASSERT_CONSTEXPR(has_single_bit(mod), "Value must be a power of two");
- return static_cast<Type>(value & (mod - 1u));
- }
- } // namespace entt
- #endif
- // #include "fwd.hpp"
- namespace entt {
- /*! @cond TURN_OFF_DOXYGEN */
- namespace internal {
- template<typename, typename = void>
- struct entt_traits;
- template<typename Type>
- struct entt_traits<Type, std::enable_if_t<std::is_enum_v<Type>>>
- : entt_traits<std::underlying_type_t<Type>> {
- using value_type = Type;
- };
- template<typename Type>
- struct entt_traits<Type, std::enable_if_t<std::is_class_v<Type>>>
- : entt_traits<typename Type::entity_type> {
- using value_type = Type;
- };
- template<>
- struct entt_traits<std::uint32_t> {
- using value_type = std::uint32_t;
- using entity_type = std::uint32_t;
- using version_type = std::uint16_t;
- static constexpr entity_type entity_mask = 0xFFFFF;
- static constexpr entity_type version_mask = 0xFFF;
- };
- template<>
- struct entt_traits<std::uint64_t> {
- using value_type = std::uint64_t;
- using entity_type = std::uint64_t;
- using version_type = std::uint32_t;
- static constexpr entity_type entity_mask = 0xFFFFFFFF;
- static constexpr entity_type version_mask = 0xFFFFFFFF;
- };
- } // namespace internal
- /*! @endcond */
- /**
- * @brief Common basic entity traits implementation.
- * @tparam Traits Actual entity traits to use.
- */
- template<typename Traits>
- class basic_entt_traits {
- static constexpr auto length = popcount(Traits::entity_mask);
- static_assert(Traits::entity_mask && ((Traits::entity_mask & (Traits::entity_mask + 1)) == 0), "Invalid entity mask");
- static_assert((Traits::version_mask & (Traits::version_mask + 1)) == 0, "Invalid version mask");
- public:
- /*! @brief Value type. */
- using value_type = typename Traits::value_type;
- /*! @brief Underlying entity type. */
- using entity_type = typename Traits::entity_type;
- /*! @brief Underlying version type. */
- using version_type = typename Traits::version_type;
- /*! @brief Entity mask size. */
- static constexpr entity_type entity_mask = Traits::entity_mask;
- /*! @brief Version mask size */
- static constexpr entity_type version_mask = Traits::version_mask;
- /**
- * @brief Converts an entity to its underlying type.
- * @param value The value to convert.
- * @return The integral representation of the given value.
- */
- [[nodiscard]] static constexpr entity_type to_integral(const value_type value) noexcept {
- return static_cast<entity_type>(value);
- }
- /**
- * @brief Returns the entity part once converted to the underlying type.
- * @param value The value to convert.
- * @return The integral representation of the entity part.
- */
- [[nodiscard]] static constexpr entity_type to_entity(const value_type value) noexcept {
- return (to_integral(value) & entity_mask);
- }
- /**
- * @brief Returns the version part once converted to the underlying type.
- * @param value The value to convert.
- * @return The integral representation of the version part.
- */
- [[nodiscard]] static constexpr version_type to_version(const value_type value) noexcept {
- if constexpr(Traits::version_mask == 0u) {
- return version_type{};
- } else {
- return (static_cast<version_type>(to_integral(value) >> length) & version_mask);
- }
- }
- /**
- * @brief Returns the successor of a given identifier.
- * @param value The identifier of which to return the successor.
- * @return The successor of the given identifier.
- */
- [[nodiscard]] static constexpr value_type next(const value_type value) noexcept {
- const auto vers = to_version(value) + 1;
- return construct(to_integral(value), static_cast<version_type>(vers + (vers == version_mask)));
- }
- /**
- * @brief Constructs an identifier from its parts.
- *
- * If the version part is not provided, a tombstone is returned.<br/>
- * If the entity part is not provided, a null identifier is returned.
- *
- * @param entity The entity part of the identifier.
- * @param version The version part of the identifier.
- * @return A properly constructed identifier.
- */
- [[nodiscard]] static constexpr value_type construct(const entity_type entity, const version_type version) noexcept {
- if constexpr(Traits::version_mask == 0u) {
- return value_type{entity & entity_mask};
- } else {
- return value_type{(entity & entity_mask) | (static_cast<entity_type>(version & version_mask) << length)};
- }
- }
- /**
- * @brief Combines two identifiers in a single one.
- *
- * The returned identifier is a copy of the first element except for its
- * version, which is taken from the second element.
- *
- * @param lhs The identifier from which to take the entity part.
- * @param rhs The identifier from which to take the version part.
- * @return A properly constructed identifier.
- */
- [[nodiscard]] static constexpr value_type combine(const entity_type lhs, const entity_type rhs) noexcept {
- if constexpr(Traits::version_mask == 0u) {
- return value_type{lhs & entity_mask};
- } else {
- return value_type{(lhs & entity_mask) | (rhs & (version_mask << length))};
- }
- }
- };
- /**
- * @brief Entity traits.
- * @tparam Type Type of identifier.
- */
- template<typename Type>
- struct entt_traits: basic_entt_traits<internal::entt_traits<Type>> {
- /*! @brief Base type. */
- using base_type = basic_entt_traits<internal::entt_traits<Type>>;
- /*! @brief Page size, default is `ENTT_SPARSE_PAGE`. */
- static constexpr std::size_t page_size = ENTT_SPARSE_PAGE;
- };
- /**
- * @brief Converts an entity to its underlying type.
- * @tparam Entity The value type.
- * @param value The value to convert.
- * @return The integral representation of the given value.
- */
- template<typename Entity>
- [[nodiscard]] constexpr typename entt_traits<Entity>::entity_type to_integral(const Entity value) noexcept {
- return entt_traits<Entity>::to_integral(value);
- }
- /**
- * @brief Returns the entity part once converted to the underlying type.
- * @tparam Entity The value type.
- * @param value The value to convert.
- * @return The integral representation of the entity part.
- */
- template<typename Entity>
- [[nodiscard]] constexpr typename entt_traits<Entity>::entity_type to_entity(const Entity value) noexcept {
- return entt_traits<Entity>::to_entity(value);
- }
- /**
- * @brief Returns the version part once converted to the underlying type.
- * @tparam Entity The value type.
- * @param value The value to convert.
- * @return The integral representation of the version part.
- */
- template<typename Entity>
- [[nodiscard]] constexpr typename entt_traits<Entity>::version_type to_version(const Entity value) noexcept {
- return entt_traits<Entity>::to_version(value);
- }
- /*! @brief Null object for all identifiers. */
- struct null_t {
- /**
- * @brief Converts the null object to identifiers of any type.
- * @tparam Entity Type of identifier.
- * @return The null representation for the given type.
- */
- template<typename Entity>
- [[nodiscard]] constexpr operator Entity() const noexcept {
- using traits_type = entt_traits<Entity>;
- constexpr auto value = traits_type::construct(traits_type::entity_mask, traits_type::version_mask);
- return value;
- }
- /**
- * @brief Compares two null objects.
- * @param other A null object.
- * @return True in all cases.
- */
- [[nodiscard]] constexpr bool operator==([[maybe_unused]] const null_t other) const noexcept {
- return true;
- }
- /**
- * @brief Compares two null objects.
- * @param other A null object.
- * @return False in all cases.
- */
- [[nodiscard]] constexpr bool operator!=([[maybe_unused]] const null_t other) const noexcept {
- return false;
- }
- /**
- * @brief Compares a null object and an identifier of any type.
- * @tparam Entity Type of identifier.
- * @param entity Identifier with which to compare.
- * @return False if the two elements differ, true otherwise.
- */
- template<typename Entity>
- [[nodiscard]] constexpr bool operator==(const Entity entity) const noexcept {
- using traits_type = entt_traits<Entity>;
- return traits_type::to_entity(entity) == traits_type::to_entity(*this);
- }
- /**
- * @brief Compares a null object and an identifier of any type.
- * @tparam Entity Type of identifier.
- * @param entity Identifier with which to compare.
- * @return True if the two elements differ, false otherwise.
- */
- template<typename Entity>
- [[nodiscard]] constexpr bool operator!=(const Entity entity) const noexcept {
- return !(entity == *this);
- }
- };
- /**
- * @brief Compares a null object and an identifier of any type.
- * @tparam Entity Type of identifier.
- * @param lhs Identifier with which to compare.
- * @param rhs A null object yet to be converted.
- * @return False if the two elements differ, true otherwise.
- */
- template<typename Entity>
- [[nodiscard]] constexpr bool operator==(const Entity lhs, const null_t rhs) noexcept {
- return rhs.operator==(lhs);
- }
- /**
- * @brief Compares a null object and an identifier of any type.
- * @tparam Entity Type of identifier.
- * @param lhs Identifier with which to compare.
- * @param rhs A null object yet to be converted.
- * @return True if the two elements differ, false otherwise.
- */
- template<typename Entity>
- [[nodiscard]] constexpr bool operator!=(const Entity lhs, const null_t rhs) noexcept {
- return !(rhs == lhs);
- }
- /*! @brief Tombstone object for all identifiers. */
- struct tombstone_t {
- /**
- * @brief Converts the tombstone object to identifiers of any type.
- * @tparam Entity Type of identifier.
- * @return The tombstone representation for the given type.
- */
- template<typename Entity>
- [[nodiscard]] constexpr operator Entity() const noexcept {
- using traits_type = entt_traits<Entity>;
- constexpr auto value = traits_type::construct(traits_type::entity_mask, traits_type::version_mask);
- return value;
- }
- /**
- * @brief Compares two tombstone objects.
- * @param other A tombstone object.
- * @return True in all cases.
- */
- [[nodiscard]] constexpr bool operator==([[maybe_unused]] const tombstone_t other) const noexcept {
- return true;
- }
- /**
- * @brief Compares two tombstone objects.
- * @param other A tombstone object.
- * @return False in all cases.
- */
- [[nodiscard]] constexpr bool operator!=([[maybe_unused]] const tombstone_t other) const noexcept {
- return false;
- }
- /**
- * @brief Compares a tombstone object and an identifier of any type.
- * @tparam Entity Type of identifier.
- * @param entity Identifier with which to compare.
- * @return False if the two elements differ, true otherwise.
- */
- template<typename Entity>
- [[nodiscard]] constexpr bool operator==(const Entity entity) const noexcept {
- using traits_type = entt_traits<Entity>;
- if constexpr(traits_type::version_mask == 0u) {
- return false;
- } else {
- return (traits_type::to_version(entity) == traits_type::to_version(*this));
- }
- }
- /**
- * @brief Compares a tombstone object and an identifier of any type.
- * @tparam Entity Type of identifier.
- * @param entity Identifier with which to compare.
- * @return True if the two elements differ, false otherwise.
- */
- template<typename Entity>
- [[nodiscard]] constexpr bool operator!=(const Entity entity) const noexcept {
- return !(entity == *this);
- }
- };
- /**
- * @brief Compares a tombstone object and an identifier of any type.
- * @tparam Entity Type of identifier.
- * @param lhs Identifier with which to compare.
- * @param rhs A tombstone object yet to be converted.
- * @return False if the two elements differ, true otherwise.
- */
- template<typename Entity>
- [[nodiscard]] constexpr bool operator==(const Entity lhs, const tombstone_t rhs) noexcept {
- return rhs.operator==(lhs);
- }
- /**
- * @brief Compares a tombstone object and an identifier of any type.
- * @tparam Entity Type of identifier.
- * @param lhs Identifier with which to compare.
- * @param rhs A tombstone object yet to be converted.
- * @return True if the two elements differ, false otherwise.
- */
- template<typename Entity>
- [[nodiscard]] constexpr bool operator!=(const Entity lhs, const tombstone_t rhs) noexcept {
- return !(rhs == lhs);
- }
- /**
- * @brief Compile-time constant for null entities.
- *
- * There exist implicit conversions from this variable to identifiers of any
- * allowed type. Similarly, there exist comparison operators between the null
- * entity and any other identifier.
- */
- inline constexpr null_t null{};
- /**
- * @brief Compile-time constant for tombstone entities.
- *
- * There exist implicit conversions from this variable to identifiers of any
- * allowed type. Similarly, there exist comparison operators between the
- * tombstone entity and any other identifier.
- */
- inline constexpr tombstone_t tombstone{};
- } // namespace entt
- #endif
- // #include "entity/group.hpp"
- #ifndef ENTT_ENTITY_GROUP_HPP
- #define ENTT_ENTITY_GROUP_HPP
- #include <array>
- #include <cstddef>
- #include <iterator>
- #include <tuple>
- #include <type_traits>
- #include <utility>
- // #include "../config/config.h"
- // #include "../core/algorithm.hpp"
- #ifndef ENTT_CORE_ALGORITHM_HPP
- #define ENTT_CORE_ALGORITHM_HPP
- #include <algorithm>
- #include <functional>
- #include <iterator>
- #include <utility>
- #include <vector>
- // #include "utility.hpp"
- #ifndef ENTT_CORE_UTILITY_HPP
- #define ENTT_CORE_UTILITY_HPP
- #include <type_traits>
- #include <utility>
- namespace entt {
- /*! @brief Identity function object (waiting for C++20). */
- struct identity {
- /*! @brief Indicates that this is a transparent function object. */
- using is_transparent = void;
- /**
- * @brief Returns its argument unchanged.
- * @tparam Type Type of the argument.
- * @param value The actual argument.
- * @return The submitted value as-is.
- */
- template<typename Type>
- [[nodiscard]] constexpr Type &&operator()(Type &&value) const noexcept {
- return std::forward<Type>(value);
- }
- };
- /**
- * @brief Constant utility to disambiguate overloaded members of a class.
- * @tparam Type Type of the desired overload.
- * @tparam Class Type of class to which the member belongs.
- * @param member A valid pointer to a member.
- * @return Pointer to the member.
- */
- template<typename Type, typename Class>
- [[nodiscard]] constexpr auto overload(Type Class::*member) noexcept {
- return member;
- }
- /**
- * @brief Constant utility to disambiguate overloaded functions.
- * @tparam Func Function type of the desired overload.
- * @param func A valid pointer to a function.
- * @return Pointer to the function.
- */
- template<typename Func>
- [[nodiscard]] constexpr auto overload(Func *func) noexcept {
- return func;
- }
- /**
- * @brief Helper type for visitors.
- * @tparam Func Types of function objects.
- */
- template<typename... Func>
- struct overloaded: Func... {
- using Func::operator()...;
- };
- /**
- * @brief Deduction guide.
- * @tparam Func Types of function objects.
- */
- template<typename... Func>
- overloaded(Func...) -> overloaded<Func...>;
- /**
- * @brief Basic implementation of a y-combinator.
- * @tparam Func Type of a potentially recursive function.
- */
- template<typename Func>
- struct y_combinator {
- /**
- * @brief Constructs a y-combinator from a given function.
- * @param recursive A potentially recursive function.
- */
- constexpr y_combinator(Func recursive) noexcept(std::is_nothrow_move_constructible_v<Func>)
- : func{std::move(recursive)} {}
- /**
- * @brief Invokes a y-combinator and therefore its underlying function.
- * @tparam Args Types of arguments to use to invoke the underlying function.
- * @param args Parameters to use to invoke the underlying function.
- * @return Return value of the underlying function, if any.
- */
- template<typename... Args>
- constexpr decltype(auto) operator()(Args &&...args) const noexcept(std::is_nothrow_invocable_v<Func, const y_combinator &, Args...>) {
- return func(*this, std::forward<Args>(args)...);
- }
- /*! @copydoc operator()() */
- template<typename... Args>
- constexpr decltype(auto) operator()(Args &&...args) noexcept(std::is_nothrow_invocable_v<Func, y_combinator &, Args...>) {
- return func(*this, std::forward<Args>(args)...);
- }
- private:
- Func func;
- };
- } // namespace entt
- #endif
- namespace entt {
- /**
- * @brief Function object to wrap `std::sort` in a class type.
- *
- * Unfortunately, `std::sort` cannot be passed as template argument to a class
- * template or a function template.<br/>
- * This class fills the gap by wrapping some flavors of `std::sort` in a
- * function object.
- */
- struct std_sort {
- /**
- * @brief Sorts the elements in a range.
- *
- * Sorts the elements in a range using the given binary comparison function.
- *
- * @tparam It Type of random access iterator.
- * @tparam Compare Type of comparison function object.
- * @tparam Args Types of arguments to forward to the sort function.
- * @param first An iterator to the first element of the range to sort.
- * @param last An iterator past the last element of the range to sort.
- * @param compare A valid comparison function object.
- * @param args Arguments to forward to the sort function, if any.
- */
- template<typename It, typename Compare = std::less<>, typename... Args>
- void operator()(It first, It last, Compare compare = Compare{}, Args &&...args) const {
- std::sort(std::forward<Args>(args)..., std::move(first), std::move(last), std::move(compare));
- }
- };
- /*! @brief Function object for performing insertion sort. */
- struct insertion_sort {
- /**
- * @brief Sorts the elements in a range.
- *
- * Sorts the elements in a range using the given binary comparison function.
- *
- * @tparam It Type of random access iterator.
- * @tparam Compare Type of comparison function object.
- * @param first An iterator to the first element of the range to sort.
- * @param last An iterator past the last element of the range to sort.
- * @param compare A valid comparison function object.
- */
- template<typename It, typename Compare = std::less<>>
- void operator()(It first, It last, Compare compare = Compare{}) const {
- if(first < last) {
- for(auto it = first + 1; it < last; ++it) {
- auto value = std::move(*it);
- auto pre = it;
- // NOLINTBEGIN(cppcoreguidelines-pro-bounds-pointer-arithmetic)
- for(; pre > first && compare(value, *(pre - 1)); --pre) {
- *pre = std::move(*(pre - 1));
- }
- // NOLINTEND(cppcoreguidelines-pro-bounds-pointer-arithmetic)
- *pre = std::move(value);
- }
- }
- }
- };
- /**
- * @brief Function object for performing LSD radix sort.
- * @tparam Bit Number of bits processed per pass.
- * @tparam N Maximum number of bits to sort.
- */
- template<std::size_t Bit, std::size_t N>
- struct radix_sort {
- static_assert((N % Bit) == 0, "The maximum number of bits to sort must be a multiple of the number of bits processed per pass");
- /**
- * @brief Sorts the elements in a range.
- *
- * Sorts the elements in a range using the given _getter_ to access the
- * actual data to be sorted.
- *
- * This implementation is inspired by the online book
- * [Physically Based Rendering](http://www.pbr-book.org/3ed-2018/Primitives_and_Intersection_Acceleration/Bounding_Volume_Hierarchies.html#RadixSort).
- *
- * @tparam It Type of random access iterator.
- * @tparam Getter Type of _getter_ function object.
- * @param first An iterator to the first element of the range to sort.
- * @param last An iterator past the last element of the range to sort.
- * @param getter A valid _getter_ function object.
- */
- template<typename It, typename Getter = identity>
- void operator()(It first, It last, Getter getter = Getter{}) const {
- if(first < last) {
- constexpr auto passes = N / Bit;
- using value_type = typename std::iterator_traits<It>::value_type;
- using difference_type = typename std::iterator_traits<It>::difference_type;
- std::vector<value_type> aux(static_cast<std::size_t>(std::distance(first, last)));
- auto part = [getter = std::move(getter)](auto from, auto to, auto out, auto start) {
- constexpr auto mask = (1 << Bit) - 1;
- constexpr auto buckets = 1 << Bit;
- // NOLINTNEXTLINE(cppcoreguidelines-avoid-c-arrays, modernize-avoid-c-arrays, misc-const-correctness)
- std::size_t count[buckets]{};
- for(auto it = from; it != to; ++it) {
- ++count[(getter(*it) >> start) & mask];
- }
- // NOLINTNEXTLINE(cppcoreguidelines-avoid-c-arrays, modernize-avoid-c-arrays)
- std::size_t index[buckets]{};
- for(std::size_t pos{}, end = buckets - 1u; pos < end; ++pos) {
- index[pos + 1u] = index[pos] + count[pos];
- }
- for(auto it = from; it != to; ++it) {
- const auto pos = index[(getter(*it) >> start) & mask]++;
- out[static_cast<difference_type>(pos)] = std::move(*it);
- }
- };
- for(std::size_t pass = 0; pass < (passes & ~1u); pass += 2) {
- part(first, last, aux.begin(), pass * Bit);
- part(aux.begin(), aux.end(), first, (pass + 1) * Bit);
- }
- if constexpr(passes & 1) {
- part(first, last, aux.begin(), (passes - 1) * Bit);
- std::move(aux.begin(), aux.end(), first);
- }
- }
- }
- };
- } // namespace entt
- #endif
- // #include "../core/fwd.hpp"
- // #include "../core/iterator.hpp"
- #ifndef ENTT_CORE_ITERATOR_HPP
- #define ENTT_CORE_ITERATOR_HPP
- #include <iterator>
- #include <memory>
- #include <type_traits>
- #include <utility>
- namespace entt {
- /**
- * @brief Helper type to use as pointer with input iterators.
- * @tparam Type of wrapped value.
- */
- template<typename Type>
- struct input_iterator_pointer final {
- /*! @brief Value type. */
- using value_type = Type;
- /*! @brief Pointer type. */
- using pointer = Type *;
- /*! @brief Reference type. */
- using reference = Type &;
- /**
- * @brief Constructs a proxy object by move.
- * @param val Value to use to initialize the proxy object.
- */
- constexpr input_iterator_pointer(value_type &&val) noexcept(std::is_nothrow_move_constructible_v<value_type>)
- : value{std::move(val)} {}
- /**
- * @brief Access operator for accessing wrapped values.
- * @return A pointer to the wrapped value.
- */
- [[nodiscard]] constexpr pointer operator->() noexcept {
- return std::addressof(value);
- }
- /**
- * @brief Dereference operator for accessing wrapped values.
- * @return A reference to the wrapped value.
- */
- [[nodiscard]] constexpr reference operator*() noexcept {
- return value;
- }
- private:
- Type value;
- };
- /**
- * @brief Plain iota iterator (waiting for C++20).
- * @tparam Type Value type.
- */
- template<typename Type>
- class iota_iterator final {
- static_assert(std::is_integral_v<Type>, "Not an integral type");
- public:
- /*! @brief Value type, likely an integral one. */
- using value_type = Type;
- /*! @brief Invalid pointer type. */
- using pointer = void;
- /*! @brief Non-reference type, same as value type. */
- using reference = value_type;
- /*! @brief Difference type. */
- using difference_type = std::ptrdiff_t;
- /*! @brief Iterator category. */
- using iterator_category = std::input_iterator_tag;
- /*! @brief Default constructor. */
- constexpr iota_iterator() noexcept
- : current{} {}
- /**
- * @brief Constructs an iota iterator from a given value.
- * @param init The initial value assigned to the iota iterator.
- */
- constexpr iota_iterator(const value_type init) noexcept
- : current{init} {}
- /**
- * @brief Pre-increment operator.
- * @return This iota iterator.
- */
- constexpr iota_iterator &operator++() noexcept {
- return ++current, *this;
- }
- /**
- * @brief Post-increment operator.
- * @return This iota iterator.
- */
- constexpr iota_iterator operator++(int) noexcept {
- const iota_iterator orig = *this;
- return ++(*this), orig;
- }
- /**
- * @brief Dereference operator.
- * @return The underlying value.
- */
- [[nodiscard]] constexpr reference operator*() const noexcept {
- return current;
- }
- private:
- value_type current;
- };
- /**
- * @brief Comparison operator.
- * @tparam Type Value type of the iota iterator.
- * @param lhs A properly initialized iota iterator.
- * @param rhs A properly initialized iota iterator.
- * @return True if the two iterators are identical, false otherwise.
- */
- template<typename Type>
- [[nodiscard]] constexpr bool operator==(const iota_iterator<Type> &lhs, const iota_iterator<Type> &rhs) noexcept {
- return *lhs == *rhs;
- }
- /**
- * @brief Comparison operator.
- * @tparam Type Value type of the iota iterator.
- * @param lhs A properly initialized iota iterator.
- * @param rhs A properly initialized iota iterator.
- * @return True if the two iterators differ, false otherwise.
- */
- template<typename Type>
- [[nodiscard]] constexpr bool operator!=(const iota_iterator<Type> &lhs, const iota_iterator<Type> &rhs) noexcept {
- return !(lhs == rhs);
- }
- /**
- * @brief Utility class to create an iterable object from a pair of iterators.
- * @tparam It Type of iterator.
- * @tparam Sentinel Type of sentinel.
- */
- template<typename It, typename Sentinel = It>
- struct iterable_adaptor final {
- /*! @brief Value type. */
- using value_type = typename std::iterator_traits<It>::value_type;
- /*! @brief Iterator type. */
- using iterator = It;
- /*! @brief Sentinel type. */
- using sentinel = Sentinel;
- /*! @brief Default constructor. */
- constexpr iterable_adaptor() noexcept(std::is_nothrow_default_constructible_v<iterator> && std::is_nothrow_default_constructible_v<sentinel>)
- : first{},
- last{} {}
- /**
- * @brief Creates an iterable object from a pair of iterators.
- * @param from Begin iterator.
- * @param to End iterator.
- */
- constexpr iterable_adaptor(iterator from, sentinel to) noexcept(std::is_nothrow_move_constructible_v<iterator> && std::is_nothrow_move_constructible_v<sentinel>)
- : first{std::move(from)},
- last{std::move(to)} {}
- /**
- * @brief Returns an iterator to the beginning.
- * @return An iterator to the first element of the range.
- */
- [[nodiscard]] constexpr iterator begin() const noexcept {
- return first;
- }
- /**
- * @brief Returns an iterator to the end.
- * @return An iterator to the element following the last element of the
- * range.
- */
- [[nodiscard]] constexpr sentinel end() const noexcept {
- return last;
- }
- /*! @copydoc begin */
- [[nodiscard]] constexpr iterator cbegin() const noexcept {
- return begin();
- }
- /*! @copydoc end */
- [[nodiscard]] constexpr sentinel cend() const noexcept {
- return end();
- }
- private:
- It first;
- Sentinel last;
- };
- } // namespace entt
- #endif
- // #include "../core/type_info.hpp"
- #ifndef ENTT_CORE_TYPE_INFO_HPP
- #define ENTT_CORE_TYPE_INFO_HPP
- #include <string_view>
- #include <type_traits>
- #include <utility>
- // #include "../config/config.h"
- // #include "fwd.hpp"
- // #include "hashed_string.hpp"
- #ifndef ENTT_CORE_HASHED_STRING_HPP
- #define ENTT_CORE_HASHED_STRING_HPP
- #include <cstddef>
- #include <cstdint>
- // #include "fwd.hpp"
- namespace entt {
- /*! @cond TURN_OFF_DOXYGEN */
- namespace internal {
- template<typename = id_type>
- struct fnv_1a_params;
- template<>
- struct fnv_1a_params<std::uint32_t> {
- static constexpr auto offset = 2166136261;
- static constexpr auto prime = 16777619;
- };
- template<>
- struct fnv_1a_params<std::uint64_t> {
- static constexpr auto offset = 14695981039346656037ull;
- static constexpr auto prime = 1099511628211ull;
- };
- template<typename Char>
- struct basic_hashed_string {
- using value_type = Char;
- using size_type = std::size_t;
- using hash_type = id_type;
- const value_type *repr{};
- hash_type hash{fnv_1a_params<>::offset};
- size_type length{};
- };
- } // namespace internal
- /*! @endcond */
- /**
- * @brief Zero overhead unique identifier.
- *
- * A hashed string is a compile-time tool that allows users to use
- * human-readable identifiers in the codebase while using their numeric
- * counterparts at runtime.<br/>
- * Because of that, a hashed string can also be used in constant expressions if
- * required.
- *
- * @warning
- * This class doesn't take ownership of user-supplied strings nor does it make a
- * copy of them.
- *
- * @tparam Char Character type.
- */
- template<typename Char>
- class basic_hashed_string: internal::basic_hashed_string<Char> {
- using base_type = internal::basic_hashed_string<Char>;
- using params = internal::fnv_1a_params<>;
- struct const_wrapper {
- // non-explicit constructor on purpose
- constexpr const_wrapper(const typename base_type::value_type *str) noexcept
- : repr{str} {}
- const typename base_type::value_type *repr;
- };
- public:
- /*! @brief Character type. */
- using value_type = typename base_type::value_type;
- /*! @brief Unsigned integer type. */
- using size_type = typename base_type::size_type;
- /*! @brief Unsigned integer type. */
- using hash_type = typename base_type::hash_type;
- /**
- * @brief Returns directly the numeric representation of a string view.
- * @param str Human-readable identifier.
- * @param len Length of the string to hash.
- * @return The numeric representation of the string.
- */
- [[nodiscard]] static constexpr hash_type value(const value_type *str, const size_type len) noexcept {
- return basic_hashed_string{str, len};
- }
- /**
- * @brief Returns directly the numeric representation of a string.
- * @tparam N Number of characters of the identifier.
- * @param str Human-readable identifier.
- * @return The numeric representation of the string.
- */
- template<std::size_t N>
- // NOLINTNEXTLINE(cppcoreguidelines-avoid-c-arrays, modernize-avoid-c-arrays)
- [[nodiscard]] static ENTT_CONSTEVAL hash_type value(const value_type (&str)[N]) noexcept {
- return basic_hashed_string{str};
- }
- /**
- * @brief Returns directly the numeric representation of a string.
- * @param wrapper Helps achieving the purpose by relying on overloading.
- * @return The numeric representation of the string.
- */
- [[nodiscard]] static constexpr hash_type value(const_wrapper wrapper) noexcept {
- return basic_hashed_string{wrapper};
- }
- /*! @brief Constructs an empty hashed string. */
- constexpr basic_hashed_string() noexcept
- : basic_hashed_string{nullptr, 0u} {}
- /**
- * @brief Constructs a hashed string from a string view.
- * @param str Human-readable identifier.
- * @param len Length of the string to hash.
- */
- constexpr basic_hashed_string(const value_type *str, const size_type len) noexcept
- // NOLINTNEXTLINE(cppcoreguidelines-pro-bounds-array-to-pointer-decay)
- : base_type{str} {
- // NOLINTBEGIN(cppcoreguidelines-pro-bounds-pointer-arithmetic)
- for(; base_type::length < len; ++base_type::length) {
- base_type::hash = (base_type::hash ^ static_cast<id_type>(str[base_type::length])) * params::prime;
- }
- // NOLINTEND(cppcoreguidelines-pro-bounds-pointer-arithmetic)
- }
- /**
- * @brief Constructs a hashed string from an array of const characters.
- * @tparam N Number of characters of the identifier.
- * @param str Human-readable identifier.
- */
- template<std::size_t N>
- // NOLINTNEXTLINE(cppcoreguidelines-avoid-c-arrays, modernize-avoid-c-arrays)
- ENTT_CONSTEVAL basic_hashed_string(const value_type (&str)[N]) noexcept
- // NOLINTNEXTLINE(cppcoreguidelines-pro-bounds-array-to-pointer-decay)
- : base_type{str} {
- for(; str[base_type::length]; ++base_type::length) {
- base_type::hash = (base_type::hash ^ static_cast<id_type>(str[base_type::length])) * params::prime;
- }
- }
- /**
- * @brief Explicit constructor on purpose to avoid constructing a hashed
- * string directly from a `const value_type *`.
- *
- * @warning
- * The lifetime of the string is not extended nor is it copied.
- *
- * @param wrapper Helps achieving the purpose by relying on overloading.
- */
- explicit constexpr basic_hashed_string(const_wrapper wrapper) noexcept
- : base_type{wrapper.repr} {
- // NOLINTBEGIN(cppcoreguidelines-pro-bounds-pointer-arithmetic)
- for(; wrapper.repr[base_type::length]; ++base_type::length) {
- base_type::hash = (base_type::hash ^ static_cast<id_type>(wrapper.repr[base_type::length])) * params::prime;
- }
- // NOLINTEND(cppcoreguidelines-pro-bounds-pointer-arithmetic)
- }
- /**
- * @brief Returns the size of a hashed string.
- * @return The size of the hashed string.
- */
- [[nodiscard]] constexpr size_type size() const noexcept {
- return base_type::length;
- }
- /**
- * @brief Returns the human-readable representation of a hashed string.
- * @return The string used to initialize the hashed string.
- */
- [[nodiscard]] constexpr const value_type *data() const noexcept {
- return base_type::repr;
- }
- /**
- * @brief Returns the numeric representation of a hashed string.
- * @return The numeric representation of the hashed string.
- */
- [[nodiscard]] constexpr hash_type value() const noexcept {
- return base_type::hash;
- }
- /*! @copydoc data */
- [[nodiscard]] explicit constexpr operator const value_type *() const noexcept {
- return data();
- }
- /**
- * @brief Returns the numeric representation of a hashed string.
- * @return The numeric representation of the hashed string.
- */
- [[nodiscard]] constexpr operator hash_type() const noexcept {
- return value();
- }
- };
- /**
- * @brief Deduction guide.
- * @tparam Char Character type.
- * @param str Human-readable identifier.
- * @param len Length of the string to hash.
- */
- template<typename Char>
- basic_hashed_string(const Char *str, std::size_t len) -> basic_hashed_string<Char>;
- /**
- * @brief Deduction guide.
- * @tparam Char Character type.
- * @tparam N Number of characters of the identifier.
- * @param str Human-readable identifier.
- */
- template<typename Char, std::size_t N>
- // NOLINTNEXTLINE(cppcoreguidelines-avoid-c-arrays, modernize-avoid-c-arrays)
- basic_hashed_string(const Char (&str)[N]) -> basic_hashed_string<Char>;
- /**
- * @brief Compares two hashed strings.
- * @tparam Char Character type.
- * @param lhs A valid hashed string.
- * @param rhs A valid hashed string.
- * @return True if the two hashed strings are identical, false otherwise.
- */
- template<typename Char>
- [[nodiscard]] constexpr bool operator==(const basic_hashed_string<Char> &lhs, const basic_hashed_string<Char> &rhs) noexcept {
- return lhs.value() == rhs.value();
- }
- /**
- * @brief Compares two hashed strings.
- * @tparam Char Character type.
- * @param lhs A valid hashed string.
- * @param rhs A valid hashed string.
- * @return True if the two hashed strings differ, false otherwise.
- */
- template<typename Char>
- [[nodiscard]] constexpr bool operator!=(const basic_hashed_string<Char> &lhs, const basic_hashed_string<Char> &rhs) noexcept {
- return !(lhs == rhs);
- }
- /**
- * @brief Compares two hashed strings.
- * @tparam Char Character type.
- * @param lhs A valid hashed string.
- * @param rhs A valid hashed string.
- * @return True if the first element is less than the second, false otherwise.
- */
- template<typename Char>
- [[nodiscard]] constexpr bool operator<(const basic_hashed_string<Char> &lhs, const basic_hashed_string<Char> &rhs) noexcept {
- return lhs.value() < rhs.value();
- }
- /**
- * @brief Compares two hashed strings.
- * @tparam Char Character type.
- * @param lhs A valid hashed string.
- * @param rhs A valid hashed string.
- * @return True if the first element is less than or equal to the second, false
- * otherwise.
- */
- template<typename Char>
- [[nodiscard]] constexpr bool operator<=(const basic_hashed_string<Char> &lhs, const basic_hashed_string<Char> &rhs) noexcept {
- return !(rhs < lhs);
- }
- /**
- * @brief Compares two hashed strings.
- * @tparam Char Character type.
- * @param lhs A valid hashed string.
- * @param rhs A valid hashed string.
- * @return True if the first element is greater than the second, false
- * otherwise.
- */
- template<typename Char>
- [[nodiscard]] constexpr bool operator>(const basic_hashed_string<Char> &lhs, const basic_hashed_string<Char> &rhs) noexcept {
- return rhs < lhs;
- }
- /**
- * @brief Compares two hashed strings.
- * @tparam Char Character type.
- * @param lhs A valid hashed string.
- * @param rhs A valid hashed string.
- * @return True if the first element is greater than or equal to the second,
- * false otherwise.
- */
- template<typename Char>
- [[nodiscard]] constexpr bool operator>=(const basic_hashed_string<Char> &lhs, const basic_hashed_string<Char> &rhs) noexcept {
- return !(lhs < rhs);
- }
- inline namespace literals {
- /**
- * @brief User defined literal for hashed strings.
- * @param str The literal without its suffix.
- * @return A properly initialized hashed string.
- */
- [[nodiscard]] ENTT_CONSTEVAL hashed_string operator""_hs(const char *str, std::size_t) noexcept {
- return hashed_string{str};
- }
- /**
- * @brief User defined literal for hashed wstrings.
- * @param str The literal without its suffix.
- * @return A properly initialized hashed wstring.
- */
- [[nodiscard]] ENTT_CONSTEVAL hashed_wstring operator""_hws(const wchar_t *str, std::size_t) noexcept {
- return hashed_wstring{str};
- }
- } // namespace literals
- } // namespace entt
- #endif
- namespace entt {
- /*! @cond TURN_OFF_DOXYGEN */
- namespace internal {
- struct ENTT_API type_index final {
- [[nodiscard]] static id_type next() noexcept {
- static ENTT_MAYBE_ATOMIC(id_type) value{};
- return value++;
- }
- };
- template<typename Type>
- [[nodiscard]] constexpr const char *pretty_function() noexcept {
- #if defined ENTT_PRETTY_FUNCTION
- return static_cast<const char *>(ENTT_PRETTY_FUNCTION);
- #else
- return "";
- #endif
- }
- template<typename Type>
- [[nodiscard]] constexpr auto stripped_type_name() noexcept {
- #if defined ENTT_PRETTY_FUNCTION
- const std::string_view full_name{pretty_function<Type>()};
- auto first = full_name.find_first_not_of(' ', full_name.find_first_of(ENTT_PRETTY_FUNCTION_PREFIX) + 1);
- auto value = full_name.substr(first, full_name.find_last_of(ENTT_PRETTY_FUNCTION_SUFFIX) - first);
- return value;
- #else
- return std::string_view{};
- #endif
- }
- template<typename Type, auto = stripped_type_name<Type>().find_first_of('.')>
- [[nodiscard]] constexpr std::string_view type_name(int) noexcept {
- constexpr auto value = stripped_type_name<Type>();
- return value;
- }
- template<typename Type>
- [[nodiscard]] std::string_view type_name(char) noexcept {
- static const auto value = stripped_type_name<Type>();
- return value;
- }
- template<typename Type, auto = stripped_type_name<Type>().find_first_of('.')>
- [[nodiscard]] constexpr id_type type_hash(int) noexcept {
- constexpr auto stripped = stripped_type_name<Type>();
- constexpr auto value = hashed_string::value(stripped.data(), stripped.size());
- return value;
- }
- template<typename Type>
- [[nodiscard]] id_type type_hash(char) noexcept {
- static const auto value = [](const auto stripped) {
- return hashed_string::value(stripped.data(), stripped.size());
- }(stripped_type_name<Type>());
- return value;
- }
- } // namespace internal
- /*! @endcond */
- /**
- * @brief Type sequential identifier.
- * @tparam Type Type for which to generate a sequential identifier.
- */
- template<typename Type, typename = void>
- struct ENTT_API type_index final {
- /**
- * @brief Returns the sequential identifier of a given type.
- * @return The sequential identifier of a given type.
- */
- [[nodiscard]] static id_type value() noexcept {
- static const id_type value = internal::type_index::next();
- return value;
- }
- /*! @copydoc value */
- [[nodiscard]] constexpr operator id_type() const noexcept {
- return value();
- }
- };
- /**
- * @brief Type hash.
- * @tparam Type Type for which to generate a hash value.
- */
- template<typename Type, typename = void>
- struct type_hash final {
- /**
- * @brief Returns the numeric representation of a given type.
- * @return The numeric representation of the given type.
- */
- #if defined ENTT_PRETTY_FUNCTION
- [[nodiscard]] static constexpr id_type value() noexcept {
- return internal::type_hash<Type>(0);
- #else
- [[nodiscard]] static constexpr id_type value() noexcept {
- return type_index<Type>::value();
- #endif
- }
- /*! @copydoc value */
- [[nodiscard]] constexpr operator id_type() const noexcept {
- return value();
- }
- };
- /**
- * @brief Type name.
- * @tparam Type Type for which to generate a name.
- */
- template<typename Type, typename = void>
- struct type_name final {
- /**
- * @brief Returns the name of a given type.
- * @return The name of the given type.
- */
- [[nodiscard]] static constexpr std::string_view value() noexcept {
- return internal::type_name<Type>(0);
- }
- /*! @copydoc value */
- [[nodiscard]] constexpr operator std::string_view() const noexcept {
- return value();
- }
- };
- /*! @brief Implementation specific information about a type. */
- struct type_info final {
- /**
- * @brief Constructs a type info object for a given type.
- * @tparam Type Type for which to construct a type info object.
- */
- template<typename Type>
- // NOLINTBEGIN(modernize-use-transparent-functors)
- constexpr type_info(std::in_place_type_t<Type>) noexcept
- : seq{type_index<std::remove_const_t<std::remove_reference_t<Type>>>::value()},
- identifier{type_hash<std::remove_const_t<std::remove_reference_t<Type>>>::value()},
- alias{type_name<std::remove_const_t<std::remove_reference_t<Type>>>::value()} {}
- // NOLINTEND(modernize-use-transparent-functors)
- /**
- * @brief Type index.
- * @return Type index.
- */
- [[nodiscard]] constexpr id_type index() const noexcept {
- return seq;
- }
- /**
- * @brief Type hash.
- * @return Type hash.
- */
- [[nodiscard]] constexpr id_type hash() const noexcept {
- return identifier;
- }
- /**
- * @brief Type name.
- * @return Type name.
- */
- [[nodiscard]] constexpr std::string_view name() const noexcept {
- return alias;
- }
- private:
- id_type seq;
- id_type identifier;
- std::string_view alias;
- };
- /**
- * @brief Compares the contents of two type info objects.
- * @param lhs A type info object.
- * @param rhs A type info object.
- * @return True if the two type info objects are identical, false otherwise.
- */
- [[nodiscard]] constexpr bool operator==(const type_info &lhs, const type_info &rhs) noexcept {
- return lhs.hash() == rhs.hash();
- }
- /**
- * @brief Compares the contents of two type info objects.
- * @param lhs A type info object.
- * @param rhs A type info object.
- * @return True if the two type info objects differ, false otherwise.
- */
- [[nodiscard]] constexpr bool operator!=(const type_info &lhs, const type_info &rhs) noexcept {
- return !(lhs == rhs);
- }
- /**
- * @brief Compares two type info objects.
- * @param lhs A valid type info object.
- * @param rhs A valid type info object.
- * @return True if the first element is less than the second, false otherwise.
- */
- [[nodiscard]] constexpr bool operator<(const type_info &lhs, const type_info &rhs) noexcept {
- return lhs.index() < rhs.index();
- }
- /**
- * @brief Compares two type info objects.
- * @param lhs A valid type info object.
- * @param rhs A valid type info object.
- * @return True if the first element is less than or equal to the second, false
- * otherwise.
- */
- [[nodiscard]] constexpr bool operator<=(const type_info &lhs, const type_info &rhs) noexcept {
- return !(rhs < lhs);
- }
- /**
- * @brief Compares two type info objects.
- * @param lhs A valid type info object.
- * @param rhs A valid type info object.
- * @return True if the first element is greater than the second, false
- * otherwise.
- */
- [[nodiscard]] constexpr bool operator>(const type_info &lhs, const type_info &rhs) noexcept {
- return rhs < lhs;
- }
- /**
- * @brief Compares two type info objects.
- * @param lhs A valid type info object.
- * @param rhs A valid type info object.
- * @return True if the first element is greater than or equal to the second,
- * false otherwise.
- */
- [[nodiscard]] constexpr bool operator>=(const type_info &lhs, const type_info &rhs) noexcept {
- return !(lhs < rhs);
- }
- /**
- * @brief Returns the type info object associated to a given type.
- *
- * The returned element refers to an object with static storage duration.<br/>
- * The type doesn't need to be a complete type. If the type is a reference, the
- * result refers to the referenced type. In all cases, top-level cv-qualifiers
- * are ignored.
- *
- * @tparam Type Type for which to generate a type info object.
- * @return A reference to a properly initialized type info object.
- */
- template<typename Type>
- [[nodiscard]] const type_info &type_id() noexcept {
- if constexpr(std::is_same_v<Type, std::remove_const_t<std::remove_reference_t<Type>>>) {
- static const type_info instance{std::in_place_type<Type>};
- return instance;
- } else {
- return type_id<std::remove_const_t<std::remove_reference_t<Type>>>();
- }
- }
- /*! @copydoc type_id */
- template<typename Type>
- // NOLINTNEXTLINE(cppcoreguidelines-missing-std-forward)
- [[nodiscard]] const type_info &type_id(Type &&) noexcept {
- return type_id<std::remove_const_t<std::remove_reference_t<Type>>>();
- }
- } // namespace entt
- #endif
- // #include "../core/type_traits.hpp"
- // #include "entity.hpp"
- #ifndef ENTT_ENTITY_ENTITY_HPP
- #define ENTT_ENTITY_ENTITY_HPP
- #include <cstddef>
- #include <cstdint>
- #include <type_traits>
- // #include "../config/config.h"
- // #include "../core/bit.hpp"
- // #include "fwd.hpp"
- namespace entt {
- /*! @cond TURN_OFF_DOXYGEN */
- namespace internal {
- template<typename, typename = void>
- struct entt_traits;
- template<typename Type>
- struct entt_traits<Type, std::enable_if_t<std::is_enum_v<Type>>>
- : entt_traits<std::underlying_type_t<Type>> {
- using value_type = Type;
- };
- template<typename Type>
- struct entt_traits<Type, std::enable_if_t<std::is_class_v<Type>>>
- : entt_traits<typename Type::entity_type> {
- using value_type = Type;
- };
- template<>
- struct entt_traits<std::uint32_t> {
- using value_type = std::uint32_t;
- using entity_type = std::uint32_t;
- using version_type = std::uint16_t;
- static constexpr entity_type entity_mask = 0xFFFFF;
- static constexpr entity_type version_mask = 0xFFF;
- };
- template<>
- struct entt_traits<std::uint64_t> {
- using value_type = std::uint64_t;
- using entity_type = std::uint64_t;
- using version_type = std::uint32_t;
- static constexpr entity_type entity_mask = 0xFFFFFFFF;
- static constexpr entity_type version_mask = 0xFFFFFFFF;
- };
- } // namespace internal
- /*! @endcond */
- /**
- * @brief Common basic entity traits implementation.
- * @tparam Traits Actual entity traits to use.
- */
- template<typename Traits>
- class basic_entt_traits {
- static constexpr auto length = popcount(Traits::entity_mask);
- static_assert(Traits::entity_mask && ((Traits::entity_mask & (Traits::entity_mask + 1)) == 0), "Invalid entity mask");
- static_assert((Traits::version_mask & (Traits::version_mask + 1)) == 0, "Invalid version mask");
- public:
- /*! @brief Value type. */
- using value_type = typename Traits::value_type;
- /*! @brief Underlying entity type. */
- using entity_type = typename Traits::entity_type;
- /*! @brief Underlying version type. */
- using version_type = typename Traits::version_type;
- /*! @brief Entity mask size. */
- static constexpr entity_type entity_mask = Traits::entity_mask;
- /*! @brief Version mask size */
- static constexpr entity_type version_mask = Traits::version_mask;
- /**
- * @brief Converts an entity to its underlying type.
- * @param value The value to convert.
- * @return The integral representation of the given value.
- */
- [[nodiscard]] static constexpr entity_type to_integral(const value_type value) noexcept {
- return static_cast<entity_type>(value);
- }
- /**
- * @brief Returns the entity part once converted to the underlying type.
- * @param value The value to convert.
- * @return The integral representation of the entity part.
- */
- [[nodiscard]] static constexpr entity_type to_entity(const value_type value) noexcept {
- return (to_integral(value) & entity_mask);
- }
- /**
- * @brief Returns the version part once converted to the underlying type.
- * @param value The value to convert.
- * @return The integral representation of the version part.
- */
- [[nodiscard]] static constexpr version_type to_version(const value_type value) noexcept {
- if constexpr(Traits::version_mask == 0u) {
- return version_type{};
- } else {
- return (static_cast<version_type>(to_integral(value) >> length) & version_mask);
- }
- }
- /**
- * @brief Returns the successor of a given identifier.
- * @param value The identifier of which to return the successor.
- * @return The successor of the given identifier.
- */
- [[nodiscard]] static constexpr value_type next(const value_type value) noexcept {
- const auto vers = to_version(value) + 1;
- return construct(to_integral(value), static_cast<version_type>(vers + (vers == version_mask)));
- }
- /**
- * @brief Constructs an identifier from its parts.
- *
- * If the version part is not provided, a tombstone is returned.<br/>
- * If the entity part is not provided, a null identifier is returned.
- *
- * @param entity The entity part of the identifier.
- * @param version The version part of the identifier.
- * @return A properly constructed identifier.
- */
- [[nodiscard]] static constexpr value_type construct(const entity_type entity, const version_type version) noexcept {
- if constexpr(Traits::version_mask == 0u) {
- return value_type{entity & entity_mask};
- } else {
- return value_type{(entity & entity_mask) | (static_cast<entity_type>(version & version_mask) << length)};
- }
- }
- /**
- * @brief Combines two identifiers in a single one.
- *
- * The returned identifier is a copy of the first element except for its
- * version, which is taken from the second element.
- *
- * @param lhs The identifier from which to take the entity part.
- * @param rhs The identifier from which to take the version part.
- * @return A properly constructed identifier.
- */
- [[nodiscard]] static constexpr value_type combine(const entity_type lhs, const entity_type rhs) noexcept {
- if constexpr(Traits::version_mask == 0u) {
- return value_type{lhs & entity_mask};
- } else {
- return value_type{(lhs & entity_mask) | (rhs & (version_mask << length))};
- }
- }
- };
- /**
- * @brief Entity traits.
- * @tparam Type Type of identifier.
- */
- template<typename Type>
- struct entt_traits: basic_entt_traits<internal::entt_traits<Type>> {
- /*! @brief Base type. */
- using base_type = basic_entt_traits<internal::entt_traits<Type>>;
- /*! @brief Page size, default is `ENTT_SPARSE_PAGE`. */
- static constexpr std::size_t page_size = ENTT_SPARSE_PAGE;
- };
- /**
- * @brief Converts an entity to its underlying type.
- * @tparam Entity The value type.
- * @param value The value to convert.
- * @return The integral representation of the given value.
- */
- template<typename Entity>
- [[nodiscard]] constexpr typename entt_traits<Entity>::entity_type to_integral(const Entity value) noexcept {
- return entt_traits<Entity>::to_integral(value);
- }
- /**
- * @brief Returns the entity part once converted to the underlying type.
- * @tparam Entity The value type.
- * @param value The value to convert.
- * @return The integral representation of the entity part.
- */
- template<typename Entity>
- [[nodiscard]] constexpr typename entt_traits<Entity>::entity_type to_entity(const Entity value) noexcept {
- return entt_traits<Entity>::to_entity(value);
- }
- /**
- * @brief Returns the version part once converted to the underlying type.
- * @tparam Entity The value type.
- * @param value The value to convert.
- * @return The integral representation of the version part.
- */
- template<typename Entity>
- [[nodiscard]] constexpr typename entt_traits<Entity>::version_type to_version(const Entity value) noexcept {
- return entt_traits<Entity>::to_version(value);
- }
- /*! @brief Null object for all identifiers. */
- struct null_t {
- /**
- * @brief Converts the null object to identifiers of any type.
- * @tparam Entity Type of identifier.
- * @return The null representation for the given type.
- */
- template<typename Entity>
- [[nodiscard]] constexpr operator Entity() const noexcept {
- using traits_type = entt_traits<Entity>;
- constexpr auto value = traits_type::construct(traits_type::entity_mask, traits_type::version_mask);
- return value;
- }
- /**
- * @brief Compares two null objects.
- * @param other A null object.
- * @return True in all cases.
- */
- [[nodiscard]] constexpr bool operator==([[maybe_unused]] const null_t other) const noexcept {
- return true;
- }
- /**
- * @brief Compares two null objects.
- * @param other A null object.
- * @return False in all cases.
- */
- [[nodiscard]] constexpr bool operator!=([[maybe_unused]] const null_t other) const noexcept {
- return false;
- }
- /**
- * @brief Compares a null object and an identifier of any type.
- * @tparam Entity Type of identifier.
- * @param entity Identifier with which to compare.
- * @return False if the two elements differ, true otherwise.
- */
- template<typename Entity>
- [[nodiscard]] constexpr bool operator==(const Entity entity) const noexcept {
- using traits_type = entt_traits<Entity>;
- return traits_type::to_entity(entity) == traits_type::to_entity(*this);
- }
- /**
- * @brief Compares a null object and an identifier of any type.
- * @tparam Entity Type of identifier.
- * @param entity Identifier with which to compare.
- * @return True if the two elements differ, false otherwise.
- */
- template<typename Entity>
- [[nodiscard]] constexpr bool operator!=(const Entity entity) const noexcept {
- return !(entity == *this);
- }
- };
- /**
- * @brief Compares a null object and an identifier of any type.
- * @tparam Entity Type of identifier.
- * @param lhs Identifier with which to compare.
- * @param rhs A null object yet to be converted.
- * @return False if the two elements differ, true otherwise.
- */
- template<typename Entity>
- [[nodiscard]] constexpr bool operator==(const Entity lhs, const null_t rhs) noexcept {
- return rhs.operator==(lhs);
- }
- /**
- * @brief Compares a null object and an identifier of any type.
- * @tparam Entity Type of identifier.
- * @param lhs Identifier with which to compare.
- * @param rhs A null object yet to be converted.
- * @return True if the two elements differ, false otherwise.
- */
- template<typename Entity>
- [[nodiscard]] constexpr bool operator!=(const Entity lhs, const null_t rhs) noexcept {
- return !(rhs == lhs);
- }
- /*! @brief Tombstone object for all identifiers. */
- struct tombstone_t {
- /**
- * @brief Converts the tombstone object to identifiers of any type.
- * @tparam Entity Type of identifier.
- * @return The tombstone representation for the given type.
- */
- template<typename Entity>
- [[nodiscard]] constexpr operator Entity() const noexcept {
- using traits_type = entt_traits<Entity>;
- constexpr auto value = traits_type::construct(traits_type::entity_mask, traits_type::version_mask);
- return value;
- }
- /**
- * @brief Compares two tombstone objects.
- * @param other A tombstone object.
- * @return True in all cases.
- */
- [[nodiscard]] constexpr bool operator==([[maybe_unused]] const tombstone_t other) const noexcept {
- return true;
- }
- /**
- * @brief Compares two tombstone objects.
- * @param other A tombstone object.
- * @return False in all cases.
- */
- [[nodiscard]] constexpr bool operator!=([[maybe_unused]] const tombstone_t other) const noexcept {
- return false;
- }
- /**
- * @brief Compares a tombstone object and an identifier of any type.
- * @tparam Entity Type of identifier.
- * @param entity Identifier with which to compare.
- * @return False if the two elements differ, true otherwise.
- */
- template<typename Entity>
- [[nodiscard]] constexpr bool operator==(const Entity entity) const noexcept {
- using traits_type = entt_traits<Entity>;
- if constexpr(traits_type::version_mask == 0u) {
- return false;
- } else {
- return (traits_type::to_version(entity) == traits_type::to_version(*this));
- }
- }
- /**
- * @brief Compares a tombstone object and an identifier of any type.
- * @tparam Entity Type of identifier.
- * @param entity Identifier with which to compare.
- * @return True if the two elements differ, false otherwise.
- */
- template<typename Entity>
- [[nodiscard]] constexpr bool operator!=(const Entity entity) const noexcept {
- return !(entity == *this);
- }
- };
- /**
- * @brief Compares a tombstone object and an identifier of any type.
- * @tparam Entity Type of identifier.
- * @param lhs Identifier with which to compare.
- * @param rhs A tombstone object yet to be converted.
- * @return False if the two elements differ, true otherwise.
- */
- template<typename Entity>
- [[nodiscard]] constexpr bool operator==(const Entity lhs, const tombstone_t rhs) noexcept {
- return rhs.operator==(lhs);
- }
- /**
- * @brief Compares a tombstone object and an identifier of any type.
- * @tparam Entity Type of identifier.
- * @param lhs Identifier with which to compare.
- * @param rhs A tombstone object yet to be converted.
- * @return True if the two elements differ, false otherwise.
- */
- template<typename Entity>
- [[nodiscard]] constexpr bool operator!=(const Entity lhs, const tombstone_t rhs) noexcept {
- return !(rhs == lhs);
- }
- /**
- * @brief Compile-time constant for null entities.
- *
- * There exist implicit conversions from this variable to identifiers of any
- * allowed type. Similarly, there exist comparison operators between the null
- * entity and any other identifier.
- */
- inline constexpr null_t null{};
- /**
- * @brief Compile-time constant for tombstone entities.
- *
- * There exist implicit conversions from this variable to identifiers of any
- * allowed type. Similarly, there exist comparison operators between the
- * tombstone entity and any other identifier.
- */
- inline constexpr tombstone_t tombstone{};
- } // namespace entt
- #endif
- // #include "fwd.hpp"
- namespace entt {
- /*! @cond TURN_OFF_DOXYGEN */
- namespace internal {
- template<typename, typename, typename>
- class extended_group_iterator;
- template<typename It, typename... Owned, typename... Get>
- class extended_group_iterator<It, owned_t<Owned...>, get_t<Get...>> {
- template<typename Type>
- [[nodiscard]] auto index_to_element([[maybe_unused]] Type &cpool) const {
- if constexpr(std::is_void_v<typename Type::value_type>) {
- return std::make_tuple();
- } else {
- return std::forward_as_tuple(cpool.rbegin()[it.index()]);
- }
- }
- public:
- using iterator_type = It;
- using value_type = decltype(std::tuple_cat(std::make_tuple(*std::declval<It>()), std::declval<Owned>().get_as_tuple({})..., std::declval<Get>().get_as_tuple({})...));
- using pointer = input_iterator_pointer<value_type>;
- using reference = value_type;
- using difference_type = std::ptrdiff_t;
- using iterator_category = std::input_iterator_tag;
- using iterator_concept = std::forward_iterator_tag;
- constexpr extended_group_iterator()
- : it{},
- pools{} {}
- extended_group_iterator(iterator_type from, std::tuple<Owned *..., Get *...> cpools)
- : it{from},
- pools{std::move(cpools)} {}
- extended_group_iterator &operator++() noexcept {
- return ++it, *this;
- }
- extended_group_iterator operator++(int) noexcept {
- const extended_group_iterator orig = *this;
- return ++(*this), orig;
- }
- [[nodiscard]] reference operator*() const noexcept {
- return std::tuple_cat(std::make_tuple(*it), index_to_element(*std::get<Owned *>(pools))..., std::get<Get *>(pools)->get_as_tuple(*it)...);
- }
- [[nodiscard]] pointer operator->() const noexcept {
- return operator*();
- }
- [[nodiscard]] constexpr iterator_type base() const noexcept {
- return it;
- }
- template<typename... Lhs, typename... Rhs>
- friend constexpr bool operator==(const extended_group_iterator<Lhs...> &, const extended_group_iterator<Rhs...> &) noexcept;
- private:
- It it;
- std::tuple<Owned *..., Get *...> pools;
- };
- template<typename... Lhs, typename... Rhs>
- [[nodiscard]] constexpr bool operator==(const extended_group_iterator<Lhs...> &lhs, const extended_group_iterator<Rhs...> &rhs) noexcept {
- return lhs.it == rhs.it;
- }
- template<typename... Lhs, typename... Rhs>
- [[nodiscard]] constexpr bool operator!=(const extended_group_iterator<Lhs...> &lhs, const extended_group_iterator<Rhs...> &rhs) noexcept {
- return !(lhs == rhs);
- }
- struct group_descriptor {
- using size_type = std::size_t;
- virtual ~group_descriptor() = default;
- [[nodiscard]] virtual bool owned(const id_type) const noexcept {
- return false;
- }
- };
- template<typename Type, std::size_t Owned, std::size_t Get, std::size_t Exclude>
- class group_handler final: public group_descriptor {
- using entity_type = typename Type::entity_type;
- void swap_elements(const std::size_t pos, const entity_type entt) {
- for(size_type next{}; next < Owned; ++next) {
- pools[next]->swap_elements((*pools[next])[pos], entt);
- }
- }
- void push_on_construct(const entity_type entt) {
- if(std::apply([entt, pos = len](auto *cpool, auto *...other) { return cpool->contains(entt) && !(cpool->index(entt) < pos) && (other->contains(entt) && ...); }, pools)
- && std::apply([entt](auto *...cpool) { return (!cpool->contains(entt) && ...); }, filter)) {
- swap_elements(len++, entt);
- }
- }
- void push_on_destroy(const entity_type entt) {
- if(std::apply([entt, pos = len](auto *cpool, auto *...other) { return cpool->contains(entt) && !(cpool->index(entt) < pos) && (other->contains(entt) && ...); }, pools)
- && std::apply([entt](auto *...cpool) { return (0u + ... + cpool->contains(entt)) == 1u; }, filter)) {
- swap_elements(len++, entt);
- }
- }
- void remove_if(const entity_type entt) {
- if(pools[0u]->contains(entt) && (pools[0u]->index(entt) < len)) {
- swap_elements(--len, entt);
- }
- }
- void common_setup() {
- // we cannot iterate backwards because we want to leave behind valid entities in case of owned types
- for(auto first = pools[0u]->rbegin(), last = first + static_cast<typename decltype(pools)::difference_type>(pools[0u]->size()); first != last; ++first) {
- push_on_construct(*first);
- }
- }
- public:
- using common_type = Type;
- using size_type = typename Type::size_type;
- template<typename... OGType, typename... EType>
- group_handler(std::tuple<OGType &...> ogpool, std::tuple<EType &...> epool)
- : pools{std::apply([](auto &&...cpool) { return std::array<common_type *, (Owned + Get)>{&cpool...}; }, ogpool)},
- filter{std::apply([](auto &&...cpool) { return std::array<common_type *, Exclude>{&cpool...}; }, epool)} {
- std::apply([this](auto &...cpool) { ((cpool.on_construct().template connect<&group_handler::push_on_construct>(*this), cpool.on_destroy().template connect<&group_handler::remove_if>(*this)), ...); }, ogpool);
- std::apply([this](auto &...cpool) { ((cpool.on_construct().template connect<&group_handler::remove_if>(*this), cpool.on_destroy().template connect<&group_handler::push_on_destroy>(*this)), ...); }, epool);
- common_setup();
- }
- [[nodiscard]] bool owned(const id_type hash) const noexcept override {
- for(size_type pos{}; pos < Owned; ++pos) {
- if(pools[pos]->info().hash() == hash) {
- return true;
- }
- }
- return false;
- }
- [[nodiscard]] size_type length() const noexcept {
- return len;
- }
- template<std::size_t Index>
- [[nodiscard]] common_type *storage() const noexcept {
- if constexpr(Index < (Owned + Get)) {
- return pools[Index];
- } else {
- return filter[Index - (Owned + Get)];
- }
- }
- private:
- std::array<common_type *, (Owned + Get)> pools;
- std::array<common_type *, Exclude> filter;
- std::size_t len{};
- };
- template<typename Type, std::size_t Get, std::size_t Exclude>
- class group_handler<Type, 0u, Get, Exclude> final: public group_descriptor {
- using entity_type = typename Type::entity_type;
- void push_on_construct(const entity_type entt) {
- if(!elem.contains(entt)
- && std::apply([entt](auto *...cpool) { return (cpool->contains(entt) && ...); }, pools)
- && std::apply([entt](auto *...cpool) { return (!cpool->contains(entt) && ...); }, filter)) {
- elem.push(entt);
- }
- }
- void push_on_destroy(const entity_type entt) {
- if(!elem.contains(entt)
- && std::apply([entt](auto *...cpool) { return (cpool->contains(entt) && ...); }, pools)
- && std::apply([entt](auto *...cpool) { return (0u + ... + cpool->contains(entt)) == 1u; }, filter)) {
- elem.push(entt);
- }
- }
- void remove_if(const entity_type entt) {
- elem.remove(entt);
- }
- void common_setup() {
- for(const auto entity: *pools[0u]) {
- push_on_construct(entity);
- }
- }
- public:
- using common_type = Type;
- template<typename Allocator, typename... GType, typename... EType>
- group_handler(const Allocator &allocator, std::tuple<GType &...> gpool, std::tuple<EType &...> epool)
- : pools{std::apply([](auto &&...cpool) { return std::array<common_type *, Get>{&cpool...}; }, gpool)},
- filter{std::apply([](auto &&...cpool) { return std::array<common_type *, Exclude>{&cpool...}; }, epool)},
- elem{allocator} {
- std::apply([this](auto &...cpool) { ((cpool.on_construct().template connect<&group_handler::push_on_construct>(*this), cpool.on_destroy().template connect<&group_handler::remove_if>(*this)), ...); }, gpool);
- std::apply([this](auto &...cpool) { ((cpool.on_construct().template connect<&group_handler::remove_if>(*this), cpool.on_destroy().template connect<&group_handler::push_on_destroy>(*this)), ...); }, epool);
- common_setup();
- }
- [[nodiscard]] common_type &handle() noexcept {
- return elem;
- }
- [[nodiscard]] const common_type &handle() const noexcept {
- return elem;
- }
- template<std::size_t Index>
- [[nodiscard]] common_type *storage() const noexcept {
- if constexpr(Index < Get) {
- return pools[Index];
- } else {
- return filter[Index - Get];
- }
- }
- private:
- std::array<common_type *, Get> pools;
- std::array<common_type *, Exclude> filter;
- common_type elem;
- };
- } // namespace internal
- /*! @endcond */
- /**
- * @brief Group.
- *
- * Primary template isn't defined on purpose. All the specializations give a
- * compile-time error, but for a few reasonable cases.
- */
- template<typename, typename, typename>
- class basic_group;
- /**
- * @brief Non-owning group.
- *
- * A non-owning group returns all entities and only the entities that are at
- * least in the given storage. Moreover, it's guaranteed that the entity list is
- * tightly packed in memory for fast iterations.
- *
- * @b Important
- *
- * Iterators aren't invalidated if:
- *
- * * New elements are added to the storage.
- * * The entity currently pointed is modified (for example, elements are added
- * or removed from it).
- * * The entity currently pointed is destroyed.
- *
- * In all other cases, modifying the pools iterated by the group in any way
- * invalidates all the iterators.
- *
- * @tparam Get Types of storage _observed_ by the group.
- * @tparam Exclude Types of storage used to filter the group.
- */
- template<typename... Get, typename... Exclude>
- class basic_group<owned_t<>, get_t<Get...>, exclude_t<Exclude...>> {
- using base_type = std::common_type_t<typename Get::base_type..., typename Exclude::base_type...>;
- using underlying_type = typename base_type::entity_type;
- template<typename Type>
- static constexpr std::size_t index_of = type_list_index_v<std::remove_const_t<Type>, type_list<typename Get::element_type..., typename Exclude::element_type...>>;
- template<std::size_t... Index>
- [[nodiscard]] auto pools_for(std::index_sequence<Index...>) const noexcept {
- using return_type = std::tuple<Get *...>;
- return descriptor ? return_type{static_cast<Get *>(descriptor->template storage<Index>())...} : return_type{};
- }
- public:
- /*! @brief Underlying entity identifier. */
- using entity_type = underlying_type;
- /*! @brief Unsigned integer type. */
- using size_type = std::size_t;
- /*! @brief Signed integer type. */
- using difference_type = std::ptrdiff_t;
- /*! @brief Common type among all storage types. */
- using common_type = base_type;
- /*! @brief Random access iterator type. */
- using iterator = typename common_type::iterator;
- /*! @brief Reverse iterator type. */
- using reverse_iterator = typename common_type::reverse_iterator;
- /*! @brief Iterable group type. */
- using iterable = iterable_adaptor<internal::extended_group_iterator<iterator, owned_t<>, get_t<Get...>>>;
- /*! @brief Group handler type. */
- using handler = internal::group_handler<common_type, 0u, sizeof...(Get), sizeof...(Exclude)>;
- /**
- * @brief Group opaque identifier.
- * @return Group opaque identifier.
- */
- static id_type group_id() noexcept {
- return type_hash<basic_group<owned_t<>, get_t<std::remove_const_t<Get>...>, exclude_t<std::remove_const_t<Exclude>...>>>::value();
- }
- /*! @brief Default constructor to use to create empty, invalid groups. */
- basic_group() noexcept
- : descriptor{} {}
- /**
- * @brief Constructs a group from a set of storage classes.
- * @param ref A reference to a group handler.
- */
- basic_group(handler &ref) noexcept
- : descriptor{&ref} {}
- /**
- * @brief Returns the leading storage of a group.
- * @return The leading storage of the group.
- */
- [[nodiscard]] const common_type &handle() const noexcept {
- return descriptor->handle();
- }
- /**
- * @brief Returns the storage for a given element type, if any.
- * @tparam Type Type of element of which to return the storage.
- * @return The storage for the given element type.
- */
- template<typename Type>
- [[nodiscard]] auto *storage() const noexcept {
- return storage<index_of<Type>>();
- }
- /**
- * @brief Returns the storage for a given index, if any.
- * @tparam Index Index of the storage to return.
- * @return The storage for the given index.
- */
- template<std::size_t Index>
- [[nodiscard]] auto *storage() const noexcept {
- using type = type_list_element_t<Index, type_list<Get..., Exclude...>>;
- return *this ? static_cast<type *>(descriptor->template storage<Index>()) : nullptr;
- }
- /**
- * @brief Returns the number of entities that are part of the group.
- * @return Number of entities that are part of the group.
- */
- [[nodiscard]] size_type size() const noexcept {
- return *this ? handle().size() : size_type{};
- }
- /**
- * @brief Returns the number of elements that a group has currently
- * allocated space for.
- * @return Capacity of the group.
- */
- [[nodiscard]] size_type capacity() const noexcept {
- return *this ? handle().capacity() : size_type{};
- }
- /*! @brief Requests the removal of unused capacity. */
- void shrink_to_fit() {
- if(*this) {
- descriptor->handle().shrink_to_fit();
- }
- }
- /**
- * @brief Checks whether a group is empty.
- * @return True if the group is empty, false otherwise.
- */
- [[nodiscard]] bool empty() const noexcept {
- return !*this || handle().empty();
- }
- /**
- * @brief Returns an iterator to the first entity of the group.
- *
- * If the group is empty, the returned iterator will be equal to `end()`.
- *
- * @return An iterator to the first entity of the group.
- */
- [[nodiscard]] iterator begin() const noexcept {
- return *this ? handle().begin() : iterator{};
- }
- /**
- * @brief Returns an iterator that is past the last entity of the group.
- * @return An iterator to the entity following the last entity of the
- * group.
- */
- [[nodiscard]] iterator end() const noexcept {
- return *this ? handle().end() : iterator{};
- }
- /**
- * @brief Returns an iterator to the first entity of the reversed group.
- *
- * If the group is empty, the returned iterator will be equal to `rend()`.
- *
- * @return An iterator to the first entity of the reversed group.
- */
- [[nodiscard]] reverse_iterator rbegin() const noexcept {
- return *this ? handle().rbegin() : reverse_iterator{};
- }
- /**
- * @brief Returns an iterator that is past the last entity of the reversed
- * group.
- * @return An iterator to the entity following the last entity of the
- * reversed group.
- */
- [[nodiscard]] reverse_iterator rend() const noexcept {
- return *this ? handle().rend() : reverse_iterator{};
- }
- /**
- * @brief Returns the first entity of the group, if any.
- * @return The first entity of the group if one exists, the null entity
- * otherwise.
- */
- [[nodiscard]] entity_type front() const noexcept {
- const auto it = begin();
- return it != end() ? *it : null;
- }
- /**
- * @brief Returns the last entity of the group, if any.
- * @return The last entity of the group if one exists, the null entity
- * otherwise.
- */
- [[nodiscard]] entity_type back() const noexcept {
- const auto it = rbegin();
- return it != rend() ? *it : null;
- }
- /**
- * @brief Finds an entity.
- * @param entt A valid identifier.
- * @return An iterator to the given entity if it's found, past the end
- * iterator otherwise.
- */
- [[nodiscard]] iterator find(const entity_type entt) const noexcept {
- return *this ? handle().find(entt) : iterator{};
- }
- /**
- * @brief Returns the identifier that occupies the given position.
- * @param pos Position of the element to return.
- * @return The identifier that occupies the given position.
- */
- [[nodiscard]] entity_type operator[](const size_type pos) const {
- return begin()[static_cast<difference_type>(pos)];
- }
- /**
- * @brief Checks if a group is properly initialized.
- * @return True if the group is properly initialized, false otherwise.
- */
- [[nodiscard]] explicit operator bool() const noexcept {
- return descriptor != nullptr;
- }
- /**
- * @brief Checks if a group contains an entity.
- * @param entt A valid identifier.
- * @return True if the group contains the given entity, false otherwise.
- */
- [[nodiscard]] bool contains(const entity_type entt) const noexcept {
- return *this && handle().contains(entt);
- }
- /**
- * @brief Returns the elements assigned to the given entity.
- * @tparam Type Type of the element to get.
- * @tparam Other Other types of elements to get.
- * @param entt A valid identifier.
- * @return The elements assigned to the entity.
- */
- template<typename Type, typename... Other>
- [[nodiscard]] decltype(auto) get(const entity_type entt) const {
- return get<index_of<Type>, index_of<Other>...>(entt);
- }
- /**
- * @brief Returns the elements assigned to the given entity.
- * @tparam Index Indexes of the elements to get.
- * @param entt A valid identifier.
- * @return The elements assigned to the entity.
- */
- template<std::size_t... Index>
- [[nodiscard]] decltype(auto) get(const entity_type entt) const {
- const auto cpools = pools_for(std::index_sequence_for<Get...>{});
- if constexpr(sizeof...(Index) == 0) {
- return std::apply([entt](auto *...curr) { return std::tuple_cat(curr->get_as_tuple(entt)...); }, cpools);
- } else if constexpr(sizeof...(Index) == 1) {
- return (std::get<Index>(cpools)->get(entt), ...);
- } else {
- return std::tuple_cat(std::get<Index>(cpools)->get_as_tuple(entt)...);
- }
- }
- /**
- * @brief Iterates entities and elements and applies the given function
- * object to them.
- *
- * The function object is invoked for each entity. It is provided with the
- * entity itself and a set of references to non-empty elements. The
- * _constness_ of the elements is as requested.<br/>
- * The signature of the function must be equivalent to one of the following
- * forms:
- *
- * @code{.cpp}
- * void(const entity_type, Type &...);
- * void(Type &...);
- * @endcode
- *
- * @note
- * Empty types aren't explicitly instantiated and therefore they are never
- * returned during iterations.
- *
- * @tparam Func Type of the function object to invoke.
- * @param func A valid function object.
- */
- template<typename Func>
- void each(Func func) const {
- for(const auto entt: *this) {
- if constexpr(is_applicable_v<Func, decltype(std::tuple_cat(std::tuple<entity_type>{}, std::declval<basic_group>().get({})))>) {
- std::apply(func, std::tuple_cat(std::make_tuple(entt), get(entt)));
- } else {
- std::apply(func, get(entt));
- }
- }
- }
- /**
- * @brief Returns an iterable object to use to _visit_ a group.
- *
- * The iterable object returns tuples that contain the current entity and a
- * set of references to its non-empty elements. The _constness_ of the
- * elements is as requested.
- *
- * @note
- * Empty types aren't explicitly instantiated and therefore they are never
- * returned during iterations.
- *
- * @return An iterable object to use to _visit_ the group.
- */
- [[nodiscard]] iterable each() const noexcept {
- const auto cpools = pools_for(std::index_sequence_for<Get...>{});
- return iterable{{begin(), cpools}, {end(), cpools}};
- }
- /**
- * @brief Sort a group according to the given comparison function.
- *
- * The comparison function object must return `true` if the first element
- * is _less_ than the second one, `false` otherwise. The signature of the
- * comparison function should be equivalent to one of the following:
- *
- * @code{.cpp}
- * bool(std::tuple<Type &...>, std::tuple<Type &...>);
- * bool(const Type &..., const Type &...);
- * bool(const Entity, const Entity);
- * @endcode
- *
- * Where `Type` are such that they are iterated by the group.<br/>
- * Moreover, the comparison function object shall induce a
- * _strict weak ordering_ on the values.
- *
- * The sort function object must offer a member function template
- * `operator()` that accepts three arguments:
- *
- * * An iterator to the first element of the range to sort.
- * * An iterator past the last element of the range to sort.
- * * A comparison function to use to compare the elements.
- *
- * @tparam Type Optional type of element to compare.
- * @tparam Other Other optional types of elements to compare.
- * @tparam Compare Type of comparison function object.
- * @tparam Sort Type of sort function object.
- * @tparam Args Types of arguments to forward to the sort function object.
- * @param compare A valid comparison function object.
- * @param algo A valid sort function object.
- * @param args Arguments to forward to the sort function object, if any.
- */
- template<typename Type, typename... Other, typename Compare, typename Sort = std_sort, typename... Args>
- void sort(Compare compare, Sort algo = Sort{}, Args &&...args) {
- sort<index_of<Type>, index_of<Other>...>(std::move(compare), std::move(algo), std::forward<Args>(args)...);
- }
- /**
- * @brief Sort a group according to the given comparison function.
- *
- * @sa sort
- *
- * @tparam Index Optional indexes of elements to compare.
- * @tparam Compare Type of comparison function object.
- * @tparam Sort Type of sort function object.
- * @tparam Args Types of arguments to forward to the sort function object.
- * @param compare A valid comparison function object.
- * @param algo A valid sort function object.
- * @param args Arguments to forward to the sort function object, if any.
- */
- template<std::size_t... Index, typename Compare, typename Sort = std_sort, typename... Args>
- void sort(Compare compare, Sort algo = Sort{}, Args &&...args) {
- if(*this) {
- if constexpr(sizeof...(Index) == 0) {
- static_assert(std::is_invocable_v<Compare, const entity_type, const entity_type>, "Invalid comparison function");
- descriptor->handle().sort(std::move(compare), std::move(algo), std::forward<Args>(args)...);
- } else {
- auto comp = [&compare, cpools = pools_for(std::index_sequence_for<Get...>{})](const entity_type lhs, const entity_type rhs) {
- if constexpr(sizeof...(Index) == 1) {
- return compare((std::get<Index>(cpools)->get(lhs), ...), (std::get<Index>(cpools)->get(rhs), ...));
- } else {
- return compare(std::forward_as_tuple(std::get<Index>(cpools)->get(lhs)...), std::forward_as_tuple(std::get<Index>(cpools)->get(rhs)...));
- }
- };
- descriptor->handle().sort(std::move(comp), std::move(algo), std::forward<Args>(args)...);
- }
- }
- }
- /**
- * @brief Sort entities according to their order in a range.
- *
- * The shared pool of entities and thus its order is affected by the changes
- * to each and every pool that it tracks.
- *
- * @tparam It Type of input iterator.
- * @param first An iterator to the first element of the range of entities.
- * @param last An iterator past the last element of the range of entities.
- */
- template<typename It>
- void sort_as(It first, It last) const {
- if(*this) {
- descriptor->handle().sort_as(first, last);
- }
- }
- private:
- handler *descriptor;
- };
- /**
- * @brief Owning group.
- *
- * Owning groups returns all entities and only the entities that are at
- * least in the given storage. Moreover:
- *
- * * It's guaranteed that the entity list is tightly packed in memory for fast
- * iterations.
- * * It's guaranteed that all elements in the owned storage are tightly packed
- * in memory for even faster iterations and to allow direct access.
- * * They stay true to the order of the owned storage and all instances have the
- * same order in memory.
- *
- * The more types of storage are owned, the faster it is to iterate a group.
- *
- * @b Important
- *
- * Iterators aren't invalidated if:
- *
- * * New elements are added to the storage.
- * * The entity currently pointed is modified (for example, elements are added
- * or removed from it).
- * * The entity currently pointed is destroyed.
- *
- * In all other cases, modifying the pools iterated by the group in any way
- * invalidates all the iterators.
- *
- * @tparam Owned Types of storage _owned_ by the group.
- * @tparam Get Types of storage _observed_ by the group.
- * @tparam Exclude Types of storage used to filter the group.
- */
- template<typename... Owned, typename... Get, typename... Exclude>
- class basic_group<owned_t<Owned...>, get_t<Get...>, exclude_t<Exclude...>> {
- static_assert(((Owned::storage_policy != deletion_policy::in_place) && ...), "Groups do not support in-place delete");
- using base_type = std::common_type_t<typename Owned::base_type..., typename Get::base_type..., typename Exclude::base_type...>;
- using underlying_type = typename base_type::entity_type;
- template<typename Type>
- static constexpr std::size_t index_of = type_list_index_v<std::remove_const_t<Type>, type_list<typename Owned::element_type..., typename Get::element_type..., typename Exclude::element_type...>>;
- template<std::size_t... Index, std::size_t... Other>
- [[nodiscard]] auto pools_for(std::index_sequence<Index...>, std::index_sequence<Other...>) const noexcept {
- using return_type = std::tuple<Owned *..., Get *...>;
- return descriptor ? return_type{static_cast<Owned *>(descriptor->template storage<Index>())..., static_cast<Get *>(descriptor->template storage<sizeof...(Owned) + Other>())...} : return_type{};
- }
- public:
- /*! @brief Underlying entity identifier. */
- using entity_type = underlying_type;
- /*! @brief Unsigned integer type. */
- using size_type = std::size_t;
- /*! @brief Signed integer type. */
- using difference_type = std::ptrdiff_t;
- /*! @brief Common type among all storage types. */
- using common_type = base_type;
- /*! @brief Random access iterator type. */
- using iterator = typename common_type::iterator;
- /*! @brief Reverse iterator type. */
- using reverse_iterator = typename common_type::reverse_iterator;
- /*! @brief Iterable group type. */
- using iterable = iterable_adaptor<internal::extended_group_iterator<iterator, owned_t<Owned...>, get_t<Get...>>>;
- /*! @brief Group handler type. */
- using handler = internal::group_handler<common_type, sizeof...(Owned), sizeof...(Get), sizeof...(Exclude)>;
- /**
- * @brief Group opaque identifier.
- * @return Group opaque identifier.
- */
- static id_type group_id() noexcept {
- return type_hash<basic_group<owned_t<std::remove_const_t<Owned>...>, get_t<std::remove_const_t<Get>...>, exclude_t<std::remove_const_t<Exclude>...>>>::value();
- }
- /*! @brief Default constructor to use to create empty, invalid groups. */
- basic_group() noexcept
- : descriptor{} {}
- /**
- * @brief Constructs a group from a set of storage classes.
- * @param ref A reference to a group handler.
- */
- basic_group(handler &ref) noexcept
- : descriptor{&ref} {}
- /**
- * @brief Returns the leading storage of a group.
- * @return The leading storage of the group.
- */
- [[nodiscard]] const common_type &handle() const noexcept {
- return *storage<0>();
- }
- /**
- * @brief Returns the storage for a given element type, if any.
- * @tparam Type Type of element of which to return the storage.
- * @return The storage for the given element type.
- */
- template<typename Type>
- [[nodiscard]] auto *storage() const noexcept {
- return storage<index_of<Type>>();
- }
- /**
- * @brief Returns the storage for a given index, if any.
- * @tparam Index Index of the storage to return.
- * @return The storage for the given index.
- */
- template<std::size_t Index>
- [[nodiscard]] auto *storage() const noexcept {
- using type = type_list_element_t<Index, type_list<Owned..., Get..., Exclude...>>;
- return *this ? static_cast<type *>(descriptor->template storage<Index>()) : nullptr;
- }
- /**
- * @brief Returns the number of entities that that are part of the group.
- * @return Number of entities that that are part of the group.
- */
- [[nodiscard]] size_type size() const noexcept {
- return *this ? descriptor->length() : size_type{};
- }
- /**
- * @brief Checks whether a group is empty.
- * @return True if the group is empty, false otherwise.
- */
- [[nodiscard]] bool empty() const noexcept {
- return !*this || !descriptor->length();
- }
- /**
- * @brief Returns an iterator to the first entity of the group.
- *
- * If the group is empty, the returned iterator will be equal to `end()`.
- *
- * @return An iterator to the first entity of the group.
- */
- [[nodiscard]] iterator begin() const noexcept {
- return *this ? (handle().end() - static_cast<difference_type>(descriptor->length())) : iterator{};
- }
- /**
- * @brief Returns an iterator that is past the last entity of the group.
- * @return An iterator to the entity following the last entity of the
- * group.
- */
- [[nodiscard]] iterator end() const noexcept {
- return *this ? handle().end() : iterator{};
- }
- /**
- * @brief Returns an iterator to the first entity of the reversed group.
- *
- * If the group is empty, the returned iterator will be equal to `rend()`.
- *
- * @return An iterator to the first entity of the reversed group.
- */
- [[nodiscard]] reverse_iterator rbegin() const noexcept {
- return *this ? handle().rbegin() : reverse_iterator{};
- }
- /**
- * @brief Returns an iterator that is past the last entity of the reversed
- * group.
- * @return An iterator to the entity following the last entity of the
- * reversed group.
- */
- [[nodiscard]] reverse_iterator rend() const noexcept {
- return *this ? (handle().rbegin() + static_cast<difference_type>(descriptor->length())) : reverse_iterator{};
- }
- /**
- * @brief Returns the first entity of the group, if any.
- * @return The first entity of the group if one exists, the null entity
- * otherwise.
- */
- [[nodiscard]] entity_type front() const noexcept {
- const auto it = begin();
- return it != end() ? *it : null;
- }
- /**
- * @brief Returns the last entity of the group, if any.
- * @return The last entity of the group if one exists, the null entity
- * otherwise.
- */
- [[nodiscard]] entity_type back() const noexcept {
- const auto it = rbegin();
- return it != rend() ? *it : null;
- }
- /**
- * @brief Finds an entity.
- * @param entt A valid identifier.
- * @return An iterator to the given entity if it's found, past the end
- * iterator otherwise.
- */
- [[nodiscard]] iterator find(const entity_type entt) const noexcept {
- const auto it = *this ? handle().find(entt) : iterator{};
- return it >= begin() ? it : iterator{};
- }
- /**
- * @brief Returns the identifier that occupies the given position.
- * @param pos Position of the element to return.
- * @return The identifier that occupies the given position.
- */
- [[nodiscard]] entity_type operator[](const size_type pos) const {
- return begin()[static_cast<difference_type>(pos)];
- }
- /**
- * @brief Checks if a group is properly initialized.
- * @return True if the group is properly initialized, false otherwise.
- */
- [[nodiscard]] explicit operator bool() const noexcept {
- return descriptor != nullptr;
- }
- /**
- * @brief Checks if a group contains an entity.
- * @param entt A valid identifier.
- * @return True if the group contains the given entity, false otherwise.
- */
- [[nodiscard]] bool contains(const entity_type entt) const noexcept {
- return *this && handle().contains(entt) && (handle().index(entt) < (descriptor->length()));
- }
- /**
- * @brief Returns the elements assigned to the given entity.
- * @tparam Type Type of the element to get.
- * @tparam Other Other types of elements to get.
- * @param entt A valid identifier.
- * @return The elements assigned to the entity.
- */
- template<typename Type, typename... Other>
- [[nodiscard]] decltype(auto) get(const entity_type entt) const {
- return get<index_of<Type>, index_of<Other>...>(entt);
- }
- /**
- * @brief Returns the elements assigned to the given entity.
- * @tparam Index Indexes of the elements to get.
- * @param entt A valid identifier.
- * @return The elements assigned to the entity.
- */
- template<std::size_t... Index>
- [[nodiscard]] decltype(auto) get(const entity_type entt) const {
- const auto cpools = pools_for(std::index_sequence_for<Owned...>{}, std::index_sequence_for<Get...>{});
- if constexpr(sizeof...(Index) == 0) {
- return std::apply([entt](auto *...curr) { return std::tuple_cat(curr->get_as_tuple(entt)...); }, cpools);
- } else if constexpr(sizeof...(Index) == 1) {
- return (std::get<Index>(cpools)->get(entt), ...);
- } else {
- return std::tuple_cat(std::get<Index>(cpools)->get_as_tuple(entt)...);
- }
- }
- /**
- * @brief Iterates entities and elements and applies the given function
- * object to them.
- *
- * The function object is invoked for each entity. It is provided with the
- * entity itself and a set of references to non-empty elements. The
- * _constness_ of the elements is as requested.<br/>
- * The signature of the function must be equivalent to one of the following
- * forms:
- *
- * @code{.cpp}
- * void(const entity_type, Type &...);
- * void(Type &...);
- * @endcode
- *
- * @note
- * Empty types aren't explicitly instantiated and therefore they are never
- * returned during iterations.
- *
- * @tparam Func Type of the function object to invoke.
- * @param func A valid function object.
- */
- template<typename Func>
- void each(Func func) const {
- for(auto args: each()) {
- if constexpr(is_applicable_v<Func, decltype(std::tuple_cat(std::tuple<entity_type>{}, std::declval<basic_group>().get({})))>) {
- std::apply(func, args);
- } else {
- std::apply([&func](auto, auto &&...less) { func(std::forward<decltype(less)>(less)...); }, args);
- }
- }
- }
- /**
- * @brief Returns an iterable object to use to _visit_ a group.
- *
- * The iterable object returns tuples that contain the current entity and a
- * set of references to its non-empty elements. The _constness_ of the
- * elements is as requested.
- *
- * @note
- * Empty types aren't explicitly instantiated and therefore they are never
- * returned during iterations.
- *
- * @return An iterable object to use to _visit_ the group.
- */
- [[nodiscard]] iterable each() const noexcept {
- const auto cpools = pools_for(std::index_sequence_for<Owned...>{}, std::index_sequence_for<Get...>{});
- return iterable{{begin(), cpools}, {end(), cpools}};
- }
- /**
- * @brief Sort a group according to the given comparison function.
- *
- * The comparison function object must return `true` if the first element
- * is _less_ than the second one, `false` otherwise. The signature of the
- * comparison function should be equivalent to one of the following:
- *
- * @code{.cpp}
- * bool(std::tuple<Type &...>, std::tuple<Type &...>);
- * bool(const Type &, const Type &);
- * bool(const Entity, const Entity);
- * @endcode
- *
- * Where `Type` are either owned types or not but still such that they are
- * iterated by the group.<br/>
- * Moreover, the comparison function object shall induce a
- * _strict weak ordering_ on the values.
- *
- * The sort function object must offer a member function template
- * `operator()` that accepts three arguments:
- *
- * * An iterator to the first element of the range to sort.
- * * An iterator past the last element of the range to sort.
- * * A comparison function to use to compare the elements.
- *
- * @tparam Type Optional type of element to compare.
- * @tparam Other Other optional types of elements to compare.
- * @tparam Compare Type of comparison function object.
- * @tparam Sort Type of sort function object.
- * @tparam Args Types of arguments to forward to the sort function object.
- * @param compare A valid comparison function object.
- * @param algo A valid sort function object.
- * @param args Arguments to forward to the sort function object, if any.
- */
- template<typename Type, typename... Other, typename Compare, typename Sort = std_sort, typename... Args>
- void sort(Compare compare, Sort algo = Sort{}, Args &&...args) const {
- sort<index_of<Type>, index_of<Other>...>(std::move(compare), std::move(algo), std::forward<Args>(args)...);
- }
- /**
- * @brief Sort a group according to the given comparison function.
- *
- * @sa sort
- *
- * @tparam Index Optional indexes of elements to compare.
- * @tparam Compare Type of comparison function object.
- * @tparam Sort Type of sort function object.
- * @tparam Args Types of arguments to forward to the sort function object.
- * @param compare A valid comparison function object.
- * @param algo A valid sort function object.
- * @param args Arguments to forward to the sort function object, if any.
- */
- template<std::size_t... Index, typename Compare, typename Sort = std_sort, typename... Args>
- void sort(Compare compare, Sort algo = Sort{}, Args &&...args) const {
- const auto cpools = pools_for(std::index_sequence_for<Owned...>{}, std::index_sequence_for<Get...>{});
- if constexpr(sizeof...(Index) == 0) {
- static_assert(std::is_invocable_v<Compare, const entity_type, const entity_type>, "Invalid comparison function");
- storage<0>()->sort_n(descriptor->length(), std::move(compare), std::move(algo), std::forward<Args>(args)...);
- } else {
- auto comp = [&compare, &cpools](const entity_type lhs, const entity_type rhs) {
- if constexpr(sizeof...(Index) == 1) {
- return compare((std::get<Index>(cpools)->get(lhs), ...), (std::get<Index>(cpools)->get(rhs), ...));
- } else {
- return compare(std::forward_as_tuple(std::get<Index>(cpools)->get(lhs)...), std::forward_as_tuple(std::get<Index>(cpools)->get(rhs)...));
- }
- };
- storage<0>()->sort_n(descriptor->length(), std::move(comp), std::move(algo), std::forward<Args>(args)...);
- }
- auto cb = [this](auto *head, auto *...other) {
- for(auto next = descriptor->length(); next; --next) {
- const auto pos = next - 1;
- [[maybe_unused]] const auto entt = head->data()[pos];
- (other->swap_elements(other->data()[pos], entt), ...);
- }
- };
- std::apply(cb, cpools);
- }
- private:
- handler *descriptor;
- };
- } // namespace entt
- #endif
- // #include "entity/handle.hpp"
- #ifndef ENTT_ENTITY_HANDLE_HPP
- #define ENTT_ENTITY_HANDLE_HPP
- #include <iterator>
- #include <tuple>
- #include <type_traits>
- #include <utility>
- // #include "../config/config.h"
- // #include "../core/iterator.hpp"
- // #include "../core/type_traits.hpp"
- // #include "entity.hpp"
- // #include "fwd.hpp"
- namespace entt {
- /*! @cond TURN_OFF_DOXYGEN */
- namespace internal {
- template<typename It>
- class handle_storage_iterator final {
- template<typename Other>
- friend class handle_storage_iterator;
- using underlying_type = std::remove_reference_t<typename It::value_type::second_type>;
- using entity_type = typename underlying_type::entity_type;
- public:
- using value_type = typename std::iterator_traits<It>::value_type;
- using pointer = input_iterator_pointer<value_type>;
- using reference = value_type;
- using difference_type = std::ptrdiff_t;
- using iterator_category = std::input_iterator_tag;
- using iterator_concept = std::forward_iterator_tag;
- constexpr handle_storage_iterator() noexcept
- : entt{null},
- it{},
- last{} {}
- constexpr handle_storage_iterator(entity_type value, It from, It to) noexcept
- : entt{value},
- it{from},
- last{to} {
- while(it != last && !it->second.contains(entt)) {
- ++it;
- }
- }
- constexpr handle_storage_iterator &operator++() noexcept {
- for(++it; it != last && !it->second.contains(entt); ++it) {}
- return *this;
- }
- constexpr handle_storage_iterator operator++(int) noexcept {
- const handle_storage_iterator orig = *this;
- return ++(*this), orig;
- }
- [[nodiscard]] constexpr reference operator*() const noexcept {
- return *it;
- }
- [[nodiscard]] constexpr pointer operator->() const noexcept {
- return operator*();
- }
- template<typename ILhs, typename IRhs>
- friend constexpr bool operator==(const handle_storage_iterator<ILhs> &, const handle_storage_iterator<IRhs> &) noexcept;
- private:
- entity_type entt;
- It it;
- It last;
- };
- template<typename ILhs, typename IRhs>
- [[nodiscard]] constexpr bool operator==(const handle_storage_iterator<ILhs> &lhs, const handle_storage_iterator<IRhs> &rhs) noexcept {
- return lhs.it == rhs.it;
- }
- template<typename ILhs, typename IRhs>
- [[nodiscard]] constexpr bool operator!=(const handle_storage_iterator<ILhs> &lhs, const handle_storage_iterator<IRhs> &rhs) noexcept {
- return !(lhs == rhs);
- }
- } // namespace internal
- /*! @endcond */
- /**
- * @brief Non-owning handle to an entity.
- *
- * Tiny wrapper around a registry and an entity.
- *
- * @tparam Registry Basic registry type.
- * @tparam Scope Types to which to restrict the scope of a handle.
- */
- template<typename Registry, typename... Scope>
- class basic_handle {
- using traits_type = entt_traits<typename Registry::entity_type>;
- [[nodiscard]] auto &owner_or_assert() const noexcept {
- ENTT_ASSERT(owner != nullptr, "Invalid pointer to registry");
- return static_cast<Registry &>(*owner);
- }
- public:
- /*! @brief Type of registry accepted by the handle. */
- using registry_type = Registry;
- /*! @brief Underlying entity identifier. */
- using entity_type = typename traits_type::value_type;
- /*! @brief Underlying version type. */
- using version_type = typename traits_type::version_type;
- /*! @brief Unsigned integer type. */
- using size_type = std::size_t;
- /*! @brief Iterable handle type. */
- using iterable = iterable_adaptor<internal::handle_storage_iterator<typename decltype(std::declval<registry_type>().storage())::iterator>>;
- /*! @brief Constructs an invalid handle. */
- basic_handle() noexcept
- : owner{},
- entt{null} {}
- /**
- * @brief Constructs a handle from a given registry and entity.
- * @param ref An instance of the registry class.
- * @param value A valid identifier.
- */
- basic_handle(registry_type &ref, entity_type value) noexcept
- : owner{&ref},
- entt{value} {}
- /**
- * @brief Returns an iterable object to use to _visit_ a handle.
- *
- * The iterable object returns a pair that contains the name and a reference
- * to the current storage.<br/>
- * Returned storage are those that contain the entity associated with the
- * handle.
- *
- * @return An iterable object to use to _visit_ the handle.
- */
- [[nodiscard]] iterable storage() const noexcept {
- auto underlying = owner_or_assert().storage();
- return iterable{{entt, underlying.begin(), underlying.end()}, {entt, underlying.end(), underlying.end()}};
- }
- /*! @copydoc valid */
- [[nodiscard]] explicit operator bool() const noexcept {
- return owner && owner->valid(entt);
- }
- /**
- * @brief Checks if a handle refers to a valid registry and entity.
- * @return True if the handle refers to a valid registry and entity, false
- * otherwise.
- */
- [[nodiscard]] bool valid() const {
- return static_cast<bool>(*this);
- }
- /**
- * @brief Returns a pointer to the underlying registry, if any.
- * @return A pointer to the underlying registry, if any.
- */
- [[nodiscard]] registry_type *registry() const noexcept {
- return owner;
- }
- /**
- * @brief Returns the entity associated with a handle.
- * @return The entity associated with the handle.
- */
- [[nodiscard]] entity_type entity() const noexcept {
- return entt;
- }
- /*! @copydoc entity */
- [[nodiscard]] operator entity_type() const noexcept {
- return entity();
- }
- /*! @brief Destroys the entity associated with a handle. */
- void destroy() {
- owner_or_assert().destroy(std::exchange(entt, null));
- }
- /**
- * @brief Destroys the entity associated with a handle.
- * @param version A desired version upon destruction.
- */
- void destroy(const version_type version) {
- owner_or_assert().destroy(std::exchange(entt, null), version);
- }
- /**
- * @brief Assigns the given element to a handle.
- * @tparam Type Type of element to create.
- * @tparam Args Types of arguments to use to construct the element.
- * @param args Parameters to use to initialize the element.
- * @return A reference to the newly created element.
- */
- template<typename Type, typename... Args>
- // NOLINTNEXTLINE(modernize-use-nodiscard)
- decltype(auto) emplace(Args &&...args) const {
- static_assert(((sizeof...(Scope) == 0) || ... || std::is_same_v<Type, Scope>), "Invalid type");
- return owner_or_assert().template emplace<Type>(entt, std::forward<Args>(args)...);
- }
- /**
- * @brief Assigns or replaces the given element for a handle.
- * @tparam Type Type of element to assign or replace.
- * @tparam Args Types of arguments to use to construct the element.
- * @param args Parameters to use to initialize the element.
- * @return A reference to the newly created element.
- */
- template<typename Type, typename... Args>
- decltype(auto) emplace_or_replace(Args &&...args) const {
- static_assert(((sizeof...(Scope) == 0) || ... || std::is_same_v<Type, Scope>), "Invalid type");
- return owner_or_assert().template emplace_or_replace<Type>(entt, std::forward<Args>(args)...);
- }
- /**
- * @brief Patches the given element for a handle.
- * @tparam Type Type of element to patch.
- * @tparam Func Types of the function objects to invoke.
- * @param func Valid function objects.
- * @return A reference to the patched element.
- */
- template<typename Type, typename... Func>
- decltype(auto) patch(Func &&...func) const {
- static_assert(((sizeof...(Scope) == 0) || ... || std::is_same_v<Type, Scope>), "Invalid type");
- return owner_or_assert().template patch<Type>(entt, std::forward<Func>(func)...);
- }
- /**
- * @brief Replaces the given element for a handle.
- * @tparam Type Type of element to replace.
- * @tparam Args Types of arguments to use to construct the element.
- * @param args Parameters to use to initialize the element.
- * @return A reference to the element being replaced.
- */
- template<typename Type, typename... Args>
- decltype(auto) replace(Args &&...args) const {
- static_assert(((sizeof...(Scope) == 0) || ... || std::is_same_v<Type, Scope>), "Invalid type");
- return owner_or_assert().template replace<Type>(entt, std::forward<Args>(args)...);
- }
- /**
- * @brief Removes the given elements from a handle.
- * @tparam Type Types of elements to remove.
- * @return The number of elements actually removed.
- */
- template<typename... Type>
- // NOLINTNEXTLINE(modernize-use-nodiscard)
- size_type remove() const {
- static_assert(sizeof...(Scope) == 0 || (type_list_contains_v<type_list<Scope...>, Type> && ...), "Invalid type");
- return owner_or_assert().template remove<Type...>(entt);
- }
- /**
- * @brief Erases the given elements from a handle.
- * @tparam Type Types of elements to erase.
- */
- template<typename... Type>
- void erase() const {
- static_assert(sizeof...(Scope) == 0 || (type_list_contains_v<type_list<Scope...>, Type> && ...), "Invalid type");
- owner_or_assert().template erase<Type...>(entt);
- }
- /**
- * @brief Checks if a handle has all the given elements.
- * @tparam Type Elements for which to perform the check.
- * @return True if the handle has all the elements, false otherwise.
- */
- template<typename... Type>
- [[nodiscard]] decltype(auto) all_of() const {
- return owner_or_assert().template all_of<Type...>(entt);
- }
- /**
- * @brief Checks if a handle has at least one of the given elements.
- * @tparam Type Elements for which to perform the check.
- * @return True if the handle has at least one of the given elements,
- * false otherwise.
- */
- template<typename... Type>
- [[nodiscard]] decltype(auto) any_of() const {
- return owner_or_assert().template any_of<Type...>(entt);
- }
- /**
- * @brief Returns references to the given elements for a handle.
- * @tparam Type Types of elements to get.
- * @return References to the elements owned by the handle.
- */
- template<typename... Type>
- [[nodiscard]] decltype(auto) get() const {
- static_assert(sizeof...(Scope) == 0 || (type_list_contains_v<type_list<Scope...>, Type> && ...), "Invalid type");
- return owner_or_assert().template get<Type...>(entt);
- }
- /**
- * @brief Returns a reference to the given element for a handle.
- * @tparam Type Type of element to get.
- * @tparam Args Types of arguments to use to construct the element.
- * @param args Parameters to use to initialize the element.
- * @return Reference to the element owned by the handle.
- */
- template<typename Type, typename... Args>
- [[nodiscard]] decltype(auto) get_or_emplace(Args &&...args) const {
- static_assert(((sizeof...(Scope) == 0) || ... || std::is_same_v<Type, Scope>), "Invalid type");
- return owner_or_assert().template get_or_emplace<Type>(entt, std::forward<Args>(args)...);
- }
- /**
- * @brief Returns pointers to the given elements for a handle.
- * @tparam Type Types of elements to get.
- * @return Pointers to the elements owned by the handle.
- */
- template<typename... Type>
- [[nodiscard]] auto try_get() const {
- static_assert(sizeof...(Scope) == 0 || (type_list_contains_v<type_list<Scope...>, Type> && ...), "Invalid type");
- return owner_or_assert().template try_get<Type...>(entt);
- }
- /**
- * @brief Checks if a handle has elements assigned.
- * @return True if the handle has no elements assigned, false otherwise.
- */
- [[nodiscard]] bool orphan() const {
- return owner_or_assert().orphan(entt);
- }
- /**
- * @brief Returns a const handle from a non-const one.
- * @tparam Other A valid entity type.
- * @tparam Args Scope of the handle to construct.
- * @return A const handle referring to the same registry and the same
- * entity.
- */
- template<typename Other, typename... Args>
- operator basic_handle<Other, Args...>() const noexcept {
- static_assert(std::is_same_v<Other, Registry> || std::is_same_v<std::remove_const_t<Other>, Registry>, "Invalid conversion between different handles");
- static_assert((sizeof...(Scope) == 0 || ((sizeof...(Args) != 0 && sizeof...(Args) <= sizeof...(Scope)) && ... && (type_list_contains_v<type_list<Scope...>, Args>))), "Invalid conversion between different handles");
- return owner ? basic_handle<Other, Args...>{*owner, entt} : basic_handle<Other, Args...>{};
- }
- private:
- registry_type *owner;
- entity_type entt;
- };
- /**
- * @brief Compares two handles.
- * @tparam Args Scope of the first handle.
- * @tparam Other Scope of the second handle.
- * @param lhs A valid handle.
- * @param rhs A valid handle.
- * @return True if both handles refer to the same registry and the same
- * entity, false otherwise.
- */
- template<typename... Args, typename... Other>
- [[nodiscard]] bool operator==(const basic_handle<Args...> &lhs, const basic_handle<Other...> &rhs) noexcept {
- return lhs.registry() == rhs.registry() && lhs.entity() == rhs.entity();
- }
- /**
- * @brief Compares two handles.
- * @tparam Args Scope of the first handle.
- * @tparam Other Scope of the second handle.
- * @param lhs A valid handle.
- * @param rhs A valid handle.
- * @return False if both handles refer to the same registry and the same
- * entity, true otherwise.
- */
- template<typename... Args, typename... Other>
- [[nodiscard]] bool operator!=(const basic_handle<Args...> &lhs, const basic_handle<Other...> &rhs) noexcept {
- return !(lhs == rhs);
- }
- /**
- * @brief Compares a handle with the null object.
- * @tparam Args Scope of the handle.
- * @param lhs A valid handle.
- * @param rhs A null object yet to be converted.
- * @return False if the two elements differ, true otherwise.
- */
- template<typename... Args>
- [[nodiscard]] constexpr bool operator==(const basic_handle<Args...> &lhs, const null_t rhs) noexcept {
- return (lhs.entity() == rhs);
- }
- /**
- * @brief Compares a handle with the null object.
- * @tparam Args Scope of the handle.
- * @param lhs A null object yet to be converted.
- * @param rhs A valid handle.
- * @return False if the two elements differ, true otherwise.
- */
- template<typename... Args>
- [[nodiscard]] constexpr bool operator==(const null_t lhs, const basic_handle<Args...> &rhs) noexcept {
- return (rhs == lhs);
- }
- /**
- * @brief Compares a handle with the null object.
- * @tparam Args Scope of the handle.
- * @param lhs A valid handle.
- * @param rhs A null object yet to be converted.
- * @return True if the two elements differ, false otherwise.
- */
- template<typename... Args>
- [[nodiscard]] constexpr bool operator!=(const basic_handle<Args...> &lhs, const null_t rhs) noexcept {
- return (lhs.entity() != rhs);
- }
- /**
- * @brief Compares a handle with the null object.
- * @tparam Args Scope of the handle.
- * @param lhs A null object yet to be converted.
- * @param rhs A valid handle.
- * @return True if the two elements differ, false otherwise.
- */
- template<typename... Args>
- [[nodiscard]] constexpr bool operator!=(const null_t lhs, const basic_handle<Args...> &rhs) noexcept {
- return (rhs != lhs);
- }
- } // namespace entt
- #endif
- // #include "entity/helper.hpp"
- #ifndef ENTT_ENTITY_HELPER_HPP
- #define ENTT_ENTITY_HELPER_HPP
- #include <memory>
- #include <type_traits>
- #include <utility>
- // #include "../core/fwd.hpp"
- // #include "../core/type_traits.hpp"
- // #include "component.hpp"
- #ifndef ENTT_ENTITY_COMPONENT_HPP
- #define ENTT_ENTITY_COMPONENT_HPP
- #include <cstddef>
- #include <type_traits>
- // #include "../config/config.h"
- // #include "fwd.hpp"
- namespace entt {
- /*! @cond TURN_OFF_DOXYGEN */
- namespace internal {
- template<typename Type, typename = void>
- struct in_place_delete: std::bool_constant<!(std::is_move_constructible_v<Type> && std::is_move_assignable_v<Type>)> {};
- template<>
- struct in_place_delete<void>: std::false_type {};
- template<typename Type>
- struct in_place_delete<Type, std::enable_if_t<Type::in_place_delete>>
- : std::true_type {};
- template<typename Type, typename = void>
- struct page_size: std::integral_constant<std::size_t, !std::is_empty_v<ENTT_ETO_TYPE(Type)> * ENTT_PACKED_PAGE> {};
- template<>
- struct page_size<void>: std::integral_constant<std::size_t, 0u> {};
- template<typename Type>
- struct page_size<Type, std::void_t<decltype(Type::page_size)>>
- : std::integral_constant<std::size_t, Type::page_size> {};
- } // namespace internal
- /*! @endcond */
- /**
- * @brief Common way to access various properties of components.
- * @tparam Type Element type.
- * @tparam Entity A valid entity type.
- */
- template<typename Type, typename Entity, typename>
- struct component_traits {
- static_assert(std::is_same_v<std::decay_t<Type>, Type>, "Unsupported type");
- /*! @brief Element type. */
- using element_type = Type;
- /*! @brief Underlying entity identifier. */
- using entity_type = Entity;
- /*! @brief Pointer stability, default is `false`. */
- static constexpr bool in_place_delete = internal::in_place_delete<Type>::value;
- /*! @brief Page size, default is `ENTT_PACKED_PAGE` for non-empty types. */
- static constexpr std::size_t page_size = internal::page_size<Type>::value;
- };
- } // namespace entt
- #endif
- // #include "fwd.hpp"
- // #include "group.hpp"
- #ifndef ENTT_ENTITY_GROUP_HPP
- #define ENTT_ENTITY_GROUP_HPP
- #include <array>
- #include <cstddef>
- #include <iterator>
- #include <tuple>
- #include <type_traits>
- #include <utility>
- // #include "../config/config.h"
- // #include "../core/algorithm.hpp"
- // #include "../core/fwd.hpp"
- // #include "../core/iterator.hpp"
- // #include "../core/type_info.hpp"
- // #include "../core/type_traits.hpp"
- // #include "entity.hpp"
- // #include "fwd.hpp"
- namespace entt {
- /*! @cond TURN_OFF_DOXYGEN */
- namespace internal {
- template<typename, typename, typename>
- class extended_group_iterator;
- template<typename It, typename... Owned, typename... Get>
- class extended_group_iterator<It, owned_t<Owned...>, get_t<Get...>> {
- template<typename Type>
- [[nodiscard]] auto index_to_element([[maybe_unused]] Type &cpool) const {
- if constexpr(std::is_void_v<typename Type::value_type>) {
- return std::make_tuple();
- } else {
- return std::forward_as_tuple(cpool.rbegin()[it.index()]);
- }
- }
- public:
- using iterator_type = It;
- using value_type = decltype(std::tuple_cat(std::make_tuple(*std::declval<It>()), std::declval<Owned>().get_as_tuple({})..., std::declval<Get>().get_as_tuple({})...));
- using pointer = input_iterator_pointer<value_type>;
- using reference = value_type;
- using difference_type = std::ptrdiff_t;
- using iterator_category = std::input_iterator_tag;
- using iterator_concept = std::forward_iterator_tag;
- constexpr extended_group_iterator()
- : it{},
- pools{} {}
- extended_group_iterator(iterator_type from, std::tuple<Owned *..., Get *...> cpools)
- : it{from},
- pools{std::move(cpools)} {}
- extended_group_iterator &operator++() noexcept {
- return ++it, *this;
- }
- extended_group_iterator operator++(int) noexcept {
- const extended_group_iterator orig = *this;
- return ++(*this), orig;
- }
- [[nodiscard]] reference operator*() const noexcept {
- return std::tuple_cat(std::make_tuple(*it), index_to_element(*std::get<Owned *>(pools))..., std::get<Get *>(pools)->get_as_tuple(*it)...);
- }
- [[nodiscard]] pointer operator->() const noexcept {
- return operator*();
- }
- [[nodiscard]] constexpr iterator_type base() const noexcept {
- return it;
- }
- template<typename... Lhs, typename... Rhs>
- friend constexpr bool operator==(const extended_group_iterator<Lhs...> &, const extended_group_iterator<Rhs...> &) noexcept;
- private:
- It it;
- std::tuple<Owned *..., Get *...> pools;
- };
- template<typename... Lhs, typename... Rhs>
- [[nodiscard]] constexpr bool operator==(const extended_group_iterator<Lhs...> &lhs, const extended_group_iterator<Rhs...> &rhs) noexcept {
- return lhs.it == rhs.it;
- }
- template<typename... Lhs, typename... Rhs>
- [[nodiscard]] constexpr bool operator!=(const extended_group_iterator<Lhs...> &lhs, const extended_group_iterator<Rhs...> &rhs) noexcept {
- return !(lhs == rhs);
- }
- struct group_descriptor {
- using size_type = std::size_t;
- virtual ~group_descriptor() = default;
- [[nodiscard]] virtual bool owned(const id_type) const noexcept {
- return false;
- }
- };
- template<typename Type, std::size_t Owned, std::size_t Get, std::size_t Exclude>
- class group_handler final: public group_descriptor {
- using entity_type = typename Type::entity_type;
- void swap_elements(const std::size_t pos, const entity_type entt) {
- for(size_type next{}; next < Owned; ++next) {
- pools[next]->swap_elements((*pools[next])[pos], entt);
- }
- }
- void push_on_construct(const entity_type entt) {
- if(std::apply([entt, pos = len](auto *cpool, auto *...other) { return cpool->contains(entt) && !(cpool->index(entt) < pos) && (other->contains(entt) && ...); }, pools)
- && std::apply([entt](auto *...cpool) { return (!cpool->contains(entt) && ...); }, filter)) {
- swap_elements(len++, entt);
- }
- }
- void push_on_destroy(const entity_type entt) {
- if(std::apply([entt, pos = len](auto *cpool, auto *...other) { return cpool->contains(entt) && !(cpool->index(entt) < pos) && (other->contains(entt) && ...); }, pools)
- && std::apply([entt](auto *...cpool) { return (0u + ... + cpool->contains(entt)) == 1u; }, filter)) {
- swap_elements(len++, entt);
- }
- }
- void remove_if(const entity_type entt) {
- if(pools[0u]->contains(entt) && (pools[0u]->index(entt) < len)) {
- swap_elements(--len, entt);
- }
- }
- void common_setup() {
- // we cannot iterate backwards because we want to leave behind valid entities in case of owned types
- for(auto first = pools[0u]->rbegin(), last = first + static_cast<typename decltype(pools)::difference_type>(pools[0u]->size()); first != last; ++first) {
- push_on_construct(*first);
- }
- }
- public:
- using common_type = Type;
- using size_type = typename Type::size_type;
- template<typename... OGType, typename... EType>
- group_handler(std::tuple<OGType &...> ogpool, std::tuple<EType &...> epool)
- : pools{std::apply([](auto &&...cpool) { return std::array<common_type *, (Owned + Get)>{&cpool...}; }, ogpool)},
- filter{std::apply([](auto &&...cpool) { return std::array<common_type *, Exclude>{&cpool...}; }, epool)} {
- std::apply([this](auto &...cpool) { ((cpool.on_construct().template connect<&group_handler::push_on_construct>(*this), cpool.on_destroy().template connect<&group_handler::remove_if>(*this)), ...); }, ogpool);
- std::apply([this](auto &...cpool) { ((cpool.on_construct().template connect<&group_handler::remove_if>(*this), cpool.on_destroy().template connect<&group_handler::push_on_destroy>(*this)), ...); }, epool);
- common_setup();
- }
- [[nodiscard]] bool owned(const id_type hash) const noexcept override {
- for(size_type pos{}; pos < Owned; ++pos) {
- if(pools[pos]->info().hash() == hash) {
- return true;
- }
- }
- return false;
- }
- [[nodiscard]] size_type length() const noexcept {
- return len;
- }
- template<std::size_t Index>
- [[nodiscard]] common_type *storage() const noexcept {
- if constexpr(Index < (Owned + Get)) {
- return pools[Index];
- } else {
- return filter[Index - (Owned + Get)];
- }
- }
- private:
- std::array<common_type *, (Owned + Get)> pools;
- std::array<common_type *, Exclude> filter;
- std::size_t len{};
- };
- template<typename Type, std::size_t Get, std::size_t Exclude>
- class group_handler<Type, 0u, Get, Exclude> final: public group_descriptor {
- using entity_type = typename Type::entity_type;
- void push_on_construct(const entity_type entt) {
- if(!elem.contains(entt)
- && std::apply([entt](auto *...cpool) { return (cpool->contains(entt) && ...); }, pools)
- && std::apply([entt](auto *...cpool) { return (!cpool->contains(entt) && ...); }, filter)) {
- elem.push(entt);
- }
- }
- void push_on_destroy(const entity_type entt) {
- if(!elem.contains(entt)
- && std::apply([entt](auto *...cpool) { return (cpool->contains(entt) && ...); }, pools)
- && std::apply([entt](auto *...cpool) { return (0u + ... + cpool->contains(entt)) == 1u; }, filter)) {
- elem.push(entt);
- }
- }
- void remove_if(const entity_type entt) {
- elem.remove(entt);
- }
- void common_setup() {
- for(const auto entity: *pools[0u]) {
- push_on_construct(entity);
- }
- }
- public:
- using common_type = Type;
- template<typename Allocator, typename... GType, typename... EType>
- group_handler(const Allocator &allocator, std::tuple<GType &...> gpool, std::tuple<EType &...> epool)
- : pools{std::apply([](auto &&...cpool) { return std::array<common_type *, Get>{&cpool...}; }, gpool)},
- filter{std::apply([](auto &&...cpool) { return std::array<common_type *, Exclude>{&cpool...}; }, epool)},
- elem{allocator} {
- std::apply([this](auto &...cpool) { ((cpool.on_construct().template connect<&group_handler::push_on_construct>(*this), cpool.on_destroy().template connect<&group_handler::remove_if>(*this)), ...); }, gpool);
- std::apply([this](auto &...cpool) { ((cpool.on_construct().template connect<&group_handler::remove_if>(*this), cpool.on_destroy().template connect<&group_handler::push_on_destroy>(*this)), ...); }, epool);
- common_setup();
- }
- [[nodiscard]] common_type &handle() noexcept {
- return elem;
- }
- [[nodiscard]] const common_type &handle() const noexcept {
- return elem;
- }
- template<std::size_t Index>
- [[nodiscard]] common_type *storage() const noexcept {
- if constexpr(Index < Get) {
- return pools[Index];
- } else {
- return filter[Index - Get];
- }
- }
- private:
- std::array<common_type *, Get> pools;
- std::array<common_type *, Exclude> filter;
- common_type elem;
- };
- } // namespace internal
- /*! @endcond */
- /**
- * @brief Group.
- *
- * Primary template isn't defined on purpose. All the specializations give a
- * compile-time error, but for a few reasonable cases.
- */
- template<typename, typename, typename>
- class basic_group;
- /**
- * @brief Non-owning group.
- *
- * A non-owning group returns all entities and only the entities that are at
- * least in the given storage. Moreover, it's guaranteed that the entity list is
- * tightly packed in memory for fast iterations.
- *
- * @b Important
- *
- * Iterators aren't invalidated if:
- *
- * * New elements are added to the storage.
- * * The entity currently pointed is modified (for example, elements are added
- * or removed from it).
- * * The entity currently pointed is destroyed.
- *
- * In all other cases, modifying the pools iterated by the group in any way
- * invalidates all the iterators.
- *
- * @tparam Get Types of storage _observed_ by the group.
- * @tparam Exclude Types of storage used to filter the group.
- */
- template<typename... Get, typename... Exclude>
- class basic_group<owned_t<>, get_t<Get...>, exclude_t<Exclude...>> {
- using base_type = std::common_type_t<typename Get::base_type..., typename Exclude::base_type...>;
- using underlying_type = typename base_type::entity_type;
- template<typename Type>
- static constexpr std::size_t index_of = type_list_index_v<std::remove_const_t<Type>, type_list<typename Get::element_type..., typename Exclude::element_type...>>;
- template<std::size_t... Index>
- [[nodiscard]] auto pools_for(std::index_sequence<Index...>) const noexcept {
- using return_type = std::tuple<Get *...>;
- return descriptor ? return_type{static_cast<Get *>(descriptor->template storage<Index>())...} : return_type{};
- }
- public:
- /*! @brief Underlying entity identifier. */
- using entity_type = underlying_type;
- /*! @brief Unsigned integer type. */
- using size_type = std::size_t;
- /*! @brief Signed integer type. */
- using difference_type = std::ptrdiff_t;
- /*! @brief Common type among all storage types. */
- using common_type = base_type;
- /*! @brief Random access iterator type. */
- using iterator = typename common_type::iterator;
- /*! @brief Reverse iterator type. */
- using reverse_iterator = typename common_type::reverse_iterator;
- /*! @brief Iterable group type. */
- using iterable = iterable_adaptor<internal::extended_group_iterator<iterator, owned_t<>, get_t<Get...>>>;
- /*! @brief Group handler type. */
- using handler = internal::group_handler<common_type, 0u, sizeof...(Get), sizeof...(Exclude)>;
- /**
- * @brief Group opaque identifier.
- * @return Group opaque identifier.
- */
- static id_type group_id() noexcept {
- return type_hash<basic_group<owned_t<>, get_t<std::remove_const_t<Get>...>, exclude_t<std::remove_const_t<Exclude>...>>>::value();
- }
- /*! @brief Default constructor to use to create empty, invalid groups. */
- basic_group() noexcept
- : descriptor{} {}
- /**
- * @brief Constructs a group from a set of storage classes.
- * @param ref A reference to a group handler.
- */
- basic_group(handler &ref) noexcept
- : descriptor{&ref} {}
- /**
- * @brief Returns the leading storage of a group.
- * @return The leading storage of the group.
- */
- [[nodiscard]] const common_type &handle() const noexcept {
- return descriptor->handle();
- }
- /**
- * @brief Returns the storage for a given element type, if any.
- * @tparam Type Type of element of which to return the storage.
- * @return The storage for the given element type.
- */
- template<typename Type>
- [[nodiscard]] auto *storage() const noexcept {
- return storage<index_of<Type>>();
- }
- /**
- * @brief Returns the storage for a given index, if any.
- * @tparam Index Index of the storage to return.
- * @return The storage for the given index.
- */
- template<std::size_t Index>
- [[nodiscard]] auto *storage() const noexcept {
- using type = type_list_element_t<Index, type_list<Get..., Exclude...>>;
- return *this ? static_cast<type *>(descriptor->template storage<Index>()) : nullptr;
- }
- /**
- * @brief Returns the number of entities that are part of the group.
- * @return Number of entities that are part of the group.
- */
- [[nodiscard]] size_type size() const noexcept {
- return *this ? handle().size() : size_type{};
- }
- /**
- * @brief Returns the number of elements that a group has currently
- * allocated space for.
- * @return Capacity of the group.
- */
- [[nodiscard]] size_type capacity() const noexcept {
- return *this ? handle().capacity() : size_type{};
- }
- /*! @brief Requests the removal of unused capacity. */
- void shrink_to_fit() {
- if(*this) {
- descriptor->handle().shrink_to_fit();
- }
- }
- /**
- * @brief Checks whether a group is empty.
- * @return True if the group is empty, false otherwise.
- */
- [[nodiscard]] bool empty() const noexcept {
- return !*this || handle().empty();
- }
- /**
- * @brief Returns an iterator to the first entity of the group.
- *
- * If the group is empty, the returned iterator will be equal to `end()`.
- *
- * @return An iterator to the first entity of the group.
- */
- [[nodiscard]] iterator begin() const noexcept {
- return *this ? handle().begin() : iterator{};
- }
- /**
- * @brief Returns an iterator that is past the last entity of the group.
- * @return An iterator to the entity following the last entity of the
- * group.
- */
- [[nodiscard]] iterator end() const noexcept {
- return *this ? handle().end() : iterator{};
- }
- /**
- * @brief Returns an iterator to the first entity of the reversed group.
- *
- * If the group is empty, the returned iterator will be equal to `rend()`.
- *
- * @return An iterator to the first entity of the reversed group.
- */
- [[nodiscard]] reverse_iterator rbegin() const noexcept {
- return *this ? handle().rbegin() : reverse_iterator{};
- }
- /**
- * @brief Returns an iterator that is past the last entity of the reversed
- * group.
- * @return An iterator to the entity following the last entity of the
- * reversed group.
- */
- [[nodiscard]] reverse_iterator rend() const noexcept {
- return *this ? handle().rend() : reverse_iterator{};
- }
- /**
- * @brief Returns the first entity of the group, if any.
- * @return The first entity of the group if one exists, the null entity
- * otherwise.
- */
- [[nodiscard]] entity_type front() const noexcept {
- const auto it = begin();
- return it != end() ? *it : null;
- }
- /**
- * @brief Returns the last entity of the group, if any.
- * @return The last entity of the group if one exists, the null entity
- * otherwise.
- */
- [[nodiscard]] entity_type back() const noexcept {
- const auto it = rbegin();
- return it != rend() ? *it : null;
- }
- /**
- * @brief Finds an entity.
- * @param entt A valid identifier.
- * @return An iterator to the given entity if it's found, past the end
- * iterator otherwise.
- */
- [[nodiscard]] iterator find(const entity_type entt) const noexcept {
- return *this ? handle().find(entt) : iterator{};
- }
- /**
- * @brief Returns the identifier that occupies the given position.
- * @param pos Position of the element to return.
- * @return The identifier that occupies the given position.
- */
- [[nodiscard]] entity_type operator[](const size_type pos) const {
- return begin()[static_cast<difference_type>(pos)];
- }
- /**
- * @brief Checks if a group is properly initialized.
- * @return True if the group is properly initialized, false otherwise.
- */
- [[nodiscard]] explicit operator bool() const noexcept {
- return descriptor != nullptr;
- }
- /**
- * @brief Checks if a group contains an entity.
- * @param entt A valid identifier.
- * @return True if the group contains the given entity, false otherwise.
- */
- [[nodiscard]] bool contains(const entity_type entt) const noexcept {
- return *this && handle().contains(entt);
- }
- /**
- * @brief Returns the elements assigned to the given entity.
- * @tparam Type Type of the element to get.
- * @tparam Other Other types of elements to get.
- * @param entt A valid identifier.
- * @return The elements assigned to the entity.
- */
- template<typename Type, typename... Other>
- [[nodiscard]] decltype(auto) get(const entity_type entt) const {
- return get<index_of<Type>, index_of<Other>...>(entt);
- }
- /**
- * @brief Returns the elements assigned to the given entity.
- * @tparam Index Indexes of the elements to get.
- * @param entt A valid identifier.
- * @return The elements assigned to the entity.
- */
- template<std::size_t... Index>
- [[nodiscard]] decltype(auto) get(const entity_type entt) const {
- const auto cpools = pools_for(std::index_sequence_for<Get...>{});
- if constexpr(sizeof...(Index) == 0) {
- return std::apply([entt](auto *...curr) { return std::tuple_cat(curr->get_as_tuple(entt)...); }, cpools);
- } else if constexpr(sizeof...(Index) == 1) {
- return (std::get<Index>(cpools)->get(entt), ...);
- } else {
- return std::tuple_cat(std::get<Index>(cpools)->get_as_tuple(entt)...);
- }
- }
- /**
- * @brief Iterates entities and elements and applies the given function
- * object to them.
- *
- * The function object is invoked for each entity. It is provided with the
- * entity itself and a set of references to non-empty elements. The
- * _constness_ of the elements is as requested.<br/>
- * The signature of the function must be equivalent to one of the following
- * forms:
- *
- * @code{.cpp}
- * void(const entity_type, Type &...);
- * void(Type &...);
- * @endcode
- *
- * @note
- * Empty types aren't explicitly instantiated and therefore they are never
- * returned during iterations.
- *
- * @tparam Func Type of the function object to invoke.
- * @param func A valid function object.
- */
- template<typename Func>
- void each(Func func) const {
- for(const auto entt: *this) {
- if constexpr(is_applicable_v<Func, decltype(std::tuple_cat(std::tuple<entity_type>{}, std::declval<basic_group>().get({})))>) {
- std::apply(func, std::tuple_cat(std::make_tuple(entt), get(entt)));
- } else {
- std::apply(func, get(entt));
- }
- }
- }
- /**
- * @brief Returns an iterable object to use to _visit_ a group.
- *
- * The iterable object returns tuples that contain the current entity and a
- * set of references to its non-empty elements. The _constness_ of the
- * elements is as requested.
- *
- * @note
- * Empty types aren't explicitly instantiated and therefore they are never
- * returned during iterations.
- *
- * @return An iterable object to use to _visit_ the group.
- */
- [[nodiscard]] iterable each() const noexcept {
- const auto cpools = pools_for(std::index_sequence_for<Get...>{});
- return iterable{{begin(), cpools}, {end(), cpools}};
- }
- /**
- * @brief Sort a group according to the given comparison function.
- *
- * The comparison function object must return `true` if the first element
- * is _less_ than the second one, `false` otherwise. The signature of the
- * comparison function should be equivalent to one of the following:
- *
- * @code{.cpp}
- * bool(std::tuple<Type &...>, std::tuple<Type &...>);
- * bool(const Type &..., const Type &...);
- * bool(const Entity, const Entity);
- * @endcode
- *
- * Where `Type` are such that they are iterated by the group.<br/>
- * Moreover, the comparison function object shall induce a
- * _strict weak ordering_ on the values.
- *
- * The sort function object must offer a member function template
- * `operator()` that accepts three arguments:
- *
- * * An iterator to the first element of the range to sort.
- * * An iterator past the last element of the range to sort.
- * * A comparison function to use to compare the elements.
- *
- * @tparam Type Optional type of element to compare.
- * @tparam Other Other optional types of elements to compare.
- * @tparam Compare Type of comparison function object.
- * @tparam Sort Type of sort function object.
- * @tparam Args Types of arguments to forward to the sort function object.
- * @param compare A valid comparison function object.
- * @param algo A valid sort function object.
- * @param args Arguments to forward to the sort function object, if any.
- */
- template<typename Type, typename... Other, typename Compare, typename Sort = std_sort, typename... Args>
- void sort(Compare compare, Sort algo = Sort{}, Args &&...args) {
- sort<index_of<Type>, index_of<Other>...>(std::move(compare), std::move(algo), std::forward<Args>(args)...);
- }
- /**
- * @brief Sort a group according to the given comparison function.
- *
- * @sa sort
- *
- * @tparam Index Optional indexes of elements to compare.
- * @tparam Compare Type of comparison function object.
- * @tparam Sort Type of sort function object.
- * @tparam Args Types of arguments to forward to the sort function object.
- * @param compare A valid comparison function object.
- * @param algo A valid sort function object.
- * @param args Arguments to forward to the sort function object, if any.
- */
- template<std::size_t... Index, typename Compare, typename Sort = std_sort, typename... Args>
- void sort(Compare compare, Sort algo = Sort{}, Args &&...args) {
- if(*this) {
- if constexpr(sizeof...(Index) == 0) {
- static_assert(std::is_invocable_v<Compare, const entity_type, const entity_type>, "Invalid comparison function");
- descriptor->handle().sort(std::move(compare), std::move(algo), std::forward<Args>(args)...);
- } else {
- auto comp = [&compare, cpools = pools_for(std::index_sequence_for<Get...>{})](const entity_type lhs, const entity_type rhs) {
- if constexpr(sizeof...(Index) == 1) {
- return compare((std::get<Index>(cpools)->get(lhs), ...), (std::get<Index>(cpools)->get(rhs), ...));
- } else {
- return compare(std::forward_as_tuple(std::get<Index>(cpools)->get(lhs)...), std::forward_as_tuple(std::get<Index>(cpools)->get(rhs)...));
- }
- };
- descriptor->handle().sort(std::move(comp), std::move(algo), std::forward<Args>(args)...);
- }
- }
- }
- /**
- * @brief Sort entities according to their order in a range.
- *
- * The shared pool of entities and thus its order is affected by the changes
- * to each and every pool that it tracks.
- *
- * @tparam It Type of input iterator.
- * @param first An iterator to the first element of the range of entities.
- * @param last An iterator past the last element of the range of entities.
- */
- template<typename It>
- void sort_as(It first, It last) const {
- if(*this) {
- descriptor->handle().sort_as(first, last);
- }
- }
- private:
- handler *descriptor;
- };
- /**
- * @brief Owning group.
- *
- * Owning groups returns all entities and only the entities that are at
- * least in the given storage. Moreover:
- *
- * * It's guaranteed that the entity list is tightly packed in memory for fast
- * iterations.
- * * It's guaranteed that all elements in the owned storage are tightly packed
- * in memory for even faster iterations and to allow direct access.
- * * They stay true to the order of the owned storage and all instances have the
- * same order in memory.
- *
- * The more types of storage are owned, the faster it is to iterate a group.
- *
- * @b Important
- *
- * Iterators aren't invalidated if:
- *
- * * New elements are added to the storage.
- * * The entity currently pointed is modified (for example, elements are added
- * or removed from it).
- * * The entity currently pointed is destroyed.
- *
- * In all other cases, modifying the pools iterated by the group in any way
- * invalidates all the iterators.
- *
- * @tparam Owned Types of storage _owned_ by the group.
- * @tparam Get Types of storage _observed_ by the group.
- * @tparam Exclude Types of storage used to filter the group.
- */
- template<typename... Owned, typename... Get, typename... Exclude>
- class basic_group<owned_t<Owned...>, get_t<Get...>, exclude_t<Exclude...>> {
- static_assert(((Owned::storage_policy != deletion_policy::in_place) && ...), "Groups do not support in-place delete");
- using base_type = std::common_type_t<typename Owned::base_type..., typename Get::base_type..., typename Exclude::base_type...>;
- using underlying_type = typename base_type::entity_type;
- template<typename Type>
- static constexpr std::size_t index_of = type_list_index_v<std::remove_const_t<Type>, type_list<typename Owned::element_type..., typename Get::element_type..., typename Exclude::element_type...>>;
- template<std::size_t... Index, std::size_t... Other>
- [[nodiscard]] auto pools_for(std::index_sequence<Index...>, std::index_sequence<Other...>) const noexcept {
- using return_type = std::tuple<Owned *..., Get *...>;
- return descriptor ? return_type{static_cast<Owned *>(descriptor->template storage<Index>())..., static_cast<Get *>(descriptor->template storage<sizeof...(Owned) + Other>())...} : return_type{};
- }
- public:
- /*! @brief Underlying entity identifier. */
- using entity_type = underlying_type;
- /*! @brief Unsigned integer type. */
- using size_type = std::size_t;
- /*! @brief Signed integer type. */
- using difference_type = std::ptrdiff_t;
- /*! @brief Common type among all storage types. */
- using common_type = base_type;
- /*! @brief Random access iterator type. */
- using iterator = typename common_type::iterator;
- /*! @brief Reverse iterator type. */
- using reverse_iterator = typename common_type::reverse_iterator;
- /*! @brief Iterable group type. */
- using iterable = iterable_adaptor<internal::extended_group_iterator<iterator, owned_t<Owned...>, get_t<Get...>>>;
- /*! @brief Group handler type. */
- using handler = internal::group_handler<common_type, sizeof...(Owned), sizeof...(Get), sizeof...(Exclude)>;
- /**
- * @brief Group opaque identifier.
- * @return Group opaque identifier.
- */
- static id_type group_id() noexcept {
- return type_hash<basic_group<owned_t<std::remove_const_t<Owned>...>, get_t<std::remove_const_t<Get>...>, exclude_t<std::remove_const_t<Exclude>...>>>::value();
- }
- /*! @brief Default constructor to use to create empty, invalid groups. */
- basic_group() noexcept
- : descriptor{} {}
- /**
- * @brief Constructs a group from a set of storage classes.
- * @param ref A reference to a group handler.
- */
- basic_group(handler &ref) noexcept
- : descriptor{&ref} {}
- /**
- * @brief Returns the leading storage of a group.
- * @return The leading storage of the group.
- */
- [[nodiscard]] const common_type &handle() const noexcept {
- return *storage<0>();
- }
- /**
- * @brief Returns the storage for a given element type, if any.
- * @tparam Type Type of element of which to return the storage.
- * @return The storage for the given element type.
- */
- template<typename Type>
- [[nodiscard]] auto *storage() const noexcept {
- return storage<index_of<Type>>();
- }
- /**
- * @brief Returns the storage for a given index, if any.
- * @tparam Index Index of the storage to return.
- * @return The storage for the given index.
- */
- template<std::size_t Index>
- [[nodiscard]] auto *storage() const noexcept {
- using type = type_list_element_t<Index, type_list<Owned..., Get..., Exclude...>>;
- return *this ? static_cast<type *>(descriptor->template storage<Index>()) : nullptr;
- }
- /**
- * @brief Returns the number of entities that that are part of the group.
- * @return Number of entities that that are part of the group.
- */
- [[nodiscard]] size_type size() const noexcept {
- return *this ? descriptor->length() : size_type{};
- }
- /**
- * @brief Checks whether a group is empty.
- * @return True if the group is empty, false otherwise.
- */
- [[nodiscard]] bool empty() const noexcept {
- return !*this || !descriptor->length();
- }
- /**
- * @brief Returns an iterator to the first entity of the group.
- *
- * If the group is empty, the returned iterator will be equal to `end()`.
- *
- * @return An iterator to the first entity of the group.
- */
- [[nodiscard]] iterator begin() const noexcept {
- return *this ? (handle().end() - static_cast<difference_type>(descriptor->length())) : iterator{};
- }
- /**
- * @brief Returns an iterator that is past the last entity of the group.
- * @return An iterator to the entity following the last entity of the
- * group.
- */
- [[nodiscard]] iterator end() const noexcept {
- return *this ? handle().end() : iterator{};
- }
- /**
- * @brief Returns an iterator to the first entity of the reversed group.
- *
- * If the group is empty, the returned iterator will be equal to `rend()`.
- *
- * @return An iterator to the first entity of the reversed group.
- */
- [[nodiscard]] reverse_iterator rbegin() const noexcept {
- return *this ? handle().rbegin() : reverse_iterator{};
- }
- /**
- * @brief Returns an iterator that is past the last entity of the reversed
- * group.
- * @return An iterator to the entity following the last entity of the
- * reversed group.
- */
- [[nodiscard]] reverse_iterator rend() const noexcept {
- return *this ? (handle().rbegin() + static_cast<difference_type>(descriptor->length())) : reverse_iterator{};
- }
- /**
- * @brief Returns the first entity of the group, if any.
- * @return The first entity of the group if one exists, the null entity
- * otherwise.
- */
- [[nodiscard]] entity_type front() const noexcept {
- const auto it = begin();
- return it != end() ? *it : null;
- }
- /**
- * @brief Returns the last entity of the group, if any.
- * @return The last entity of the group if one exists, the null entity
- * otherwise.
- */
- [[nodiscard]] entity_type back() const noexcept {
- const auto it = rbegin();
- return it != rend() ? *it : null;
- }
- /**
- * @brief Finds an entity.
- * @param entt A valid identifier.
- * @return An iterator to the given entity if it's found, past the end
- * iterator otherwise.
- */
- [[nodiscard]] iterator find(const entity_type entt) const noexcept {
- const auto it = *this ? handle().find(entt) : iterator{};
- return it >= begin() ? it : iterator{};
- }
- /**
- * @brief Returns the identifier that occupies the given position.
- * @param pos Position of the element to return.
- * @return The identifier that occupies the given position.
- */
- [[nodiscard]] entity_type operator[](const size_type pos) const {
- return begin()[static_cast<difference_type>(pos)];
- }
- /**
- * @brief Checks if a group is properly initialized.
- * @return True if the group is properly initialized, false otherwise.
- */
- [[nodiscard]] explicit operator bool() const noexcept {
- return descriptor != nullptr;
- }
- /**
- * @brief Checks if a group contains an entity.
- * @param entt A valid identifier.
- * @return True if the group contains the given entity, false otherwise.
- */
- [[nodiscard]] bool contains(const entity_type entt) const noexcept {
- return *this && handle().contains(entt) && (handle().index(entt) < (descriptor->length()));
- }
- /**
- * @brief Returns the elements assigned to the given entity.
- * @tparam Type Type of the element to get.
- * @tparam Other Other types of elements to get.
- * @param entt A valid identifier.
- * @return The elements assigned to the entity.
- */
- template<typename Type, typename... Other>
- [[nodiscard]] decltype(auto) get(const entity_type entt) const {
- return get<index_of<Type>, index_of<Other>...>(entt);
- }
- /**
- * @brief Returns the elements assigned to the given entity.
- * @tparam Index Indexes of the elements to get.
- * @param entt A valid identifier.
- * @return The elements assigned to the entity.
- */
- template<std::size_t... Index>
- [[nodiscard]] decltype(auto) get(const entity_type entt) const {
- const auto cpools = pools_for(std::index_sequence_for<Owned...>{}, std::index_sequence_for<Get...>{});
- if constexpr(sizeof...(Index) == 0) {
- return std::apply([entt](auto *...curr) { return std::tuple_cat(curr->get_as_tuple(entt)...); }, cpools);
- } else if constexpr(sizeof...(Index) == 1) {
- return (std::get<Index>(cpools)->get(entt), ...);
- } else {
- return std::tuple_cat(std::get<Index>(cpools)->get_as_tuple(entt)...);
- }
- }
- /**
- * @brief Iterates entities and elements and applies the given function
- * object to them.
- *
- * The function object is invoked for each entity. It is provided with the
- * entity itself and a set of references to non-empty elements. The
- * _constness_ of the elements is as requested.<br/>
- * The signature of the function must be equivalent to one of the following
- * forms:
- *
- * @code{.cpp}
- * void(const entity_type, Type &...);
- * void(Type &...);
- * @endcode
- *
- * @note
- * Empty types aren't explicitly instantiated and therefore they are never
- * returned during iterations.
- *
- * @tparam Func Type of the function object to invoke.
- * @param func A valid function object.
- */
- template<typename Func>
- void each(Func func) const {
- for(auto args: each()) {
- if constexpr(is_applicable_v<Func, decltype(std::tuple_cat(std::tuple<entity_type>{}, std::declval<basic_group>().get({})))>) {
- std::apply(func, args);
- } else {
- std::apply([&func](auto, auto &&...less) { func(std::forward<decltype(less)>(less)...); }, args);
- }
- }
- }
- /**
- * @brief Returns an iterable object to use to _visit_ a group.
- *
- * The iterable object returns tuples that contain the current entity and a
- * set of references to its non-empty elements. The _constness_ of the
- * elements is as requested.
- *
- * @note
- * Empty types aren't explicitly instantiated and therefore they are never
- * returned during iterations.
- *
- * @return An iterable object to use to _visit_ the group.
- */
- [[nodiscard]] iterable each() const noexcept {
- const auto cpools = pools_for(std::index_sequence_for<Owned...>{}, std::index_sequence_for<Get...>{});
- return iterable{{begin(), cpools}, {end(), cpools}};
- }
- /**
- * @brief Sort a group according to the given comparison function.
- *
- * The comparison function object must return `true` if the first element
- * is _less_ than the second one, `false` otherwise. The signature of the
- * comparison function should be equivalent to one of the following:
- *
- * @code{.cpp}
- * bool(std::tuple<Type &...>, std::tuple<Type &...>);
- * bool(const Type &, const Type &);
- * bool(const Entity, const Entity);
- * @endcode
- *
- * Where `Type` are either owned types or not but still such that they are
- * iterated by the group.<br/>
- * Moreover, the comparison function object shall induce a
- * _strict weak ordering_ on the values.
- *
- * The sort function object must offer a member function template
- * `operator()` that accepts three arguments:
- *
- * * An iterator to the first element of the range to sort.
- * * An iterator past the last element of the range to sort.
- * * A comparison function to use to compare the elements.
- *
- * @tparam Type Optional type of element to compare.
- * @tparam Other Other optional types of elements to compare.
- * @tparam Compare Type of comparison function object.
- * @tparam Sort Type of sort function object.
- * @tparam Args Types of arguments to forward to the sort function object.
- * @param compare A valid comparison function object.
- * @param algo A valid sort function object.
- * @param args Arguments to forward to the sort function object, if any.
- */
- template<typename Type, typename... Other, typename Compare, typename Sort = std_sort, typename... Args>
- void sort(Compare compare, Sort algo = Sort{}, Args &&...args) const {
- sort<index_of<Type>, index_of<Other>...>(std::move(compare), std::move(algo), std::forward<Args>(args)...);
- }
- /**
- * @brief Sort a group according to the given comparison function.
- *
- * @sa sort
- *
- * @tparam Index Optional indexes of elements to compare.
- * @tparam Compare Type of comparison function object.
- * @tparam Sort Type of sort function object.
- * @tparam Args Types of arguments to forward to the sort function object.
- * @param compare A valid comparison function object.
- * @param algo A valid sort function object.
- * @param args Arguments to forward to the sort function object, if any.
- */
- template<std::size_t... Index, typename Compare, typename Sort = std_sort, typename... Args>
- void sort(Compare compare, Sort algo = Sort{}, Args &&...args) const {
- const auto cpools = pools_for(std::index_sequence_for<Owned...>{}, std::index_sequence_for<Get...>{});
- if constexpr(sizeof...(Index) == 0) {
- static_assert(std::is_invocable_v<Compare, const entity_type, const entity_type>, "Invalid comparison function");
- storage<0>()->sort_n(descriptor->length(), std::move(compare), std::move(algo), std::forward<Args>(args)...);
- } else {
- auto comp = [&compare, &cpools](const entity_type lhs, const entity_type rhs) {
- if constexpr(sizeof...(Index) == 1) {
- return compare((std::get<Index>(cpools)->get(lhs), ...), (std::get<Index>(cpools)->get(rhs), ...));
- } else {
- return compare(std::forward_as_tuple(std::get<Index>(cpools)->get(lhs)...), std::forward_as_tuple(std::get<Index>(cpools)->get(rhs)...));
- }
- };
- storage<0>()->sort_n(descriptor->length(), std::move(comp), std::move(algo), std::forward<Args>(args)...);
- }
- auto cb = [this](auto *head, auto *...other) {
- for(auto next = descriptor->length(); next; --next) {
- const auto pos = next - 1;
- [[maybe_unused]] const auto entt = head->data()[pos];
- (other->swap_elements(other->data()[pos], entt), ...);
- }
- };
- std::apply(cb, cpools);
- }
- private:
- handler *descriptor;
- };
- } // namespace entt
- #endif
- // #include "storage.hpp"
- #ifndef ENTT_ENTITY_STORAGE_HPP
- #define ENTT_ENTITY_STORAGE_HPP
- #include <cstddef>
- #include <iterator>
- #include <memory>
- #include <tuple>
- #include <type_traits>
- #include <utility>
- #include <vector>
- // #include "../config/config.h"
- // #include "../core/bit.hpp"
- // #include "../core/iterator.hpp"
- // #include "../core/memory.hpp"
- #ifndef ENTT_CORE_MEMORY_HPP
- #define ENTT_CORE_MEMORY_HPP
- #include <cstddef>
- #include <memory>
- #include <tuple>
- #include <type_traits>
- #include <utility>
- // #include "../config/config.h"
- namespace entt {
- /**
- * @brief Unwraps fancy pointers, does nothing otherwise (waiting for C++20).
- * @tparam Type Pointer type.
- * @param ptr Fancy or raw pointer.
- * @return A raw pointer that represents the address of the original pointer.
- */
- template<typename Type>
- [[nodiscard]] constexpr auto to_address(Type &&ptr) noexcept {
- if constexpr(std::is_pointer_v<std::decay_t<Type>>) {
- return ptr;
- } else {
- return to_address(std::forward<Type>(ptr).operator->());
- }
- }
- /**
- * @brief Utility function to design allocation-aware containers.
- * @tparam Allocator Type of allocator.
- * @param lhs A valid allocator.
- * @param rhs Another valid allocator.
- */
- template<typename Allocator>
- constexpr void propagate_on_container_copy_assignment([[maybe_unused]] Allocator &lhs, [[maybe_unused]] Allocator &rhs) noexcept {
- if constexpr(std::allocator_traits<Allocator>::propagate_on_container_copy_assignment::value) {
- lhs = rhs;
- }
- }
- /**
- * @brief Utility function to design allocation-aware containers.
- * @tparam Allocator Type of allocator.
- * @param lhs A valid allocator.
- * @param rhs Another valid allocator.
- */
- template<typename Allocator>
- constexpr void propagate_on_container_move_assignment([[maybe_unused]] Allocator &lhs, [[maybe_unused]] Allocator &rhs) noexcept {
- if constexpr(std::allocator_traits<Allocator>::propagate_on_container_move_assignment::value) {
- lhs = std::move(rhs);
- }
- }
- /**
- * @brief Utility function to design allocation-aware containers.
- * @tparam Allocator Type of allocator.
- * @param lhs A valid allocator.
- * @param rhs Another valid allocator.
- */
- template<typename Allocator>
- constexpr void propagate_on_container_swap([[maybe_unused]] Allocator &lhs, [[maybe_unused]] Allocator &rhs) noexcept {
- if constexpr(std::allocator_traits<Allocator>::propagate_on_container_swap::value) {
- using std::swap;
- swap(lhs, rhs);
- } else {
- ENTT_ASSERT_CONSTEXPR(lhs == rhs, "Cannot swap the containers");
- }
- }
- /**
- * @brief Deleter for allocator-aware unique pointers (waiting for C++20).
- * @tparam Allocator Type of allocator used to manage memory and elements.
- */
- template<typename Allocator>
- struct allocation_deleter: private Allocator {
- /*! @brief Allocator type. */
- using allocator_type = Allocator;
- /*! @brief Pointer type. */
- using pointer = typename std::allocator_traits<Allocator>::pointer;
- /**
- * @brief Inherited constructors.
- * @param alloc The allocator to use.
- */
- constexpr allocation_deleter(const allocator_type &alloc) noexcept(std::is_nothrow_copy_constructible_v<allocator_type>)
- : Allocator{alloc} {}
- /**
- * @brief Destroys the pointed object and deallocates its memory.
- * @param ptr A valid pointer to an object of the given type.
- */
- constexpr void operator()(pointer ptr) noexcept(std::is_nothrow_destructible_v<typename allocator_type::value_type>) {
- using alloc_traits = std::allocator_traits<Allocator>;
- alloc_traits::destroy(*this, to_address(ptr));
- alloc_traits::deallocate(*this, ptr, 1u);
- }
- };
- /**
- * @brief Allows `std::unique_ptr` to use allocators (waiting for C++20).
- * @tparam Type Type of object to allocate for and to construct.
- * @tparam Allocator Type of allocator used to manage memory and elements.
- * @tparam Args Types of arguments to use to construct the object.
- * @param allocator The allocator to use.
- * @param args Parameters to use to construct the object.
- * @return A properly initialized unique pointer with a custom deleter.
- */
- template<typename Type, typename Allocator, typename... Args>
- ENTT_CONSTEXPR auto allocate_unique(Allocator &allocator, Args &&...args) {
- static_assert(!std::is_array_v<Type>, "Array types are not supported");
- using alloc_traits = typename std::allocator_traits<Allocator>::template rebind_traits<Type>;
- using allocator_type = typename alloc_traits::allocator_type;
- allocator_type alloc{allocator};
- auto ptr = alloc_traits::allocate(alloc, 1u);
- ENTT_TRY {
- alloc_traits::construct(alloc, to_address(ptr), std::forward<Args>(args)...);
- }
- ENTT_CATCH {
- alloc_traits::deallocate(alloc, ptr, 1u);
- ENTT_THROW;
- }
- return std::unique_ptr<Type, allocation_deleter<allocator_type>>{ptr, alloc};
- }
- /*! @cond TURN_OFF_DOXYGEN */
- namespace internal {
- template<typename Type>
- struct uses_allocator_construction {
- template<typename Allocator, typename... Params>
- static constexpr auto args([[maybe_unused]] const Allocator &allocator, Params &&...params) noexcept {
- if constexpr(!std::uses_allocator_v<Type, Allocator> && std::is_constructible_v<Type, Params...>) {
- return std::forward_as_tuple(std::forward<Params>(params)...);
- } else {
- static_assert(std::uses_allocator_v<Type, Allocator>, "Ill-formed request");
- if constexpr(std::is_constructible_v<Type, std::allocator_arg_t, const Allocator &, Params...>) {
- return std::tuple<std::allocator_arg_t, const Allocator &, Params &&...>{std::allocator_arg, allocator, std::forward<Params>(params)...};
- } else {
- static_assert(std::is_constructible_v<Type, Params..., const Allocator &>, "Ill-formed request");
- return std::forward_as_tuple(std::forward<Params>(params)..., allocator);
- }
- }
- }
- };
- template<typename Type, typename Other>
- struct uses_allocator_construction<std::pair<Type, Other>> {
- using type = std::pair<Type, Other>;
- template<typename Allocator, typename First, typename Second>
- static constexpr auto args(const Allocator &allocator, std::piecewise_construct_t, First &&first, Second &&second) noexcept {
- return std::make_tuple(
- std::piecewise_construct,
- std::apply([&allocator](auto &&...curr) { return uses_allocator_construction<Type>::args(allocator, std::forward<decltype(curr)>(curr)...); }, std::forward<First>(first)),
- std::apply([&allocator](auto &&...curr) { return uses_allocator_construction<Other>::args(allocator, std::forward<decltype(curr)>(curr)...); }, std::forward<Second>(second)));
- }
- template<typename Allocator>
- static constexpr auto args(const Allocator &allocator) noexcept {
- return uses_allocator_construction<type>::args(allocator, std::piecewise_construct, std::tuple<>{}, std::tuple<>{});
- }
- template<typename Allocator, typename First, typename Second>
- static constexpr auto args(const Allocator &allocator, First &&first, Second &&second) noexcept {
- return uses_allocator_construction<type>::args(allocator, std::piecewise_construct, std::forward_as_tuple(std::forward<First>(first)), std::forward_as_tuple(std::forward<Second>(second)));
- }
- template<typename Allocator, typename First, typename Second>
- static constexpr auto args(const Allocator &allocator, const std::pair<First, Second> &value) noexcept {
- return uses_allocator_construction<type>::args(allocator, std::piecewise_construct, std::forward_as_tuple(value.first), std::forward_as_tuple(value.second));
- }
- template<typename Allocator, typename First, typename Second>
- static constexpr auto args(const Allocator &allocator, std::pair<First, Second> &&value) noexcept {
- return uses_allocator_construction<type>::args(allocator, std::piecewise_construct, std::forward_as_tuple(std::move(value.first)), std::forward_as_tuple(std::move(value.second)));
- }
- };
- } // namespace internal
- /*! @endcond */
- /**
- * @brief Uses-allocator construction utility (waiting for C++20).
- *
- * Primarily intended for internal use. Prepares the argument list needed to
- * create an object of a given type by means of uses-allocator construction.
- *
- * @tparam Type Type to return arguments for.
- * @tparam Allocator Type of allocator used to manage memory and elements.
- * @tparam Args Types of arguments to use to construct the object.
- * @param allocator The allocator to use.
- * @param args Parameters to use to construct the object.
- * @return The arguments needed to create an object of the given type.
- */
- template<typename Type, typename Allocator, typename... Args>
- constexpr auto uses_allocator_construction_args(const Allocator &allocator, Args &&...args) noexcept {
- return internal::uses_allocator_construction<Type>::args(allocator, std::forward<Args>(args)...);
- }
- /**
- * @brief Uses-allocator construction utility (waiting for C++20).
- *
- * Primarily intended for internal use. Creates an object of a given type by
- * means of uses-allocator construction.
- *
- * @tparam Type Type of object to create.
- * @tparam Allocator Type of allocator used to manage memory and elements.
- * @tparam Args Types of arguments to use to construct the object.
- * @param allocator The allocator to use.
- * @param args Parameters to use to construct the object.
- * @return A newly created object of the given type.
- */
- template<typename Type, typename Allocator, typename... Args>
- constexpr Type make_obj_using_allocator(const Allocator &allocator, Args &&...args) {
- return std::make_from_tuple<Type>(internal::uses_allocator_construction<Type>::args(allocator, std::forward<Args>(args)...));
- }
- /**
- * @brief Uses-allocator construction utility (waiting for C++20).
- *
- * Primarily intended for internal use. Creates an object of a given type by
- * means of uses-allocator construction at an uninitialized memory location.
- *
- * @tparam Type Type of object to create.
- * @tparam Allocator Type of allocator used to manage memory and elements.
- * @tparam Args Types of arguments to use to construct the object.
- * @param value Memory location in which to place the object.
- * @param allocator The allocator to use.
- * @param args Parameters to use to construct the object.
- * @return A pointer to the newly created object of the given type.
- */
- template<typename Type, typename Allocator, typename... Args>
- constexpr Type *uninitialized_construct_using_allocator(Type *value, const Allocator &allocator, Args &&...args) {
- return std::apply([value](auto &&...curr) { return ::new(value) Type(std::forward<decltype(curr)>(curr)...); }, internal::uses_allocator_construction<Type>::args(allocator, std::forward<Args>(args)...));
- }
- } // namespace entt
- #endif
- // #include "../core/type_info.hpp"
- // #include "component.hpp"
- // #include "entity.hpp"
- // #include "fwd.hpp"
- // #include "sparse_set.hpp"
- #ifndef ENTT_ENTITY_SPARSE_SET_HPP
- #define ENTT_ENTITY_SPARSE_SET_HPP
- #include <cstddef>
- #include <iterator>
- #include <memory>
- #include <type_traits>
- #include <utility>
- #include <vector>
- // #include "../config/config.h"
- // #include "../core/algorithm.hpp"
- // #include "../core/any.hpp"
- #ifndef ENTT_CORE_ANY_HPP
- #define ENTT_CORE_ANY_HPP
- #include <cstddef>
- #include <memory>
- #include <type_traits>
- #include <utility>
- // #include "../config/config.h"
- // #include "fwd.hpp"
- // #include "type_info.hpp"
- #ifndef ENTT_CORE_TYPE_INFO_HPP
- #define ENTT_CORE_TYPE_INFO_HPP
- #include <string_view>
- #include <type_traits>
- #include <utility>
- // #include "../config/config.h"
- // #include "fwd.hpp"
- // #include "hashed_string.hpp"
- namespace entt {
- /*! @cond TURN_OFF_DOXYGEN */
- namespace internal {
- struct ENTT_API type_index final {
- [[nodiscard]] static id_type next() noexcept {
- static ENTT_MAYBE_ATOMIC(id_type) value{};
- return value++;
- }
- };
- template<typename Type>
- [[nodiscard]] constexpr const char *pretty_function() noexcept {
- #if defined ENTT_PRETTY_FUNCTION
- return static_cast<const char *>(ENTT_PRETTY_FUNCTION);
- #else
- return "";
- #endif
- }
- template<typename Type>
- [[nodiscard]] constexpr auto stripped_type_name() noexcept {
- #if defined ENTT_PRETTY_FUNCTION
- const std::string_view full_name{pretty_function<Type>()};
- auto first = full_name.find_first_not_of(' ', full_name.find_first_of(ENTT_PRETTY_FUNCTION_PREFIX) + 1);
- auto value = full_name.substr(first, full_name.find_last_of(ENTT_PRETTY_FUNCTION_SUFFIX) - first);
- return value;
- #else
- return std::string_view{};
- #endif
- }
- template<typename Type, auto = stripped_type_name<Type>().find_first_of('.')>
- [[nodiscard]] constexpr std::string_view type_name(int) noexcept {
- constexpr auto value = stripped_type_name<Type>();
- return value;
- }
- template<typename Type>
- [[nodiscard]] std::string_view type_name(char) noexcept {
- static const auto value = stripped_type_name<Type>();
- return value;
- }
- template<typename Type, auto = stripped_type_name<Type>().find_first_of('.')>
- [[nodiscard]] constexpr id_type type_hash(int) noexcept {
- constexpr auto stripped = stripped_type_name<Type>();
- constexpr auto value = hashed_string::value(stripped.data(), stripped.size());
- return value;
- }
- template<typename Type>
- [[nodiscard]] id_type type_hash(char) noexcept {
- static const auto value = [](const auto stripped) {
- return hashed_string::value(stripped.data(), stripped.size());
- }(stripped_type_name<Type>());
- return value;
- }
- } // namespace internal
- /*! @endcond */
- /**
- * @brief Type sequential identifier.
- * @tparam Type Type for which to generate a sequential identifier.
- */
- template<typename Type, typename = void>
- struct ENTT_API type_index final {
- /**
- * @brief Returns the sequential identifier of a given type.
- * @return The sequential identifier of a given type.
- */
- [[nodiscard]] static id_type value() noexcept {
- static const id_type value = internal::type_index::next();
- return value;
- }
- /*! @copydoc value */
- [[nodiscard]] constexpr operator id_type() const noexcept {
- return value();
- }
- };
- /**
- * @brief Type hash.
- * @tparam Type Type for which to generate a hash value.
- */
- template<typename Type, typename = void>
- struct type_hash final {
- /**
- * @brief Returns the numeric representation of a given type.
- * @return The numeric representation of the given type.
- */
- #if defined ENTT_PRETTY_FUNCTION
- [[nodiscard]] static constexpr id_type value() noexcept {
- return internal::type_hash<Type>(0);
- #else
- [[nodiscard]] static constexpr id_type value() noexcept {
- return type_index<Type>::value();
- #endif
- }
- /*! @copydoc value */
- [[nodiscard]] constexpr operator id_type() const noexcept {
- return value();
- }
- };
- /**
- * @brief Type name.
- * @tparam Type Type for which to generate a name.
- */
- template<typename Type, typename = void>
- struct type_name final {
- /**
- * @brief Returns the name of a given type.
- * @return The name of the given type.
- */
- [[nodiscard]] static constexpr std::string_view value() noexcept {
- return internal::type_name<Type>(0);
- }
- /*! @copydoc value */
- [[nodiscard]] constexpr operator std::string_view() const noexcept {
- return value();
- }
- };
- /*! @brief Implementation specific information about a type. */
- struct type_info final {
- /**
- * @brief Constructs a type info object for a given type.
- * @tparam Type Type for which to construct a type info object.
- */
- template<typename Type>
- // NOLINTBEGIN(modernize-use-transparent-functors)
- constexpr type_info(std::in_place_type_t<Type>) noexcept
- : seq{type_index<std::remove_const_t<std::remove_reference_t<Type>>>::value()},
- identifier{type_hash<std::remove_const_t<std::remove_reference_t<Type>>>::value()},
- alias{type_name<std::remove_const_t<std::remove_reference_t<Type>>>::value()} {}
- // NOLINTEND(modernize-use-transparent-functors)
- /**
- * @brief Type index.
- * @return Type index.
- */
- [[nodiscard]] constexpr id_type index() const noexcept {
- return seq;
- }
- /**
- * @brief Type hash.
- * @return Type hash.
- */
- [[nodiscard]] constexpr id_type hash() const noexcept {
- return identifier;
- }
- /**
- * @brief Type name.
- * @return Type name.
- */
- [[nodiscard]] constexpr std::string_view name() const noexcept {
- return alias;
- }
- private:
- id_type seq;
- id_type identifier;
- std::string_view alias;
- };
- /**
- * @brief Compares the contents of two type info objects.
- * @param lhs A type info object.
- * @param rhs A type info object.
- * @return True if the two type info objects are identical, false otherwise.
- */
- [[nodiscard]] constexpr bool operator==(const type_info &lhs, const type_info &rhs) noexcept {
- return lhs.hash() == rhs.hash();
- }
- /**
- * @brief Compares the contents of two type info objects.
- * @param lhs A type info object.
- * @param rhs A type info object.
- * @return True if the two type info objects differ, false otherwise.
- */
- [[nodiscard]] constexpr bool operator!=(const type_info &lhs, const type_info &rhs) noexcept {
- return !(lhs == rhs);
- }
- /**
- * @brief Compares two type info objects.
- * @param lhs A valid type info object.
- * @param rhs A valid type info object.
- * @return True if the first element is less than the second, false otherwise.
- */
- [[nodiscard]] constexpr bool operator<(const type_info &lhs, const type_info &rhs) noexcept {
- return lhs.index() < rhs.index();
- }
- /**
- * @brief Compares two type info objects.
- * @param lhs A valid type info object.
- * @param rhs A valid type info object.
- * @return True if the first element is less than or equal to the second, false
- * otherwise.
- */
- [[nodiscard]] constexpr bool operator<=(const type_info &lhs, const type_info &rhs) noexcept {
- return !(rhs < lhs);
- }
- /**
- * @brief Compares two type info objects.
- * @param lhs A valid type info object.
- * @param rhs A valid type info object.
- * @return True if the first element is greater than the second, false
- * otherwise.
- */
- [[nodiscard]] constexpr bool operator>(const type_info &lhs, const type_info &rhs) noexcept {
- return rhs < lhs;
- }
- /**
- * @brief Compares two type info objects.
- * @param lhs A valid type info object.
- * @param rhs A valid type info object.
- * @return True if the first element is greater than or equal to the second,
- * false otherwise.
- */
- [[nodiscard]] constexpr bool operator>=(const type_info &lhs, const type_info &rhs) noexcept {
- return !(lhs < rhs);
- }
- /**
- * @brief Returns the type info object associated to a given type.
- *
- * The returned element refers to an object with static storage duration.<br/>
- * The type doesn't need to be a complete type. If the type is a reference, the
- * result refers to the referenced type. In all cases, top-level cv-qualifiers
- * are ignored.
- *
- * @tparam Type Type for which to generate a type info object.
- * @return A reference to a properly initialized type info object.
- */
- template<typename Type>
- [[nodiscard]] const type_info &type_id() noexcept {
- if constexpr(std::is_same_v<Type, std::remove_const_t<std::remove_reference_t<Type>>>) {
- static const type_info instance{std::in_place_type<Type>};
- return instance;
- } else {
- return type_id<std::remove_const_t<std::remove_reference_t<Type>>>();
- }
- }
- /*! @copydoc type_id */
- template<typename Type>
- // NOLINTNEXTLINE(cppcoreguidelines-missing-std-forward)
- [[nodiscard]] const type_info &type_id(Type &&) noexcept {
- return type_id<std::remove_const_t<std::remove_reference_t<Type>>>();
- }
- } // namespace entt
- #endif
- // #include "type_traits.hpp"
- #ifndef ENTT_CORE_TYPE_TRAITS_HPP
- #define ENTT_CORE_TYPE_TRAITS_HPP
- #include <cstddef>
- #include <iterator>
- #include <tuple>
- #include <type_traits>
- #include <utility>
- // #include "../config/config.h"
- // #include "fwd.hpp"
- namespace entt {
- /**
- * @brief Utility class to disambiguate overloaded functions.
- * @tparam N Number of choices available.
- */
- template<std::size_t N>
- struct choice_t
- // unfortunately, doxygen cannot parse such a construct
- : /*! @cond TURN_OFF_DOXYGEN */ choice_t<N - 1> /*! @endcond */
- {};
- /*! @copybrief choice_t */
- template<>
- struct choice_t<0> {};
- /**
- * @brief Variable template for the choice trick.
- * @tparam N Number of choices available.
- */
- template<std::size_t N>
- inline constexpr choice_t<N> choice{};
- /**
- * @brief Identity type trait.
- *
- * Useful to establish non-deduced contexts in template argument deduction
- * (waiting for C++20) or to provide types through function arguments.
- *
- * @tparam Type A type.
- */
- template<typename Type>
- struct type_identity {
- /*! @brief Identity type. */
- using type = Type;
- };
- /**
- * @brief Helper type.
- * @tparam Type A type.
- */
- template<typename Type>
- using type_identity_t = typename type_identity<Type>::type;
- /**
- * @brief A type-only `sizeof` wrapper that returns 0 where `sizeof` complains.
- * @tparam Type The type of which to return the size.
- */
- template<typename Type, typename = void>
- struct size_of: std::integral_constant<std::size_t, 0u> {};
- /*! @copydoc size_of */
- template<typename Type>
- struct size_of<Type, std::void_t<decltype(sizeof(Type))>>
- // NOLINTNEXTLINE(bugprone-sizeof-expression)
- : std::integral_constant<std::size_t, sizeof(Type)> {};
- /**
- * @brief Helper variable template.
- * @tparam Type The type of which to return the size.
- */
- template<typename Type>
- inline constexpr std::size_t size_of_v = size_of<Type>::value;
- /**
- * @brief Using declaration to be used to _repeat_ the same type a number of
- * times equal to the size of a given parameter pack.
- * @tparam Type A type to repeat.
- */
- template<typename Type, typename>
- using unpack_as_type = Type;
- /**
- * @brief Helper variable template to be used to _repeat_ the same value a
- * number of times equal to the size of a given parameter pack.
- * @tparam Value A value to repeat.
- */
- template<auto Value, typename>
- inline constexpr auto unpack_as_value = Value;
- /**
- * @brief Wraps a static constant.
- * @tparam Value A static constant.
- */
- template<auto Value>
- using integral_constant = std::integral_constant<decltype(Value), Value>;
- /**
- * @brief Alias template to facilitate the creation of named values.
- * @tparam Value A constant value at least convertible to `id_type`.
- */
- template<id_type Value>
- using tag = integral_constant<Value>;
- /**
- * @brief A class to use to push around lists of types, nothing more.
- * @tparam Type Types provided by the type list.
- */
- template<typename... Type>
- struct type_list {
- /*! @brief Type list type. */
- using type = type_list;
- /*! @brief Compile-time number of elements in the type list. */
- static constexpr auto size = sizeof...(Type);
- };
- /*! @brief Primary template isn't defined on purpose. */
- template<std::size_t, typename>
- struct type_list_element;
- /**
- * @brief Provides compile-time indexed access to the types of a type list.
- * @tparam Index Index of the type to return.
- * @tparam First First type provided by the type list.
- * @tparam Other Other types provided by the type list.
- */
- template<std::size_t Index, typename First, typename... Other>
- struct type_list_element<Index, type_list<First, Other...>>
- : type_list_element<Index - 1u, type_list<Other...>> {};
- /**
- * @brief Provides compile-time indexed access to the types of a type list.
- * @tparam First First type provided by the type list.
- * @tparam Other Other types provided by the type list.
- */
- template<typename First, typename... Other>
- struct type_list_element<0u, type_list<First, Other...>> {
- /*! @brief Searched type. */
- using type = First;
- };
- /**
- * @brief Helper type.
- * @tparam Index Index of the type to return.
- * @tparam List Type list to search into.
- */
- template<std::size_t Index, typename List>
- using type_list_element_t = typename type_list_element<Index, List>::type;
- /*! @brief Primary template isn't defined on purpose. */
- template<typename, typename>
- struct type_list_index;
- /**
- * @brief Provides compile-time type access to the types of a type list.
- * @tparam Type Type to look for and for which to return the index.
- * @tparam First First type provided by the type list.
- * @tparam Other Other types provided by the type list.
- */
- template<typename Type, typename First, typename... Other>
- struct type_list_index<Type, type_list<First, Other...>> {
- /*! @brief Unsigned integer type. */
- using value_type = std::size_t;
- /*! @brief Compile-time position of the given type in the sublist. */
- static constexpr value_type value = 1u + type_list_index<Type, type_list<Other...>>::value;
- };
- /**
- * @brief Provides compile-time type access to the types of a type list.
- * @tparam Type Type to look for and for which to return the index.
- * @tparam Other Other types provided by the type list.
- */
- template<typename Type, typename... Other>
- struct type_list_index<Type, type_list<Type, Other...>> {
- static_assert(type_list_index<Type, type_list<Other...>>::value == sizeof...(Other), "Non-unique type");
- /*! @brief Unsigned integer type. */
- using value_type = std::size_t;
- /*! @brief Compile-time position of the given type in the sublist. */
- static constexpr value_type value = 0u;
- };
- /**
- * @brief Provides compile-time type access to the types of a type list.
- * @tparam Type Type to look for and for which to return the index.
- */
- template<typename Type>
- struct type_list_index<Type, type_list<>> {
- /*! @brief Unsigned integer type. */
- using value_type = std::size_t;
- /*! @brief Compile-time position of the given type in the sublist. */
- static constexpr value_type value = 0u;
- };
- /**
- * @brief Helper variable template.
- * @tparam List Type list.
- * @tparam Type Type to look for and for which to return the index.
- */
- template<typename Type, typename List>
- inline constexpr std::size_t type_list_index_v = type_list_index<Type, List>::value;
- /**
- * @brief Concatenates multiple type lists.
- * @tparam Type Types provided by the first type list.
- * @tparam Other Types provided by the second type list.
- * @return A type list composed by the types of both the type lists.
- */
- template<typename... Type, typename... Other>
- constexpr type_list<Type..., Other...> operator+(type_list<Type...>, type_list<Other...>) {
- return {};
- }
- /*! @brief Primary template isn't defined on purpose. */
- template<typename...>
- struct type_list_cat;
- /*! @brief Concatenates multiple type lists. */
- template<>
- struct type_list_cat<> {
- /*! @brief A type list composed by the types of all the type lists. */
- using type = type_list<>;
- };
- /**
- * @brief Concatenates multiple type lists.
- * @tparam Type Types provided by the first type list.
- * @tparam Other Types provided by the second type list.
- * @tparam List Other type lists, if any.
- */
- template<typename... Type, typename... Other, typename... List>
- struct type_list_cat<type_list<Type...>, type_list<Other...>, List...> {
- /*! @brief A type list composed by the types of all the type lists. */
- using type = typename type_list_cat<type_list<Type..., Other...>, List...>::type;
- };
- /**
- * @brief Concatenates multiple type lists.
- * @tparam Type Types provided by the type list.
- */
- template<typename... Type>
- struct type_list_cat<type_list<Type...>> {
- /*! @brief A type list composed by the types of all the type lists. */
- using type = type_list<Type...>;
- };
- /**
- * @brief Helper type.
- * @tparam List Type lists to concatenate.
- */
- template<typename... List>
- using type_list_cat_t = typename type_list_cat<List...>::type;
- /*! @cond TURN_OFF_DOXYGEN */
- namespace internal {
- template<typename...>
- struct type_list_unique;
- template<typename First, typename... Other, typename... Type>
- struct type_list_unique<type_list<First, Other...>, Type...>
- : std::conditional_t<(std::is_same_v<First, Type> || ...), type_list_unique<type_list<Other...>, Type...>, type_list_unique<type_list<Other...>, Type..., First>> {};
- template<typename... Type>
- struct type_list_unique<type_list<>, Type...> {
- using type = type_list<Type...>;
- };
- } // namespace internal
- /*! @endcond */
- /**
- * @brief Removes duplicates types from a type list.
- * @tparam List Type list.
- */
- template<typename List>
- struct type_list_unique {
- /*! @brief A type list without duplicate types. */
- using type = typename internal::type_list_unique<List>::type;
- };
- /**
- * @brief Helper type.
- * @tparam List Type list.
- */
- template<typename List>
- using type_list_unique_t = typename type_list_unique<List>::type;
- /**
- * @brief Provides the member constant `value` to true if a type list contains a
- * given type, false otherwise.
- * @tparam List Type list.
- * @tparam Type Type to look for.
- */
- template<typename List, typename Type>
- struct type_list_contains;
- /**
- * @copybrief type_list_contains
- * @tparam Type Types provided by the type list.
- * @tparam Other Type to look for.
- */
- template<typename... Type, typename Other>
- struct type_list_contains<type_list<Type...>, Other>
- : std::bool_constant<(std::is_same_v<Type, Other> || ...)> {};
- /**
- * @brief Helper variable template.
- * @tparam List Type list.
- * @tparam Type Type to look for.
- */
- template<typename List, typename Type>
- inline constexpr bool type_list_contains_v = type_list_contains<List, Type>::value;
- /*! @brief Primary template isn't defined on purpose. */
- template<typename...>
- struct type_list_diff;
- /**
- * @brief Computes the difference between two type lists.
- * @tparam Type Types provided by the first type list.
- * @tparam Other Types provided by the second type list.
- */
- template<typename... Type, typename... Other>
- struct type_list_diff<type_list<Type...>, type_list<Other...>> {
- /*! @brief A type list that is the difference between the two type lists. */
- using type = type_list_cat_t<std::conditional_t<type_list_contains_v<type_list<Other...>, Type>, type_list<>, type_list<Type>>...>;
- };
- /**
- * @brief Helper type.
- * @tparam List Type lists between which to compute the difference.
- */
- template<typename... List>
- using type_list_diff_t = typename type_list_diff<List...>::type;
- /*! @brief Primary template isn't defined on purpose. */
- template<typename, template<typename...> class>
- struct type_list_transform;
- /**
- * @brief Applies a given _function_ to a type list and generate a new list.
- * @tparam Type Types provided by the type list.
- * @tparam Op Unary operation as template class with a type member named `type`.
- */
- template<typename... Type, template<typename...> class Op>
- struct type_list_transform<type_list<Type...>, Op> {
- /*! @brief Resulting type list after applying the transform function. */
- // NOLINTNEXTLINE(modernize-type-traits)
- using type = type_list<typename Op<Type>::type...>;
- };
- /**
- * @brief Helper type.
- * @tparam List Type list.
- * @tparam Op Unary operation as template class with a type member named `type`.
- */
- template<typename List, template<typename...> class Op>
- using type_list_transform_t = typename type_list_transform<List, Op>::type;
- /**
- * @brief A class to use to push around lists of constant values, nothing more.
- * @tparam Value Values provided by the value list.
- */
- template<auto... Value>
- struct value_list {
- /*! @brief Value list type. */
- using type = value_list;
- /*! @brief Compile-time number of elements in the value list. */
- static constexpr auto size = sizeof...(Value);
- };
- /*! @brief Primary template isn't defined on purpose. */
- template<std::size_t, typename>
- struct value_list_element;
- /**
- * @brief Provides compile-time indexed access to the values of a value list.
- * @tparam Index Index of the value to return.
- * @tparam Value First value provided by the value list.
- * @tparam Other Other values provided by the value list.
- */
- template<std::size_t Index, auto Value, auto... Other>
- struct value_list_element<Index, value_list<Value, Other...>>
- : value_list_element<Index - 1u, value_list<Other...>> {};
- /**
- * @brief Provides compile-time indexed access to the types of a type list.
- * @tparam Value First value provided by the value list.
- * @tparam Other Other values provided by the value list.
- */
- template<auto Value, auto... Other>
- struct value_list_element<0u, value_list<Value, Other...>> {
- /*! @brief Searched type. */
- using type = decltype(Value);
- /*! @brief Searched value. */
- static constexpr auto value = Value;
- };
- /**
- * @brief Helper type.
- * @tparam Index Index of the type to return.
- * @tparam List Value list to search into.
- */
- template<std::size_t Index, typename List>
- using value_list_element_t = typename value_list_element<Index, List>::type;
- /**
- * @brief Helper type.
- * @tparam Index Index of the value to return.
- * @tparam List Value list to search into.
- */
- template<std::size_t Index, typename List>
- inline constexpr auto value_list_element_v = value_list_element<Index, List>::value;
- /*! @brief Primary template isn't defined on purpose. */
- template<auto, typename>
- struct value_list_index;
- /**
- * @brief Provides compile-time type access to the values of a value list.
- * @tparam Value Value to look for and for which to return the index.
- * @tparam First First value provided by the value list.
- * @tparam Other Other values provided by the value list.
- */
- template<auto Value, auto First, auto... Other>
- struct value_list_index<Value, value_list<First, Other...>> {
- /*! @brief Unsigned integer type. */
- using value_type = std::size_t;
- /*! @brief Compile-time position of the given value in the sublist. */
- static constexpr value_type value = 1u + value_list_index<Value, value_list<Other...>>::value;
- };
- /**
- * @brief Provides compile-time type access to the values of a value list.
- * @tparam Value Value to look for and for which to return the index.
- * @tparam Other Other values provided by the value list.
- */
- template<auto Value, auto... Other>
- struct value_list_index<Value, value_list<Value, Other...>> {
- static_assert(value_list_index<Value, value_list<Other...>>::value == sizeof...(Other), "Non-unique type");
- /*! @brief Unsigned integer type. */
- using value_type = std::size_t;
- /*! @brief Compile-time position of the given value in the sublist. */
- static constexpr value_type value = 0u;
- };
- /**
- * @brief Provides compile-time type access to the values of a value list.
- * @tparam Value Value to look for and for which to return the index.
- */
- template<auto Value>
- struct value_list_index<Value, value_list<>> {
- /*! @brief Unsigned integer type. */
- using value_type = std::size_t;
- /*! @brief Compile-time position of the given type in the sublist. */
- static constexpr value_type value = 0u;
- };
- /**
- * @brief Helper variable template.
- * @tparam List Value list.
- * @tparam Value Value to look for and for which to return the index.
- */
- template<auto Value, typename List>
- inline constexpr std::size_t value_list_index_v = value_list_index<Value, List>::value;
- /**
- * @brief Concatenates multiple value lists.
- * @tparam Value Values provided by the first value list.
- * @tparam Other Values provided by the second value list.
- * @return A value list composed by the values of both the value lists.
- */
- template<auto... Value, auto... Other>
- constexpr value_list<Value..., Other...> operator+(value_list<Value...>, value_list<Other...>) {
- return {};
- }
- /*! @brief Primary template isn't defined on purpose. */
- template<typename...>
- struct value_list_cat;
- /*! @brief Concatenates multiple value lists. */
- template<>
- struct value_list_cat<> {
- /*! @brief A value list composed by the values of all the value lists. */
- using type = value_list<>;
- };
- /**
- * @brief Concatenates multiple value lists.
- * @tparam Value Values provided by the first value list.
- * @tparam Other Values provided by the second value list.
- * @tparam List Other value lists, if any.
- */
- template<auto... Value, auto... Other, typename... List>
- struct value_list_cat<value_list<Value...>, value_list<Other...>, List...> {
- /*! @brief A value list composed by the values of all the value lists. */
- using type = typename value_list_cat<value_list<Value..., Other...>, List...>::type;
- };
- /**
- * @brief Concatenates multiple value lists.
- * @tparam Value Values provided by the value list.
- */
- template<auto... Value>
- struct value_list_cat<value_list<Value...>> {
- /*! @brief A value list composed by the values of all the value lists. */
- using type = value_list<Value...>;
- };
- /**
- * @brief Helper type.
- * @tparam List Value lists to concatenate.
- */
- template<typename... List>
- using value_list_cat_t = typename value_list_cat<List...>::type;
- /*! @brief Primary template isn't defined on purpose. */
- template<typename>
- struct value_list_unique;
- /**
- * @brief Removes duplicates values from a value list.
- * @tparam Value One of the values provided by the given value list.
- * @tparam Other The other values provided by the given value list.
- */
- template<auto Value, auto... Other>
- struct value_list_unique<value_list<Value, Other...>> {
- /*! @brief A value list without duplicate types. */
- using type = std::conditional_t<
- ((Value == Other) || ...),
- typename value_list_unique<value_list<Other...>>::type,
- value_list_cat_t<value_list<Value>, typename value_list_unique<value_list<Other...>>::type>>;
- };
- /*! @brief Removes duplicates values from a value list. */
- template<>
- struct value_list_unique<value_list<>> {
- /*! @brief A value list without duplicate types. */
- using type = value_list<>;
- };
- /**
- * @brief Helper type.
- * @tparam Type A value list.
- */
- template<typename Type>
- using value_list_unique_t = typename value_list_unique<Type>::type;
- /**
- * @brief Provides the member constant `value` to true if a value list contains
- * a given value, false otherwise.
- * @tparam List Value list.
- * @tparam Value Value to look for.
- */
- template<typename List, auto Value>
- struct value_list_contains;
- /**
- * @copybrief value_list_contains
- * @tparam Value Values provided by the value list.
- * @tparam Other Value to look for.
- */
- template<auto... Value, auto Other>
- struct value_list_contains<value_list<Value...>, Other>
- : std::bool_constant<((Value == Other) || ...)> {};
- /**
- * @brief Helper variable template.
- * @tparam List Value list.
- * @tparam Value Value to look for.
- */
- template<typename List, auto Value>
- inline constexpr bool value_list_contains_v = value_list_contains<List, Value>::value;
- /*! @brief Primary template isn't defined on purpose. */
- template<typename...>
- struct value_list_diff;
- /**
- * @brief Computes the difference between two value lists.
- * @tparam Value Values provided by the first value list.
- * @tparam Other Values provided by the second value list.
- */
- template<auto... Value, auto... Other>
- struct value_list_diff<value_list<Value...>, value_list<Other...>> {
- /*! @brief A value list that is the difference between the two value lists. */
- using type = value_list_cat_t<std::conditional_t<value_list_contains_v<value_list<Other...>, Value>, value_list<>, value_list<Value>>...>;
- };
- /**
- * @brief Helper type.
- * @tparam List Value lists between which to compute the difference.
- */
- template<typename... List>
- using value_list_diff_t = typename value_list_diff<List...>::type;
- /*! @brief Same as std::is_invocable, but with tuples. */
- template<typename, typename>
- struct is_applicable: std::false_type {};
- /**
- * @copybrief is_applicable
- * @tparam Func A valid function type.
- * @tparam Tuple Tuple-like type.
- * @tparam Args The list of arguments to use to probe the function type.
- */
- template<typename Func, template<typename...> class Tuple, typename... Args>
- struct is_applicable<Func, Tuple<Args...>>: std::is_invocable<Func, Args...> {};
- /**
- * @copybrief is_applicable
- * @tparam Func A valid function type.
- * @tparam Tuple Tuple-like type.
- * @tparam Args The list of arguments to use to probe the function type.
- */
- template<typename Func, template<typename...> class Tuple, typename... Args>
- struct is_applicable<Func, const Tuple<Args...>>: std::is_invocable<Func, Args...> {};
- /**
- * @brief Helper variable template.
- * @tparam Func A valid function type.
- * @tparam Args The list of arguments to use to probe the function type.
- */
- template<typename Func, typename Args>
- inline constexpr bool is_applicable_v = is_applicable<Func, Args>::value;
- /*! @brief Same as std::is_invocable_r, but with tuples for arguments. */
- template<typename, typename, typename>
- struct is_applicable_r: std::false_type {};
- /**
- * @copybrief is_applicable_r
- * @tparam Ret The type to which the return type of the function should be
- * convertible.
- * @tparam Func A valid function type.
- * @tparam Args The list of arguments to use to probe the function type.
- */
- template<typename Ret, typename Func, typename... Args>
- struct is_applicable_r<Ret, Func, std::tuple<Args...>>: std::is_invocable_r<Ret, Func, Args...> {};
- /**
- * @brief Helper variable template.
- * @tparam Ret The type to which the return type of the function should be
- * convertible.
- * @tparam Func A valid function type.
- * @tparam Args The list of arguments to use to probe the function type.
- */
- template<typename Ret, typename Func, typename Args>
- inline constexpr bool is_applicable_r_v = is_applicable_r<Ret, Func, Args>::value;
- /**
- * @brief Provides the member constant `value` to true if a given type is
- * complete, false otherwise.
- * @tparam Type The type to test.
- */
- template<typename Type, typename = void>
- struct is_complete: std::false_type {};
- /*! @copydoc is_complete */
- template<typename Type>
- struct is_complete<Type, std::void_t<decltype(sizeof(Type))>>: std::true_type {};
- /**
- * @brief Helper variable template.
- * @tparam Type The type to test.
- */
- template<typename Type>
- inline constexpr bool is_complete_v = is_complete<Type>::value;
- /**
- * @brief Provides the member constant `value` to true if a given type is an
- * iterator, false otherwise.
- * @tparam Type The type to test.
- */
- template<typename Type, typename = void>
- struct is_iterator: std::false_type {};
- /*! @cond TURN_OFF_DOXYGEN */
- namespace internal {
- template<typename, typename = void>
- struct has_iterator_category: std::false_type {};
- template<typename Type>
- struct has_iterator_category<Type, std::void_t<typename std::iterator_traits<Type>::iterator_category>>: std::true_type {};
- } // namespace internal
- /*! @endcond */
- /*! @copydoc is_iterator */
- template<typename Type>
- struct is_iterator<Type, std::enable_if_t<!std::is_void_v<std::remove_const_t<std::remove_pointer_t<Type>>>>>
- : internal::has_iterator_category<Type> {};
- /**
- * @brief Helper variable template.
- * @tparam Type The type to test.
- */
- template<typename Type>
- inline constexpr bool is_iterator_v = is_iterator<Type>::value;
- /**
- * @brief Provides the member constant `value` to true if a given type is both
- * an empty and non-final class, false otherwise.
- * @tparam Type The type to test
- */
- template<typename Type>
- struct is_ebco_eligible
- : std::bool_constant<std::is_empty_v<Type> && !std::is_final_v<Type>> {};
- /**
- * @brief Helper variable template.
- * @tparam Type The type to test.
- */
- template<typename Type>
- inline constexpr bool is_ebco_eligible_v = is_ebco_eligible<Type>::value;
- /**
- * @brief Provides the member constant `value` to true if `Type::is_transparent`
- * is valid and denotes a type, false otherwise.
- * @tparam Type The type to test.
- */
- template<typename Type, typename = void>
- struct is_transparent: std::false_type {};
- /*! @copydoc is_transparent */
- template<typename Type>
- struct is_transparent<Type, std::void_t<typename Type::is_transparent>>: std::true_type {};
- /**
- * @brief Helper variable template.
- * @tparam Type The type to test.
- */
- template<typename Type>
- inline constexpr bool is_transparent_v = is_transparent<Type>::value;
- /*! @cond TURN_OFF_DOXYGEN */
- namespace internal {
- template<typename, typename = void>
- struct has_tuple_size_value: std::false_type {};
- template<typename Type>
- struct has_tuple_size_value<Type, std::void_t<decltype(std::tuple_size<const Type>::value)>>: std::true_type {};
- template<typename, typename = void>
- struct has_value_type: std::false_type {};
- template<typename Type>
- struct has_value_type<Type, std::void_t<typename Type::value_type>>: std::true_type {};
- template<typename>
- [[nodiscard]] constexpr bool dispatch_is_equality_comparable();
- template<typename Type, std::size_t... Index>
- [[nodiscard]] constexpr bool unpack_maybe_equality_comparable(std::index_sequence<Index...>) {
- return (dispatch_is_equality_comparable<std::tuple_element_t<Index, Type>>() && ...);
- }
- template<typename>
- [[nodiscard]] constexpr bool maybe_equality_comparable(char) {
- return false;
- }
- template<typename Type>
- [[nodiscard]] constexpr auto maybe_equality_comparable(int) -> decltype(std::declval<Type>() == std::declval<Type>()) {
- return true;
- }
- template<typename Type>
- [[nodiscard]] constexpr bool dispatch_is_equality_comparable() {
- // NOLINTBEGIN(modernize-use-transparent-functors)
- if constexpr(std::is_array_v<Type>) {
- return false;
- } else if constexpr(is_complete_v<std::tuple_size<std::remove_const_t<Type>>>) {
- if constexpr(has_tuple_size_value<Type>::value) {
- return maybe_equality_comparable<Type>(0) && unpack_maybe_equality_comparable<Type>(std::make_index_sequence<std::tuple_size<Type>::value>{});
- } else {
- return maybe_equality_comparable<Type>(0);
- }
- } else if constexpr(has_value_type<Type>::value) {
- if constexpr(is_iterator_v<Type> || std::is_same_v<typename Type::value_type, Type> || dispatch_is_equality_comparable<typename Type::value_type>()) {
- return maybe_equality_comparable<Type>(0);
- } else {
- return false;
- }
- } else {
- return maybe_equality_comparable<Type>(0);
- }
- // NOLINTEND(modernize-use-transparent-functors)
- }
- } // namespace internal
- /*! @endcond */
- /**
- * @brief Provides the member constant `value` to true if a given type is
- * equality comparable, false otherwise.
- * @tparam Type The type to test.
- */
- template<typename Type>
- struct is_equality_comparable: std::bool_constant<internal::dispatch_is_equality_comparable<Type>()> {};
- /*! @copydoc is_equality_comparable */
- template<typename Type>
- struct is_equality_comparable<const Type>: is_equality_comparable<Type> {};
- /**
- * @brief Helper variable template.
- * @tparam Type The type to test.
- */
- template<typename Type>
- inline constexpr bool is_equality_comparable_v = is_equality_comparable<Type>::value;
- /**
- * @brief Transcribes the constness of a type to another type.
- * @tparam To The type to which to transcribe the constness.
- * @tparam From The type from which to transcribe the constness.
- */
- template<typename To, typename From>
- struct constness_as {
- /*! @brief The type resulting from the transcription of the constness. */
- using type = std::remove_const_t<To>;
- };
- /*! @copydoc constness_as */
- template<typename To, typename From>
- struct constness_as<To, const From> {
- /*! @brief The type resulting from the transcription of the constness. */
- using type = const To;
- };
- /**
- * @brief Alias template to facilitate the transcription of the constness.
- * @tparam To The type to which to transcribe the constness.
- * @tparam From The type from which to transcribe the constness.
- */
- template<typename To, typename From>
- using constness_as_t = typename constness_as<To, From>::type;
- /**
- * @brief Extracts the class of a non-static member object or function.
- * @tparam Member A pointer to a non-static member object or function.
- */
- template<typename Member>
- class member_class {
- static_assert(std::is_member_pointer_v<Member>, "Invalid pointer type to non-static member object or function");
- template<typename Class, typename Ret, typename... Args>
- static Class *clazz(Ret (Class::*)(Args...));
- template<typename Class, typename Ret, typename... Args>
- static Class *clazz(Ret (Class::*)(Args...) const);
- template<typename Class, typename Type>
- static Class *clazz(Type Class::*);
- public:
- /*! @brief The class of the given non-static member object or function. */
- using type = std::remove_pointer_t<decltype(clazz(std::declval<Member>()))>;
- };
- /**
- * @brief Helper type.
- * @tparam Member A pointer to a non-static member object or function.
- */
- template<typename Member>
- using member_class_t = typename member_class<Member>::type;
- /**
- * @brief Extracts the n-th argument of a _callable_ type.
- * @tparam Index The index of the argument to extract.
- * @tparam Candidate A valid _callable_ type.
- */
- template<std::size_t Index, typename Candidate>
- class nth_argument {
- template<typename Ret, typename... Args>
- static constexpr type_list<Args...> pick_up(Ret (*)(Args...));
- template<typename Ret, typename Class, typename... Args>
- static constexpr type_list<Args...> pick_up(Ret (Class ::*)(Args...));
- template<typename Ret, typename Class, typename... Args>
- static constexpr type_list<Args...> pick_up(Ret (Class ::*)(Args...) const);
- template<typename Type, typename Class>
- static constexpr type_list<Type> pick_up(Type Class ::*);
- template<typename Type>
- static constexpr decltype(pick_up(&Type::operator())) pick_up(Type &&);
- public:
- /*! @brief N-th argument of the _callable_ type. */
- using type = type_list_element_t<Index, decltype(pick_up(std::declval<Candidate>()))>;
- };
- /**
- * @brief Helper type.
- * @tparam Index The index of the argument to extract.
- * @tparam Candidate A valid function, member function or data member type.
- */
- template<std::size_t Index, typename Candidate>
- using nth_argument_t = typename nth_argument<Index, Candidate>::type;
- } // namespace entt
- template<typename... Type>
- struct std::tuple_size<entt::type_list<Type...>>: std::integral_constant<std::size_t, entt::type_list<Type...>::size> {};
- template<std::size_t Index, typename... Type>
- struct std::tuple_element<Index, entt::type_list<Type...>>: entt::type_list_element<Index, entt::type_list<Type...>> {};
- template<auto... Value>
- struct std::tuple_size<entt::value_list<Value...>>: std::integral_constant<std::size_t, entt::value_list<Value...>::size> {};
- template<std::size_t Index, auto... Value>
- struct std::tuple_element<Index, entt::value_list<Value...>>: entt::value_list_element<Index, entt::value_list<Value...>> {};
- #endif
- // #include "utility.hpp"
- namespace entt {
- /*! @cond TURN_OFF_DOXYGEN */
- namespace internal {
- enum class any_request : std::uint8_t {
- info,
- transfer,
- assign,
- compare,
- copy,
- move
- };
- template<std::size_t Len, std::size_t Align>
- struct basic_any_storage {
- static constexpr bool has_buffer = true;
- union {
- const void *instance{};
- // NOLINTNEXTLINE(cppcoreguidelines-avoid-c-arrays, modernize-avoid-c-arrays)
- alignas(Align) std::byte buffer[Len];
- };
- };
- template<std::size_t Align>
- struct basic_any_storage<0u, Align> {
- static constexpr bool has_buffer = false;
- const void *instance{};
- };
- template<typename Type, std::size_t Len, std::size_t Align>
- // NOLINTNEXTLINE(bugprone-sizeof-expression)
- struct in_situ: std::bool_constant<(Len != 0u) && alignof(Type) <= Align && sizeof(Type) <= Len && std::is_nothrow_move_constructible_v<Type>> {};
- template<std::size_t Len, std::size_t Align>
- struct in_situ<void, Len, Align>: std::false_type {};
- } // namespace internal
- /*! @endcond */
- /**
- * @brief A SBO friendly, type-safe container for single values of any type.
- * @tparam Len Size of the buffer reserved for the small buffer optimization.
- * @tparam Align Optional alignment requirement.
- */
- template<std::size_t Len, std::size_t Align>
- class basic_any: private internal::basic_any_storage<Len, Align> {
- using request = internal::any_request;
- using base_type = internal::basic_any_storage<Len, Align>;
- using vtable_type = const void *(const request, const basic_any &, const void *);
- using deleter_type = void(const basic_any &);
- template<typename Type>
- static constexpr bool in_situ_v = internal::in_situ<Type, Len, Align>::value;
- template<typename Type>
- static const void *basic_vtable(const request req, const basic_any &value, const void *other) {
- static_assert(std::is_same_v<std::remove_const_t<std::remove_reference_t<Type>>, Type>, "Invalid type");
- switch(const auto *elem = static_cast<const Type *>(value.data()); req) {
- case request::info:
- return &type_id<Type>();
- case request::transfer:
- if constexpr(std::is_move_assignable_v<Type>) {
- // NOLINTNEXTLINE(bugprone-casting-through-void)
- *const_cast<Type *>(elem) = std::move(*static_cast<Type *>(const_cast<void *>(other)));
- return other;
- }
- [[fallthrough]];
- case request::assign:
- if constexpr(std::is_copy_assignable_v<Type>) {
- *const_cast<Type *>(elem) = *static_cast<const Type *>(other);
- return other;
- }
- break;
- case request::compare:
- if constexpr(!std::is_function_v<Type> && !std::is_array_v<Type> && is_equality_comparable_v<Type>) {
- return (*elem == *static_cast<const Type *>(other)) ? other : nullptr;
- } else {
- return (elem == other) ? other : nullptr;
- }
- case request::copy:
- if constexpr(std::is_copy_constructible_v<Type>) {
- // NOLINTNEXTLINE(bugprone-casting-through-void)
- static_cast<basic_any *>(const_cast<void *>(other))->initialize<Type>(*elem);
- }
- break;
- case request::move:
- ENTT_ASSERT(value.mode == any_policy::embedded, "Unexpected policy");
- if constexpr(in_situ_v<Type>) {
- // NOLINTNEXTLINE(bugprone-casting-through-void, bugprone-multi-level-implicit-pointer-conversion)
- return ::new(&static_cast<basic_any *>(const_cast<void *>(other))->buffer) Type{std::move(*const_cast<Type *>(elem))};
- }
- }
- return nullptr;
- }
- template<typename Type>
- static void basic_deleter(const basic_any &value) {
- static_assert(std::is_same_v<std::remove_const_t<std::remove_reference_t<Type>>, Type>, "Invalid type");
- ENTT_ASSERT((value.mode == any_policy::dynamic) || ((value.mode == any_policy::embedded) && !std::is_trivially_destructible_v<Type>), "Unexpected policy");
- const auto *elem = static_cast<const Type *>(value.data());
- if constexpr(in_situ_v<Type>) {
- (value.mode == any_policy::embedded) ? elem->~Type() : (delete elem);
- } else if constexpr(std::is_array_v<Type>) {
- delete[] elem;
- } else {
- delete elem;
- }
- }
- template<typename Type, typename... Args>
- void initialize([[maybe_unused]] Args &&...args) {
- using plain_type = std::remove_const_t<std::remove_reference_t<Type>>;
- vtable = basic_vtable<plain_type>;
- underlying_type = type_hash<plain_type>::value();
- if constexpr(std::is_void_v<Type>) {
- deleter = nullptr;
- mode = any_policy::empty;
- this->instance = nullptr;
- } else if constexpr(std::is_lvalue_reference_v<Type>) {
- deleter = nullptr;
- mode = std::is_const_v<std::remove_reference_t<Type>> ? any_policy::cref : any_policy::ref;
- static_assert((std::is_lvalue_reference_v<Args> && ...) && (sizeof...(Args) == 1u), "Invalid arguments");
- // NOLINTNEXTLINE(bugprone-multi-level-implicit-pointer-conversion)
- this->instance = (std::addressof(args), ...);
- } else if constexpr(in_situ_v<plain_type>) {
- if constexpr(std::is_trivially_destructible_v<plain_type>) {
- deleter = nullptr;
- } else {
- deleter = &basic_deleter<plain_type>;
- }
- mode = any_policy::embedded;
- if constexpr(std::is_aggregate_v<plain_type> && (sizeof...(Args) != 0u || !std::is_default_constructible_v<plain_type>)) {
- ::new(&this->buffer) plain_type{std::forward<Args>(args)...};
- } else {
- // NOLINTNEXTLINE(cppcoreguidelines-pro-bounds-array-to-pointer-decay)
- ::new(&this->buffer) plain_type(std::forward<Args>(args)...);
- }
- } else {
- deleter = &basic_deleter<plain_type>;
- mode = any_policy::dynamic;
- if constexpr(std::is_aggregate_v<plain_type> && (sizeof...(Args) != 0u || !std::is_default_constructible_v<plain_type>)) {
- this->instance = new plain_type{std::forward<Args>(args)...};
- } else if constexpr(std::is_array_v<plain_type>) {
- static_assert(sizeof...(Args) == 0u, "Invalid arguments");
- this->instance = new plain_type[std::extent_v<plain_type>]();
- } else {
- this->instance = new plain_type(std::forward<Args>(args)...);
- }
- }
- }
- void invoke_deleter_if_exists() {
- if(deleter != nullptr) {
- deleter(*this);
- }
- }
- public:
- /*! @brief Size of the internal buffer. */
- static constexpr auto length = Len;
- /*! @brief Alignment requirement. */
- static constexpr auto alignment = Align;
- /*! @brief Default constructor. */
- constexpr basic_any() noexcept
- : basic_any{std::in_place_type<void>} {}
- /**
- * @brief Constructs a wrapper by directly initializing the new object.
- * @tparam Type Type of object to use to initialize the wrapper.
- * @tparam Args Types of arguments to use to construct the new instance.
- * @param args Parameters to use to construct the instance.
- */
- template<typename Type, typename... Args>
- explicit basic_any(std::in_place_type_t<Type>, Args &&...args)
- : base_type{} {
- initialize<Type>(std::forward<Args>(args)...);
- }
- /**
- * @brief Constructs a wrapper taking ownership of the passed object.
- * @tparam Type Type of object to use to initialize the wrapper.
- * @param value A pointer to an object to take ownership of.
- */
- template<typename Type>
- explicit basic_any(std::in_place_t, Type *value)
- : base_type{} {
- static_assert(!std::is_const_v<Type> && !std::is_void_v<Type>, "Non-const non-void pointer required");
- if(value == nullptr) {
- initialize<void>();
- } else {
- initialize<Type &>(*value);
- deleter = &basic_deleter<Type>;
- mode = any_policy::dynamic;
- }
- }
- /**
- * @brief Constructs a wrapper from a given value.
- * @tparam Type Type of object to use to initialize the wrapper.
- * @param value An instance of an object to use to initialize the wrapper.
- */
- template<typename Type, typename = std::enable_if_t<!std::is_same_v<std::decay_t<Type>, basic_any>>>
- basic_any(Type &&value)
- : basic_any{std::in_place_type<std::decay_t<Type>>, std::forward<Type>(value)} {}
- /**
- * @brief Copy constructor.
- * @param other The instance to copy from.
- */
- basic_any(const basic_any &other)
- : basic_any{} {
- other.vtable(request::copy, other, this);
- }
- /**
- * @brief Move constructor.
- * @param other The instance to move from.
- */
- basic_any(basic_any &&other) noexcept
- : base_type{},
- vtable{other.vtable},
- deleter{other.deleter},
- underlying_type{other.underlying_type},
- mode{other.mode} {
- if(other.mode == any_policy::embedded) {
- other.vtable(request::move, other, this);
- } else if(other.mode != any_policy::empty) {
- this->instance = std::exchange(other.instance, nullptr);
- }
- }
- /*! @brief Frees the internal buffer, whatever it means. */
- ~basic_any() {
- invoke_deleter_if_exists();
- }
- /**
- * @brief Copy assignment operator.
- * @param other The instance to copy from.
- * @return This any object.
- */
- basic_any &operator=(const basic_any &other) {
- if(this != &other) {
- invoke_deleter_if_exists();
- if(other) {
- other.vtable(request::copy, other, this);
- } else {
- initialize<void>();
- }
- }
- return *this;
- }
- /**
- * @brief Move assignment operator.
- * @param other The instance to move from.
- * @return This any object.
- */
- basic_any &operator=(basic_any &&other) noexcept {
- if(this != &other) {
- invoke_deleter_if_exists();
- if(other.mode == any_policy::embedded) {
- other.vtable(request::move, other, this);
- } else if(other.mode != any_policy::empty) {
- this->instance = std::exchange(other.instance, nullptr);
- }
- vtable = other.vtable;
- deleter = other.deleter;
- underlying_type = other.underlying_type;
- mode = other.mode;
- }
- return *this;
- }
- /**
- * @brief Value assignment operator.
- * @tparam Type Type of object to use to initialize the wrapper.
- * @param value An instance of an object to use to initialize the wrapper.
- * @return This any object.
- */
- template<typename Type, typename = std::enable_if_t<!std::is_same_v<std::decay_t<Type>, basic_any>>>
- basic_any &operator=(Type &&value) {
- emplace<std::decay_t<Type>>(std::forward<Type>(value));
- return *this;
- }
- /**
- * @brief Returns false if a wrapper is empty, true otherwise.
- * @return False if the wrapper is empty, true otherwise.
- */
- [[nodiscard]] bool has_value() const noexcept {
- return (mode != any_policy::empty);
- }
- /**
- * @brief Returns false if the wrapper does not contain the expected type,
- * true otherwise.
- * @param req Expected type.
- * @return False if the wrapper does not contain the expected type, true
- * otherwise.
- */
- [[nodiscard]] bool has_value(const type_info &req) const noexcept {
- return (underlying_type == req.hash());
- }
- /**
- * @brief Returns false if the wrapper does not contain the expected type,
- * true otherwise.
- * @tparam Type Expected type.
- * @return False if the wrapper does not contain the expected type, true
- * otherwise.
- */
- template<typename Type>
- [[nodiscard]] bool has_value() const noexcept {
- static_assert(std::is_same_v<std::remove_const_t<Type>, Type>, "Invalid type");
- return (underlying_type == type_hash<Type>::value());
- }
- /**
- * @brief Returns the object type info if any, `type_id<void>()` otherwise.
- * @return The object type info if any, `type_id<void>()` otherwise.
- */
- [[nodiscard]] const type_info &info() const noexcept {
- return *static_cast<const type_info *>(vtable(request::info, *this, nullptr));
- }
- /*! @copydoc info */
- [[deprecated("use ::info instead")]] [[nodiscard]] const type_info &type() const noexcept {
- return info();
- }
- /**
- * @brief Returns an opaque pointer to the contained instance.
- * @return An opaque pointer the contained instance, if any.
- */
- [[nodiscard]] const void *data() const noexcept {
- if constexpr(base_type::has_buffer) {
- return (mode == any_policy::embedded) ? &this->buffer : this->instance;
- } else {
- return this->instance;
- }
- }
- /**
- * @brief Returns an opaque pointer to the contained instance.
- * @param req Expected type.
- * @return An opaque pointer the contained instance, if any.
- */
- [[nodiscard]] const void *data(const type_info &req) const noexcept {
- return has_value(req) ? data() : nullptr;
- }
- /**
- * @brief Returns an opaque pointer to the contained instance.
- * @tparam Type Expected type.
- * @return An opaque pointer the contained instance, if any.
- */
- template<typename Type>
- [[nodiscard]] const Type *data() const noexcept {
- return has_value<std::remove_const_t<Type>>() ? static_cast<const Type *>(data()) : nullptr;
- }
- /**
- * @brief Returns an opaque pointer to the contained instance.
- * @return An opaque pointer the contained instance, if any.
- */
- [[nodiscard]] void *data() noexcept {
- return (mode == any_policy::cref) ? nullptr : const_cast<void *>(std::as_const(*this).data());
- }
- /**
- * @brief Returns an opaque pointer to the contained instance.
- * @param req Expected type.
- * @return An opaque pointer the contained instance, if any.
- */
- [[nodiscard]] void *data(const type_info &req) noexcept {
- return (mode == any_policy::cref) ? nullptr : const_cast<void *>(std::as_const(*this).data(req));
- }
- /**
- * @brief Returns an opaque pointer to the contained instance.
- * @tparam Type Expected type.
- * @return An opaque pointer the contained instance, if any.
- */
- template<typename Type>
- [[nodiscard]] Type *data() noexcept {
- if constexpr(std::is_const_v<Type>) {
- return std::as_const(*this).template data<std::remove_const_t<Type>>();
- } else {
- return (mode == any_policy::cref) ? nullptr : const_cast<Type *>(std::as_const(*this).template data<std::remove_const_t<Type>>());
- }
- }
- /**
- * @brief Replaces the contained object by creating a new instance directly.
- * @tparam Type Type of object to use to initialize the wrapper.
- * @tparam Args Types of arguments to use to construct the new instance.
- * @param args Parameters to use to construct the instance.
- */
- template<typename Type, typename... Args>
- void emplace(Args &&...args) {
- invoke_deleter_if_exists();
- initialize<Type>(std::forward<Args>(args)...);
- }
- /**
- * @brief Assigns a value to the contained object without replacing it.
- * @param other The value to assign to the contained object.
- * @return True in case of success, false otherwise.
- */
- bool assign(const basic_any &other) {
- if(other && (mode != any_policy::cref) && (underlying_type == other.underlying_type)) {
- return (vtable(request::assign, *this, other.data()) != nullptr);
- }
- return false;
- }
- /*! @copydoc assign */
- // NOLINTNEXTLINE(cppcoreguidelines-rvalue-reference-param-not-moved)
- bool assign(basic_any &&other) {
- if(other && (mode != any_policy::cref) && (underlying_type == other.underlying_type)) {
- return (other.mode == any_policy::cref) ? (vtable(request::assign, *this, std::as_const(other).data()) != nullptr) : (vtable(request::transfer, *this, other.data()) != nullptr);
- }
- return false;
- }
- /*! @brief Destroys contained object */
- void reset() {
- invoke_deleter_if_exists();
- initialize<void>();
- }
- /**
- * @brief Returns false if a wrapper is empty, true otherwise.
- * @return False if the wrapper is empty, true otherwise.
- */
- [[nodiscard]] explicit operator bool() const noexcept {
- return has_value();
- }
- /**
- * @brief Checks if two wrappers differ in their content.
- * @param other Wrapper with which to compare.
- * @return False if the two objects differ in their content, true otherwise.
- */
- [[nodiscard]] bool operator==(const basic_any &other) const noexcept {
- if(other && (underlying_type == other.underlying_type)) {
- return (vtable(request::compare, *this, other.data()) != nullptr);
- }
- return (!*this && !other);
- }
- /**
- * @brief Checks if two wrappers differ in their content.
- * @param other Wrapper with which to compare.
- * @return True if the two objects differ in their content, false otherwise.
- */
- [[nodiscard]] bool operator!=(const basic_any &other) const noexcept {
- return !(*this == other);
- }
- /**
- * @brief Aliasing constructor.
- * @return A wrapper that shares a reference to an unmanaged object.
- */
- [[nodiscard]] basic_any as_ref() noexcept {
- basic_any other = std::as_const(*this).as_ref();
- other.mode = (mode == any_policy::cref ? any_policy::cref : any_policy::ref);
- return other;
- }
- /*! @copydoc as_ref */
- [[nodiscard]] basic_any as_ref() const noexcept {
- basic_any other{};
- other.instance = data();
- other.vtable = vtable;
- other.underlying_type = underlying_type;
- other.mode = any_policy::cref;
- return other;
- }
- /**
- * @brief Returns true if a wrapper owns its object, false otherwise.
- * @return True if the wrapper owns its object, false otherwise.
- */
- [[nodiscard]] bool owner() const noexcept {
- return (mode == any_policy::dynamic || mode == any_policy::embedded);
- }
- /**
- * @brief Returns the current mode of an any object.
- * @return The current mode of the any object.
- */
- [[nodiscard]] any_policy policy() const noexcept {
- return mode;
- }
- private:
- vtable_type *vtable{};
- deleter_type *deleter{};
- id_type underlying_type{};
- any_policy mode{};
- };
- /**
- * @brief Performs type-safe access to the contained object.
- * @tparam Type Type to which conversion is required.
- * @tparam Len Size of the buffer reserved for the small buffer optimization.
- * @tparam Align Alignment requirement.
- * @param data Target any object.
- * @return The element converted to the requested type.
- */
- template<typename Type, std::size_t Len, std::size_t Align>
- [[nodiscard]] std::remove_const_t<Type> any_cast(const basic_any<Len, Align> &data) noexcept {
- const auto *const instance = any_cast<std::remove_reference_t<Type>>(&data);
- ENTT_ASSERT(instance, "Invalid instance");
- return static_cast<Type>(*instance);
- }
- /*! @copydoc any_cast */
- template<typename Type, std::size_t Len, std::size_t Align>
- [[nodiscard]] std::remove_const_t<Type> any_cast(basic_any<Len, Align> &data) noexcept {
- // forces const on non-reference types to make them work also with wrappers for const references
- auto *const instance = any_cast<std::remove_reference_t<const Type>>(&data);
- ENTT_ASSERT(instance, "Invalid instance");
- return static_cast<Type>(*instance);
- }
- /*! @copydoc any_cast */
- template<typename Type, std::size_t Len, std::size_t Align>
- // NOLINTNEXTLINE(cppcoreguidelines-rvalue-reference-param-not-moved)
- [[nodiscard]] std::remove_const_t<Type> any_cast(basic_any<Len, Align> &&data) noexcept {
- if constexpr(std::is_copy_constructible_v<std::remove_const_t<std::remove_reference_t<Type>>>) {
- if(auto *const instance = any_cast<std::remove_reference_t<Type>>(&data); instance) {
- return static_cast<Type>(std::move(*instance));
- }
- return any_cast<Type>(data);
- } else {
- auto *const instance = any_cast<std::remove_reference_t<Type>>(&data);
- ENTT_ASSERT(instance, "Invalid instance");
- return static_cast<Type>(std::move(*instance));
- }
- }
- /*! @copydoc any_cast */
- template<typename Type, std::size_t Len, std::size_t Align>
- [[nodiscard]] const Type *any_cast(const basic_any<Len, Align> *data) noexcept {
- return data->template data<std::remove_const_t<Type>>();
- }
- /*! @copydoc any_cast */
- template<typename Type, std::size_t Len, std::size_t Align>
- [[nodiscard]] Type *any_cast(basic_any<Len, Align> *data) noexcept {
- if constexpr(std::is_const_v<Type>) {
- // last attempt to make wrappers for const references return their values
- return any_cast<Type>(&std::as_const(*data));
- } else {
- return data->template data<Type>();
- }
- }
- /**
- * @brief Constructs a wrapper from a given type, passing it all arguments.
- * @tparam Type Type of object to use to initialize the wrapper.
- * @tparam Len Size of the buffer reserved for the small buffer optimization.
- * @tparam Align Optional alignment requirement.
- * @tparam Args Types of arguments to use to construct the new instance.
- * @param args Parameters to use to construct the instance.
- * @return A properly initialized wrapper for an object of the given type.
- */
- template<typename Type, std::size_t Len = basic_any<>::length, std::size_t Align = basic_any<Len>::alignment, typename... Args>
- [[nodiscard]] basic_any<Len, Align> make_any(Args &&...args) {
- return basic_any<Len, Align>{std::in_place_type<Type>, std::forward<Args>(args)...};
- }
- /**
- * @brief Forwards its argument and avoids copies for lvalue references.
- * @tparam Len Size of the buffer reserved for the small buffer optimization.
- * @tparam Align Optional alignment requirement.
- * @tparam Type Type of argument to use to construct the new instance.
- * @param value Parameter to use to construct the instance.
- * @return A properly initialized and not necessarily owning wrapper.
- */
- template<std::size_t Len = basic_any<>::length, std::size_t Align = basic_any<Len>::alignment, typename Type>
- [[nodiscard]] basic_any<Len, Align> forward_as_any(Type &&value) {
- return basic_any<Len, Align>{std::in_place_type<Type &&>, std::forward<Type>(value)};
- }
- } // namespace entt
- #endif
- // #include "../core/bit.hpp"
- // #include "../core/type_info.hpp"
- // #include "entity.hpp"
- // #include "fwd.hpp"
- namespace entt {
- /*! @cond TURN_OFF_DOXYGEN */
- namespace internal {
- template<typename Container>
- struct sparse_set_iterator final {
- using value_type = typename Container::value_type;
- using pointer = typename Container::const_pointer;
- using reference = typename Container::const_reference;
- using difference_type = typename Container::difference_type;
- using iterator_category = std::random_access_iterator_tag;
- constexpr sparse_set_iterator() noexcept
- : packed{},
- offset{} {}
- constexpr sparse_set_iterator(const Container &ref, const difference_type idx) noexcept
- : packed{&ref},
- offset{idx} {}
- constexpr sparse_set_iterator &operator++() noexcept {
- return --offset, *this;
- }
- constexpr sparse_set_iterator operator++(int) noexcept {
- const sparse_set_iterator orig = *this;
- return ++(*this), orig;
- }
- constexpr sparse_set_iterator &operator--() noexcept {
- return ++offset, *this;
- }
- constexpr sparse_set_iterator operator--(int) noexcept {
- const sparse_set_iterator orig = *this;
- return operator--(), orig;
- }
- constexpr sparse_set_iterator &operator+=(const difference_type value) noexcept {
- offset -= value;
- return *this;
- }
- constexpr sparse_set_iterator operator+(const difference_type value) const noexcept {
- sparse_set_iterator copy = *this;
- return (copy += value);
- }
- constexpr sparse_set_iterator &operator-=(const difference_type value) noexcept {
- return (*this += -value);
- }
- constexpr sparse_set_iterator operator-(const difference_type value) const noexcept {
- return (*this + -value);
- }
- [[nodiscard]] constexpr reference operator[](const difference_type value) const noexcept {
- return (*packed)[static_cast<typename Container::size_type>(index() - value)];
- }
- [[nodiscard]] constexpr pointer operator->() const noexcept {
- return std::addressof(operator[](0));
- }
- [[nodiscard]] constexpr reference operator*() const noexcept {
- return operator[](0);
- }
- [[nodiscard]] constexpr pointer data() const noexcept {
- return packed ? packed->data() : nullptr;
- }
- [[nodiscard]] constexpr difference_type index() const noexcept {
- return offset - 1;
- }
- private:
- const Container *packed;
- difference_type offset;
- };
- template<typename Container>
- [[nodiscard]] constexpr std::ptrdiff_t operator-(const sparse_set_iterator<Container> &lhs, const sparse_set_iterator<Container> &rhs) noexcept {
- return rhs.index() - lhs.index();
- }
- template<typename Container>
- [[nodiscard]] constexpr bool operator==(const sparse_set_iterator<Container> &lhs, const sparse_set_iterator<Container> &rhs) noexcept {
- return lhs.index() == rhs.index();
- }
- template<typename Container>
- [[nodiscard]] constexpr bool operator!=(const sparse_set_iterator<Container> &lhs, const sparse_set_iterator<Container> &rhs) noexcept {
- return !(lhs == rhs);
- }
- template<typename Container>
- [[nodiscard]] constexpr bool operator<(const sparse_set_iterator<Container> &lhs, const sparse_set_iterator<Container> &rhs) noexcept {
- return lhs.index() > rhs.index();
- }
- template<typename Container>
- [[nodiscard]] constexpr bool operator>(const sparse_set_iterator<Container> &lhs, const sparse_set_iterator<Container> &rhs) noexcept {
- return rhs < lhs;
- }
- template<typename Container>
- [[nodiscard]] constexpr bool operator<=(const sparse_set_iterator<Container> &lhs, const sparse_set_iterator<Container> &rhs) noexcept {
- return !(lhs > rhs);
- }
- template<typename Container>
- [[nodiscard]] constexpr bool operator>=(const sparse_set_iterator<Container> &lhs, const sparse_set_iterator<Container> &rhs) noexcept {
- return !(lhs < rhs);
- }
- } // namespace internal
- /*! @endcond */
- /**
- * @brief Sparse set implementation.
- *
- * Sparse set or packed array or whatever is the name users give it.<br/>
- * Two arrays: an _external_ one and an _internal_ one; a _sparse_ one and a
- * _packed_ one; one used for direct access through contiguous memory, the other
- * one used to get the data through an extra level of indirection.<br/>
- * This type of data structure is widely documented in the literature and on the
- * web. This is nothing more than a customized implementation suitable for the
- * purpose of the framework.
- *
- * @note
- * Internal data structures arrange elements to maximize performance. There are
- * no guarantees that entities are returned in the insertion order when iterate
- * a sparse set. Do not make assumption on the order in any case.
- *
- * @tparam Entity A valid entity type.
- * @tparam Allocator Type of allocator used to manage memory and elements.
- */
- template<typename Entity, typename Allocator>
- class basic_sparse_set {
- using alloc_traits = std::allocator_traits<Allocator>;
- static_assert(std::is_same_v<typename alloc_traits::value_type, Entity>, "Invalid value type");
- using sparse_container_type = std::vector<typename alloc_traits::pointer, typename alloc_traits::template rebind_alloc<typename alloc_traits::pointer>>;
- using packed_container_type = std::vector<Entity, Allocator>;
- using traits_type = entt_traits<Entity>;
- static constexpr auto max_size = static_cast<std::size_t>(traits_type::to_entity(null));
- // it could be auto but gcc complains and emits a warning due to a false positive
- [[nodiscard]] std::size_t policy_to_head() const noexcept {
- return static_cast<size_type>(max_size * static_cast<std::remove_const_t<decltype(max_size)>>(mode != deletion_policy::swap_only));
- }
- [[nodiscard]] auto entity_to_pos(const Entity entt) const noexcept {
- return static_cast<size_type>(traits_type::to_entity(entt));
- }
- [[nodiscard]] auto pos_to_page(const std::size_t pos) const noexcept {
- return static_cast<size_type>(pos / traits_type::page_size);
- }
- [[nodiscard]] auto sparse_ptr(const Entity entt) const {
- const auto pos = entity_to_pos(entt);
- const auto page = pos_to_page(pos);
- return (page < sparse.size() && sparse[page]) ? (sparse[page] + fast_mod(pos, traits_type::page_size)) : nullptr;
- }
- [[nodiscard]] auto &sparse_ref(const Entity entt) const {
- ENTT_ASSERT(sparse_ptr(entt), "Invalid element");
- const auto pos = entity_to_pos(entt);
- return sparse[pos_to_page(pos)][fast_mod(pos, traits_type::page_size)];
- }
- [[nodiscard]] auto to_iterator(const Entity entt) const {
- return --(end() - static_cast<difference_type>(index(entt)));
- }
- [[nodiscard]] auto &assure_at_least(const Entity entt) {
- const auto pos = entity_to_pos(entt);
- const auto page = pos_to_page(pos);
- if(!(page < sparse.size())) {
- sparse.resize(page + 1u, nullptr);
- }
- if(!sparse[page]) {
- constexpr entity_type init = null;
- auto page_allocator{packed.get_allocator()};
- sparse[page] = alloc_traits::allocate(page_allocator, traits_type::page_size);
- std::uninitialized_fill(sparse[page], sparse[page] + traits_type::page_size, init);
- }
- return sparse[page][fast_mod(pos, traits_type::page_size)];
- }
- void release_sparse_pages() {
- auto page_allocator{packed.get_allocator()};
- for(auto &&page: sparse) {
- if(page != nullptr) {
- std::destroy(page, page + traits_type::page_size);
- alloc_traits::deallocate(page_allocator, page, traits_type::page_size);
- page = nullptr;
- }
- }
- }
- void swap_at(const std::size_t lhs, const std::size_t rhs) {
- auto &from = packed[lhs];
- auto &to = packed[rhs];
- sparse_ref(from) = traits_type::combine(static_cast<typename traits_type::entity_type>(rhs), traits_type::to_integral(from));
- sparse_ref(to) = traits_type::combine(static_cast<typename traits_type::entity_type>(lhs), traits_type::to_integral(to));
- std::swap(from, to);
- }
- private:
- [[nodiscard]] virtual const void *get_at(const std::size_t) const {
- return nullptr;
- }
- virtual void swap_or_move([[maybe_unused]] const std::size_t lhs, [[maybe_unused]] const std::size_t rhs) {
- ENTT_ASSERT((mode != deletion_policy::swap_only) || ((lhs < head) == (rhs < head)), "Cross swapping is not supported");
- }
- protected:
- /*! @brief Random access iterator type. */
- using basic_iterator = internal::sparse_set_iterator<packed_container_type>;
- /**
- * @brief Erases an entity from a sparse set.
- * @param it An iterator to the element to pop.
- */
- void swap_only(const basic_iterator it) {
- ENTT_ASSERT(mode == deletion_policy::swap_only, "Deletion policy mismatch");
- const auto pos = index(*it);
- bump(traits_type::next(*it));
- swap_at(pos, head -= (pos < head));
- }
- /**
- * @brief Erases an entity from a sparse set.
- * @param it An iterator to the element to pop.
- */
- void swap_and_pop(const basic_iterator it) {
- ENTT_ASSERT(mode == deletion_policy::swap_and_pop, "Deletion policy mismatch");
- auto &self = sparse_ref(*it);
- const auto entt = traits_type::to_entity(self);
- sparse_ref(packed.back()) = traits_type::combine(entt, traits_type::to_integral(packed.back()));
- packed[static_cast<size_type>(entt)] = packed.back();
- // unnecessary but it helps to detect nasty bugs
- // NOLINTNEXTLINE(bugprone-assert-side-effect)
- ENTT_ASSERT((packed.back() = null, true), "");
- // lazy self-assignment guard
- self = null;
- packed.pop_back();
- }
- /**
- * @brief Erases an entity from a sparse set.
- * @param it An iterator to the element to pop.
- */
- void in_place_pop(const basic_iterator it) {
- ENTT_ASSERT(mode == deletion_policy::in_place, "Deletion policy mismatch");
- const auto pos = entity_to_pos(std::exchange(sparse_ref(*it), null));
- packed[pos] = traits_type::combine(static_cast<typename traits_type::entity_type>(std::exchange(head, pos)), tombstone);
- }
- /**
- * @brief Erases entities from a sparse set.
- * @param first An iterator to the first element of the range of entities.
- * @param last An iterator past the last element of the range of entities.
- */
- virtual void pop(basic_iterator first, basic_iterator last) {
- switch(mode) {
- case deletion_policy::swap_and_pop:
- for(; first != last; ++first) {
- swap_and_pop(first);
- }
- break;
- case deletion_policy::in_place:
- for(; first != last; ++first) {
- in_place_pop(first);
- }
- break;
- case deletion_policy::swap_only:
- for(; first != last; ++first) {
- swap_only(first);
- }
- break;
- }
- }
- /*! @brief Erases all entities of a sparse set. */
- virtual void pop_all() {
- switch(mode) {
- case deletion_policy::in_place:
- if(head != max_size) {
- for(auto &&elem: packed) {
- if(elem != tombstone) {
- sparse_ref(elem) = null;
- }
- }
- break;
- }
- [[fallthrough]];
- case deletion_policy::swap_only:
- case deletion_policy::swap_and_pop:
- for(auto &&elem: packed) {
- sparse_ref(elem) = null;
- }
- break;
- }
- head = policy_to_head();
- packed.clear();
- }
- /**
- * @brief Assigns an entity to a sparse set.
- * @param entt A valid identifier.
- * @param force_back Force back insertion.
- * @return Iterator pointing to the emplaced element.
- */
- virtual basic_iterator try_emplace(const Entity entt, const bool force_back, const void * = nullptr) {
- ENTT_ASSERT(entt != null && entt != tombstone, "Invalid element");
- auto &elem = assure_at_least(entt);
- auto pos = size();
- switch(mode) {
- case deletion_policy::in_place:
- if(head != max_size && !force_back) {
- pos = head;
- ENTT_ASSERT(elem == null, "Slot not available");
- elem = traits_type::combine(static_cast<typename traits_type::entity_type>(head), traits_type::to_integral(entt));
- head = entity_to_pos(std::exchange(packed[pos], entt));
- break;
- }
- [[fallthrough]];
- case deletion_policy::swap_and_pop:
- packed.push_back(entt);
- ENTT_ASSERT(elem == null, "Slot not available");
- elem = traits_type::combine(static_cast<typename traits_type::entity_type>(packed.size() - 1u), traits_type::to_integral(entt));
- break;
- case deletion_policy::swap_only:
- if(elem == null) {
- packed.push_back(entt);
- elem = traits_type::combine(static_cast<typename traits_type::entity_type>(packed.size() - 1u), traits_type::to_integral(entt));
- } else {
- ENTT_ASSERT(!(entity_to_pos(elem) < head), "Slot not available");
- bump(entt);
- }
- pos = head++;
- swap_at(entity_to_pos(elem), pos);
- break;
- }
- return iterator{packed, static_cast<difference_type>(++pos)};
- }
- /*! @brief Forwards variables to derived classes, if any. */
- // NOLINTNEXTLINE(performance-unnecessary-value-param)
- virtual void bind_any(any) noexcept {}
- public:
- /*! @brief Allocator type. */
- using allocator_type = Allocator;
- /*! @brief Underlying entity identifier. */
- using entity_type = typename traits_type::value_type;
- /*! @brief Underlying version type. */
- using version_type = typename traits_type::version_type;
- /*! @brief Unsigned integer type. */
- using size_type = std::size_t;
- /*! @brief Signed integer type. */
- using difference_type = std::ptrdiff_t;
- /*! @brief Pointer type to contained entities. */
- using pointer = typename packed_container_type::const_pointer;
- /*! @brief Random access iterator type. */
- using iterator = basic_iterator;
- /*! @brief Constant random access iterator type. */
- using const_iterator = iterator;
- /*! @brief Reverse iterator type. */
- using reverse_iterator = std::reverse_iterator<iterator>;
- /*! @brief Constant reverse iterator type. */
- using const_reverse_iterator = std::reverse_iterator<const_iterator>;
- /*! @brief Default constructor. */
- basic_sparse_set()
- : basic_sparse_set{type_id<void>()} {}
- /**
- * @brief Constructs an empty container with a given allocator.
- * @param allocator The allocator to use.
- */
- explicit basic_sparse_set(const allocator_type &allocator)
- : basic_sparse_set{deletion_policy::swap_and_pop, allocator} {}
- /**
- * @brief Constructs an empty container with the given policy and allocator.
- * @param pol Type of deletion policy.
- * @param allocator The allocator to use (possibly default-constructed).
- */
- explicit basic_sparse_set(deletion_policy pol, const allocator_type &allocator = {})
- : basic_sparse_set{type_id<void>(), pol, allocator} {}
- /**
- * @brief Constructs an empty container with the given value type, policy
- * and allocator.
- * @param elem Returned value type, if any.
- * @param pol Type of deletion policy.
- * @param allocator The allocator to use (possibly default-constructed).
- */
- explicit basic_sparse_set(const type_info &elem, deletion_policy pol = deletion_policy::swap_and_pop, const allocator_type &allocator = {})
- : sparse{allocator},
- packed{allocator},
- descriptor{&elem},
- mode{pol},
- head{policy_to_head()} {
- ENTT_ASSERT(traits_type::version_mask || mode != deletion_policy::in_place, "Policy does not support zero-sized versions");
- }
- /*! @brief Default copy constructor, deleted on purpose. */
- basic_sparse_set(const basic_sparse_set &) = delete;
- /**
- * @brief Move constructor.
- * @param other The instance to move from.
- */
- basic_sparse_set(basic_sparse_set &&other) noexcept
- : sparse{std::move(other.sparse)},
- packed{std::move(other.packed)},
- descriptor{other.descriptor},
- mode{other.mode},
- head{std::exchange(other.head, policy_to_head())} {}
- /**
- * @brief Allocator-extended move constructor.
- * @param other The instance to move from.
- * @param allocator The allocator to use.
- */
- basic_sparse_set(basic_sparse_set &&other, const allocator_type &allocator)
- : sparse{std::move(other.sparse), allocator},
- packed{std::move(other.packed), allocator},
- descriptor{other.descriptor},
- mode{other.mode},
- head{std::exchange(other.head, policy_to_head())} {
- ENTT_ASSERT(alloc_traits::is_always_equal::value || get_allocator() == other.get_allocator(), "Copying a sparse set is not allowed");
- }
- /*! @brief Default destructor. */
- virtual ~basic_sparse_set() {
- release_sparse_pages();
- }
- /**
- * @brief Default copy assignment operator, deleted on purpose.
- * @return This sparse set.
- */
- basic_sparse_set &operator=(const basic_sparse_set &) = delete;
- /**
- * @brief Move assignment operator.
- * @param other The instance to move from.
- * @return This sparse set.
- */
- basic_sparse_set &operator=(basic_sparse_set &&other) noexcept {
- ENTT_ASSERT(alloc_traits::is_always_equal::value || get_allocator() == other.get_allocator(), "Copying a sparse set is not allowed");
- swap(other);
- return *this;
- }
- /**
- * @brief Exchanges the contents with those of a given sparse set.
- * @param other Sparse set to exchange the content with.
- */
- void swap(basic_sparse_set &other) noexcept {
- using std::swap;
- swap(sparse, other.sparse);
- swap(packed, other.packed);
- swap(descriptor, other.descriptor);
- swap(mode, other.mode);
- swap(head, other.head);
- }
- /**
- * @brief Returns the associated allocator.
- * @return The associated allocator.
- */
- [[nodiscard]] constexpr allocator_type get_allocator() const noexcept {
- return packed.get_allocator();
- }
- /**
- * @brief Returns the deletion policy of a sparse set.
- * @return The deletion policy of the sparse set.
- */
- [[nodiscard]] deletion_policy policy() const noexcept {
- return mode;
- }
- /**
- * @brief Returns data on the free list whose meaning depends on the mode.
- * @return Free list information that is mode dependent.
- */
- [[nodiscard]] size_type free_list() const noexcept {
- return head;
- }
- /**
- * @brief Sets data on the free list whose meaning depends on the mode.
- * @param value Free list information that is mode dependent.
- */
- void free_list(const size_type value) noexcept {
- ENTT_ASSERT((mode == deletion_policy::swap_only) && !(value > packed.size()), "Invalid value");
- head = value;
- }
- /**
- * @brief Increases the capacity of a sparse set.
- *
- * If the new capacity is greater than the current capacity, new storage is
- * allocated, otherwise the method does nothing.
- *
- * @param cap Desired capacity.
- */
- virtual void reserve(const size_type cap) {
- packed.reserve(cap);
- }
- /**
- * @brief Returns the number of elements that a sparse set has currently
- * allocated space for.
- * @return Capacity of the sparse set.
- */
- [[nodiscard]] virtual size_type capacity() const noexcept {
- return packed.capacity();
- }
- /*! @brief Requests the removal of unused capacity. */
- virtual void shrink_to_fit() {
- sparse_container_type other{sparse.get_allocator()};
- const auto len = sparse.size();
- size_type cnt{};
- other.reserve(len);
- for(auto &&elem: std::as_const(packed)) {
- if(elem != tombstone) {
- if(const auto page = pos_to_page(entity_to_pos(elem)); sparse[page] != nullptr) {
- if(const auto sz = page + 1u; sz > other.size()) {
- other.resize(sz, nullptr);
- }
- other[page] = std::exchange(sparse[page], nullptr);
- if(++cnt == len) {
- // early exit due to lack of pages
- break;
- }
- }
- }
- }
- release_sparse_pages();
- sparse.swap(other);
- sparse.shrink_to_fit();
- packed.shrink_to_fit();
- }
- /**
- * @brief Returns the extent of a sparse set.
- *
- * The extent of a sparse set is also the size of the internal sparse array.
- * There is no guarantee that all pages have been allocated, nor that the
- * internal packed array is be the same size.
- *
- * @return Extent of the sparse set.
- */
- [[nodiscard]] size_type extent() const noexcept {
- return sparse.size() * traits_type::page_size;
- }
- /**
- * @brief Returns the number of elements in a sparse set.
- *
- * The number of elements is also the size of the internal packed array.
- * There is no guarantee that the internal sparse array has the same size.
- * Usually the size of the internal sparse array is equal or greater than
- * the one of the internal packed array.
- *
- * @return Number of elements.
- */
- [[nodiscard]] size_type size() const noexcept {
- return packed.size();
- }
- /**
- * @brief Checks whether a sparse set is empty.
- * @return True if the sparse set is empty, false otherwise.
- */
- [[nodiscard]] bool empty() const noexcept {
- return packed.empty();
- }
- /**
- * @brief Checks whether a sparse set is fully packed.
- * @return True if the sparse set is fully packed, false otherwise.
- */
- [[nodiscard]] bool contiguous() const noexcept {
- return (mode != deletion_policy::in_place) || (head == max_size);
- }
- /**
- * @brief Direct access to the internal packed array.
- * @return A pointer to the internal packed array.
- */
- [[nodiscard]] pointer data() const noexcept {
- return packed.data();
- }
- /**
- * @brief Returns an iterator to the beginning.
- *
- * If the sparse set is empty, the returned iterator will be equal to
- * `end()`.
- *
- * @return An iterator to the first entity of the sparse set.
- */
- [[nodiscard]] iterator begin() const noexcept {
- const auto pos = static_cast<difference_type>(packed.size());
- return iterator{packed, pos};
- }
- /*! @copydoc begin */
- [[nodiscard]] const_iterator cbegin() const noexcept {
- return begin();
- }
- /**
- * @brief Returns an iterator to the end.
- * @return An iterator to the element following the last entity of a sparse
- * set.
- */
- [[nodiscard]] iterator end() const noexcept {
- return iterator{packed, {}};
- }
- /*! @copydoc end */
- [[nodiscard]] const_iterator cend() const noexcept {
- return end();
- }
- /**
- * @brief Returns a reverse iterator to the beginning.
- *
- * If the sparse set is empty, the returned iterator will be equal to
- * `rend()`.
- *
- * @return An iterator to the first entity of the reversed internal packed
- * array.
- */
- [[nodiscard]] reverse_iterator rbegin() const noexcept {
- return std::make_reverse_iterator(end());
- }
- /*! @copydoc rbegin */
- [[nodiscard]] const_reverse_iterator crbegin() const noexcept {
- return rbegin();
- }
- /**
- * @brief Returns a reverse iterator to the end.
- * @return An iterator to the element following the last entity of the
- * reversed sparse set.
- */
- [[nodiscard]] reverse_iterator rend() const noexcept {
- return std::make_reverse_iterator(begin());
- }
- /*! @copydoc rend */
- [[nodiscard]] const_reverse_iterator crend() const noexcept {
- return rend();
- }
- /**
- * @brief Finds an entity.
- * @param entt A valid identifier.
- * @return An iterator to the given entity if it's found, past the end
- * iterator otherwise.
- */
- [[nodiscard]] const_iterator find(const entity_type entt) const noexcept {
- return contains(entt) ? to_iterator(entt) : end();
- }
- /**
- * @brief Checks if a sparse set contains an entity.
- * @param entt A valid identifier.
- * @return True if the sparse set contains the entity, false otherwise.
- */
- [[nodiscard]] bool contains(const entity_type entt) const noexcept {
- const auto *elem = sparse_ptr(entt);
- constexpr auto cap = traits_type::entity_mask;
- constexpr auto mask = traits_type::to_integral(null) & ~cap;
- // testing versions permits to avoid accessing the packed array
- return elem && (((mask & traits_type::to_integral(entt)) ^ traits_type::to_integral(*elem)) < cap);
- }
- /**
- * @brief Returns the contained version for an identifier.
- * @param entt A valid identifier.
- * @return The version for the given identifier if present, the tombstone
- * version otherwise.
- */
- [[nodiscard]] version_type current(const entity_type entt) const noexcept {
- const auto *elem = sparse_ptr(entt);
- constexpr auto fallback = traits_type::to_version(tombstone);
- return elem ? traits_type::to_version(*elem) : fallback;
- }
- /**
- * @brief Returns the position of an entity in a sparse set.
- *
- * @warning
- * Attempting to get the position of an entity that doesn't belong to the
- * sparse set results in undefined behavior.
- *
- * @param entt A valid identifier.
- * @return The position of the entity in the sparse set.
- */
- [[nodiscard]] size_type index(const entity_type entt) const noexcept {
- ENTT_ASSERT(contains(entt), "Set does not contain entity");
- return entity_to_pos(sparse_ref(entt));
- }
- /**
- * @brief Returns the entity at specified location.
- * @param pos The position for which to return the entity.
- * @return The entity at specified location.
- */
- [[nodiscard]] entity_type operator[](const size_type pos) const noexcept {
- ENTT_ASSERT(pos < packed.size(), "Index out of bounds");
- return packed[pos];
- }
- /**
- * @brief Returns the element assigned to an entity, if any.
- *
- * @warning
- * Attempting to use an entity that doesn't belong to the sparse set results
- * in undefined behavior.
- *
- * @param entt A valid identifier.
- * @return An opaque pointer to the element assigned to the entity, if any.
- */
- [[nodiscard]] const void *value(const entity_type entt) const noexcept {
- return get_at(index(entt));
- }
- /*! @copydoc value */
- [[nodiscard]] void *value(const entity_type entt) noexcept {
- return const_cast<void *>(std::as_const(*this).value(entt));
- }
- /**
- * @brief Assigns an entity to a sparse set.
- *
- * @warning
- * Attempting to assign an entity that already belongs to the sparse set
- * results in undefined behavior.
- *
- * @param entt A valid identifier.
- * @param elem Optional opaque element to forward to mixins, if any.
- * @return Iterator pointing to the emplaced element in case of success, the
- * `end()` iterator otherwise.
- */
- iterator push(const entity_type entt, const void *elem = nullptr) {
- return try_emplace(entt, false, elem);
- }
- /**
- * @brief Assigns one or more entities to a sparse set.
- *
- * @warning
- * Attempting to assign an entity that already belongs to the sparse set
- * results in undefined behavior.
- *
- * @tparam It Type of input iterator.
- * @param first An iterator to the first element of the range of entities.
- * @param last An iterator past the last element of the range of entities.
- * @return Iterator pointing to the first element inserted in case of
- * success, the `end()` iterator otherwise.
- */
- template<typename It>
- iterator push(It first, It last) {
- auto curr = end();
- for(; first != last; ++first) {
- curr = try_emplace(*first, true);
- }
- return curr;
- }
- /**
- * @brief Bump the version number of an entity.
- *
- * @warning
- * Attempting to bump the version of an entity that doesn't belong to the
- * sparse set results in undefined behavior.
- *
- * @param entt A valid identifier.
- * @return The version of the given identifier.
- */
- version_type bump(const entity_type entt) {
- auto &elem = sparse_ref(entt);
- ENTT_ASSERT(entt != null && elem != tombstone, "Cannot set the required version");
- elem = traits_type::combine(traits_type::to_integral(elem), traits_type::to_integral(entt));
- packed[entity_to_pos(elem)] = entt;
- return traits_type::to_version(entt);
- }
- /**
- * @brief Erases an entity from a sparse set.
- *
- * @warning
- * Attempting to erase an entity that doesn't belong to the sparse set
- * results in undefined behavior.
- *
- * @param entt A valid identifier.
- */
- void erase(const entity_type entt) {
- const auto it = to_iterator(entt);
- pop(it, it + 1u);
- }
- /**
- * @brief Erases entities from a set.
- *
- * @sa erase
- *
- * @tparam It Type of input iterator.
- * @param first An iterator to the first element of the range of entities.
- * @param last An iterator past the last element of the range of entities.
- */
- template<typename It>
- void erase(It first, It last) {
- if constexpr(std::is_same_v<It, basic_iterator>) {
- pop(first, last);
- } else {
- for(; first != last; ++first) {
- erase(*first);
- }
- }
- }
- /**
- * @brief Removes an entity from a sparse set if it exists.
- * @param entt A valid identifier.
- * @return True if the entity is actually removed, false otherwise.
- */
- bool remove(const entity_type entt) {
- return contains(entt) && (erase(entt), true);
- }
- /**
- * @brief Removes entities from a sparse set if they exist.
- * @tparam It Type of input iterator.
- * @param first An iterator to the first element of the range of entities.
- * @param last An iterator past the last element of the range of entities.
- * @return The number of entities actually removed.
- */
- template<typename It>
- size_type remove(It first, It last) {
- size_type count{};
- if constexpr(std::is_same_v<It, basic_iterator>) {
- while(first != last) {
- while(first != last && !contains(*first)) {
- ++first;
- }
- const auto it = first;
- while(first != last && contains(*first)) {
- ++first;
- }
- count += static_cast<size_type>(std::distance(it, first));
- erase(it, first);
- }
- } else {
- for(; first != last; ++first) {
- count += remove(*first);
- }
- }
- return count;
- }
- /*! @brief Removes all tombstones from a sparse set. */
- void compact() {
- if(mode == deletion_policy::in_place) {
- size_type from = packed.size();
- size_type pos = std::exchange(head, max_size);
- for(; from && packed[from - 1u] == tombstone; --from) {}
- while(pos != max_size) {
- if(const auto to = std::exchange(pos, entity_to_pos(packed[pos])); to < from) {
- --from;
- swap_or_move(from, to);
- packed[to] = packed[from];
- const auto elem = static_cast<typename traits_type::entity_type>(to);
- sparse_ref(packed[to]) = traits_type::combine(elem, traits_type::to_integral(packed[to]));
- for(; from && packed[from - 1u] == tombstone; --from) {}
- }
- }
- packed.erase(packed.begin() + static_cast<difference_type>(from), packed.end());
- }
- }
- /**
- * @brief Swaps two entities in a sparse set.
- *
- * For what it's worth, this function affects both the internal sparse array
- * and the internal packed array. Users should not care of that anyway.
- *
- * @warning
- * Attempting to swap entities that don't belong to the sparse set results
- * in undefined behavior.
- *
- * @param lhs A valid identifier.
- * @param rhs A valid identifier.
- */
- void swap_elements(const entity_type lhs, const entity_type rhs) {
- const auto from = index(lhs);
- const auto to = index(rhs);
- // basic no-leak guarantee if swapping throws
- swap_or_move(from, to);
- swap_at(from, to);
- }
- /**
- * @brief Sort the first count elements according to the given comparison
- * function.
- *
- * The comparison function object must return `true` if the first element
- * is _less_ than the second one, `false` otherwise. The signature of the
- * comparison function should be equivalent to the following:
- *
- * @code{.cpp}
- * bool(const Entity, const Entity);
- * @endcode
- *
- * Moreover, the comparison function object shall induce a
- * _strict weak ordering_ on the values.
- *
- * The sort function object must offer a member function template
- * `operator()` that accepts three arguments:
- *
- * * An iterator to the first element of the range to sort.
- * * An iterator past the last element of the range to sort.
- * * A comparison function to use to compare the elements.
- *
- * @tparam Compare Type of comparison function object.
- * @tparam Sort Type of sort function object.
- * @tparam Args Types of arguments to forward to the sort function object.
- * @param length Number of elements to sort.
- * @param compare A valid comparison function object.
- * @param algo A valid sort function object.
- * @param args Arguments to forward to the sort function object, if any.
- */
- template<typename Compare, typename Sort = std_sort, typename... Args>
- void sort_n(const size_type length, Compare compare, Sort algo = Sort{}, Args &&...args) {
- ENTT_ASSERT((mode != deletion_policy::in_place) || (head == max_size), "Sorting with tombstones not allowed");
- ENTT_ASSERT(!(length > packed.size()), "Length exceeds the number of elements");
- algo(packed.rend() - static_cast<difference_type>(length), packed.rend(), std::move(compare), std::forward<Args>(args)...);
- for(size_type pos{}; pos < length; ++pos) {
- auto curr = pos;
- auto next = index(packed[curr]);
- while(curr != next) {
- const auto idx = index(packed[next]);
- const auto entt = packed[curr];
- swap_or_move(next, idx);
- const auto elem = static_cast<typename traits_type::entity_type>(curr);
- sparse_ref(entt) = traits_type::combine(elem, traits_type::to_integral(packed[curr]));
- curr = std::exchange(next, idx);
- }
- }
- }
- /**
- * @brief Sort all elements according to the given comparison function.
- *
- * @sa sort_n
- *
- * @tparam Compare Type of comparison function object.
- * @tparam Sort Type of sort function object.
- * @tparam Args Types of arguments to forward to the sort function object.
- * @param compare A valid comparison function object.
- * @param algo A valid sort function object.
- * @param args Arguments to forward to the sort function object, if any.
- */
- template<typename Compare, typename Sort = std_sort, typename... Args>
- void sort(Compare compare, Sort algo = Sort{}, Args &&...args) {
- const size_type len = (mode == deletion_policy::swap_only) ? head : packed.size();
- sort_n(len, std::move(compare), std::move(algo), std::forward<Args>(args)...);
- }
- /**
- * @brief Sort entities according to their order in a range.
- *
- * Entities that are part of both the sparse set and the range are ordered
- * internally according to the order they have in the range.<br/>
- * All other entities goes to the end of the sparse set and there are no
- * guarantees on their order.
- *
- * @tparam It Type of input iterator.
- * @param first An iterator to the first element of the range of entities.
- * @param last An iterator past the last element of the range of entities.
- * @return An iterator past the last of the elements actually shared.
- */
- template<typename It>
- iterator sort_as(It first, It last) {
- ENTT_ASSERT((mode != deletion_policy::in_place) || (head == max_size), "Sorting with tombstones not allowed");
- const size_type len = (mode == deletion_policy::swap_only) ? head : packed.size();
- auto it = end() - static_cast<difference_type>(len);
- for(const auto other = end(); (it != other) && (first != last); ++first) {
- if(const auto curr = *first; contains(curr)) {
- if(const auto entt = *it; entt != curr) {
- // basic no-leak guarantee (with invalid state) if swapping throws
- swap_elements(entt, curr);
- }
- ++it;
- }
- }
- return it;
- }
- /*! @brief Clears a sparse set. */
- void clear() {
- pop_all();
- // sanity check to avoid subtle issues due to storage classes
- ENTT_ASSERT((compact(), size()) == 0u, "Non-empty set");
- head = policy_to_head();
- packed.clear();
- }
- /**
- * @brief Returns a type info object for the value type, if any.
- * @return A type info object for the value type, if any.
- */
- [[nodiscard]] const type_info &info() const noexcept {
- return *descriptor;
- }
- /*! @copydoc info */
- [[deprecated("use ::info instead")]] [[nodiscard]] const type_info &type() const noexcept {
- return info();
- }
- /**
- * @brief Forwards variables to derived classes, if any.
- * @tparam Type Type of the element to forward.
- * @param value The element to forward.
- */
- template<typename Type>
- void bind(Type &&value) noexcept {
- bind_any(forward_as_any(std::forward<Type>(value)));
- }
- private:
- sparse_container_type sparse;
- packed_container_type packed;
- const type_info *descriptor;
- deletion_policy mode;
- size_type head;
- };
- } // namespace entt
- #endif
- namespace entt {
- /*! @cond TURN_OFF_DOXYGEN */
- namespace internal {
- template<typename Container, auto Page>
- class storage_iterator final {
- friend storage_iterator<const Container, Page>;
- using container_type = std::remove_const_t<Container>;
- using alloc_traits = std::allocator_traits<typename container_type::allocator_type>;
- using iterator_traits = std::iterator_traits<std::conditional_t<
- std::is_const_v<Container>,
- typename alloc_traits::template rebind_traits<typename std::pointer_traits<typename container_type::value_type>::element_type>::const_pointer,
- typename alloc_traits::template rebind_traits<typename std::pointer_traits<typename container_type::value_type>::element_type>::pointer>>;
- public:
- using value_type = typename iterator_traits::value_type;
- using pointer = typename iterator_traits::pointer;
- using reference = typename iterator_traits::reference;
- using difference_type = typename iterator_traits::difference_type;
- using iterator_category = std::random_access_iterator_tag;
- constexpr storage_iterator() noexcept = default;
- constexpr storage_iterator(Container *ref, const difference_type idx) noexcept
- : payload{ref},
- offset{idx} {}
- template<bool Const = std::is_const_v<Container>, typename = std::enable_if_t<Const>>
- constexpr storage_iterator(const storage_iterator<std::remove_const_t<Container>, Page> &other) noexcept
- : storage_iterator{other.payload, other.offset} {}
- constexpr storage_iterator &operator++() noexcept {
- return --offset, *this;
- }
- constexpr storage_iterator operator++(int) noexcept {
- const storage_iterator orig = *this;
- return ++(*this), orig;
- }
- constexpr storage_iterator &operator--() noexcept {
- return ++offset, *this;
- }
- constexpr storage_iterator operator--(int) noexcept {
- const storage_iterator orig = *this;
- return operator--(), orig;
- }
- constexpr storage_iterator &operator+=(const difference_type value) noexcept {
- offset -= value;
- return *this;
- }
- constexpr storage_iterator operator+(const difference_type value) const noexcept {
- storage_iterator copy = *this;
- return (copy += value);
- }
- constexpr storage_iterator &operator-=(const difference_type value) noexcept {
- return (*this += -value);
- }
- constexpr storage_iterator operator-(const difference_type value) const noexcept {
- return (*this + -value);
- }
- [[nodiscard]] constexpr reference operator[](const difference_type value) const noexcept {
- const auto pos = static_cast<typename Container::size_type>(index() - value);
- return (*payload)[pos / Page][fast_mod(static_cast<std::size_t>(pos), Page)];
- }
- [[nodiscard]] constexpr pointer operator->() const noexcept {
- return std::addressof(operator[](0));
- }
- [[nodiscard]] constexpr reference operator*() const noexcept {
- return operator[](0);
- }
- [[nodiscard]] constexpr difference_type index() const noexcept {
- return offset - 1;
- }
- private:
- Container *payload;
- difference_type offset;
- };
- template<typename Lhs, typename Rhs, auto Page>
- [[nodiscard]] constexpr std::ptrdiff_t operator-(const storage_iterator<Lhs, Page> &lhs, const storage_iterator<Rhs, Page> &rhs) noexcept {
- return rhs.index() - lhs.index();
- }
- template<typename Lhs, typename Rhs, auto Page>
- [[nodiscard]] constexpr bool operator==(const storage_iterator<Lhs, Page> &lhs, const storage_iterator<Rhs, Page> &rhs) noexcept {
- return lhs.index() == rhs.index();
- }
- template<typename Lhs, typename Rhs, auto Page>
- [[nodiscard]] constexpr bool operator!=(const storage_iterator<Lhs, Page> &lhs, const storage_iterator<Rhs, Page> &rhs) noexcept {
- return !(lhs == rhs);
- }
- template<typename Lhs, typename Rhs, auto Page>
- [[nodiscard]] constexpr bool operator<(const storage_iterator<Lhs, Page> &lhs, const storage_iterator<Rhs, Page> &rhs) noexcept {
- return lhs.index() > rhs.index();
- }
- template<typename Lhs, typename Rhs, auto Page>
- [[nodiscard]] constexpr bool operator>(const storage_iterator<Lhs, Page> &lhs, const storage_iterator<Rhs, Page> &rhs) noexcept {
- return rhs < lhs;
- }
- template<typename Lhs, typename Rhs, auto Page>
- [[nodiscard]] constexpr bool operator<=(const storage_iterator<Lhs, Page> &lhs, const storage_iterator<Rhs, Page> &rhs) noexcept {
- return !(lhs > rhs);
- }
- template<typename Lhs, typename Rhs, auto Page>
- [[nodiscard]] constexpr bool operator>=(const storage_iterator<Lhs, Page> &lhs, const storage_iterator<Rhs, Page> &rhs) noexcept {
- return !(lhs < rhs);
- }
- template<typename It, typename... Other>
- class extended_storage_iterator final {
- template<typename Iter, typename... Args>
- friend class extended_storage_iterator;
- public:
- using iterator_type = It;
- using value_type = decltype(std::tuple_cat(std::make_tuple(*std::declval<It>()), std::forward_as_tuple(*std::declval<Other>()...)));
- using pointer = input_iterator_pointer<value_type>;
- using reference = value_type;
- using difference_type = std::ptrdiff_t;
- using iterator_category = std::input_iterator_tag;
- using iterator_concept = std::forward_iterator_tag;
- constexpr extended_storage_iterator()
- : it{} {}
- constexpr extended_storage_iterator(iterator_type base, Other... other)
- : it{base, other...} {}
- template<typename... Args, typename = std::enable_if_t<(!std::is_same_v<Other, Args> && ...) && (std::is_constructible_v<Other, Args> && ...)>>
- constexpr extended_storage_iterator(const extended_storage_iterator<It, Args...> &other)
- : it{other.it} {}
- constexpr extended_storage_iterator &operator++() noexcept {
- return ++std::get<It>(it), (++std::get<Other>(it), ...), *this;
- }
- constexpr extended_storage_iterator operator++(int) noexcept {
- const extended_storage_iterator orig = *this;
- return ++(*this), orig;
- }
- [[nodiscard]] constexpr pointer operator->() const noexcept {
- return operator*();
- }
- [[nodiscard]] constexpr reference operator*() const noexcept {
- return {*std::get<It>(it), *std::get<Other>(it)...};
- }
- [[nodiscard]] constexpr iterator_type base() const noexcept {
- return std::get<It>(it);
- }
- template<typename... Lhs, typename... Rhs>
- friend constexpr bool operator==(const extended_storage_iterator<Lhs...> &, const extended_storage_iterator<Rhs...> &) noexcept;
- private:
- std::tuple<It, Other...> it;
- };
- template<typename... Lhs, typename... Rhs>
- [[nodiscard]] constexpr bool operator==(const extended_storage_iterator<Lhs...> &lhs, const extended_storage_iterator<Rhs...> &rhs) noexcept {
- return std::get<0>(lhs.it) == std::get<0>(rhs.it);
- }
- template<typename... Lhs, typename... Rhs>
- [[nodiscard]] constexpr bool operator!=(const extended_storage_iterator<Lhs...> &lhs, const extended_storage_iterator<Rhs...> &rhs) noexcept {
- return !(lhs == rhs);
- }
- } // namespace internal
- /*! @endcond */
- /**
- * @brief Storage implementation.
- *
- * Internal data structures arrange elements to maximize performance. There are
- * no guarantees that objects are returned in the insertion order when iterate
- * a storage. Do not make assumption on the order in any case.
- *
- * @warning
- * Empty types aren't explicitly instantiated. Therefore, many of the functions
- * normally available for non-empty types will not be available for empty ones.
- *
- * @tparam Type Element type.
- * @tparam Entity A valid entity type.
- * @tparam Allocator Type of allocator used to manage memory and elements.
- */
- template<typename Type, typename Entity, typename Allocator, typename>
- class basic_storage: public basic_sparse_set<Entity, typename std::allocator_traits<Allocator>::template rebind_alloc<Entity>> {
- using alloc_traits = std::allocator_traits<Allocator>;
- static_assert(std::is_same_v<typename alloc_traits::value_type, Type>, "Invalid value type");
- using container_type = std::vector<typename alloc_traits::pointer, typename alloc_traits::template rebind_alloc<typename alloc_traits::pointer>>;
- using underlying_type = basic_sparse_set<Entity, typename alloc_traits::template rebind_alloc<Entity>>;
- using underlying_iterator = typename underlying_type::basic_iterator;
- using traits_type = component_traits<Type, Entity>;
- [[nodiscard]] auto &element_at(const std::size_t pos) const {
- return payload[pos / traits_type::page_size][fast_mod(pos, traits_type::page_size)];
- }
- auto assure_at_least(const std::size_t pos) {
- const auto idx = pos / traits_type::page_size;
- if(!(idx < payload.size())) {
- auto curr = payload.size();
- allocator_type allocator{get_allocator()};
- payload.resize(idx + 1u, nullptr);
- ENTT_TRY {
- for(const auto last = payload.size(); curr < last; ++curr) {
- payload[curr] = alloc_traits::allocate(allocator, traits_type::page_size);
- }
- }
- ENTT_CATCH {
- payload.resize(curr);
- ENTT_THROW;
- }
- }
- return payload[idx] + fast_mod(pos, traits_type::page_size);
- }
- template<typename... Args>
- auto emplace_element(const Entity entt, const bool force_back, Args &&...args) {
- const auto it = base_type::try_emplace(entt, force_back);
- ENTT_TRY {
- auto *elem = to_address(assure_at_least(static_cast<size_type>(it.index())));
- entt::uninitialized_construct_using_allocator(elem, get_allocator(), std::forward<Args>(args)...);
- }
- ENTT_CATCH {
- base_type::pop(it, it + 1u);
- ENTT_THROW;
- }
- return it;
- }
- void shrink_to_size(const std::size_t sz) {
- const auto from = (sz + traits_type::page_size - 1u) / traits_type::page_size;
- allocator_type allocator{get_allocator()};
- for(auto pos = sz, length = base_type::size(); pos < length; ++pos) {
- if constexpr(traits_type::in_place_delete) {
- if(base_type::data()[pos] != tombstone) {
- alloc_traits::destroy(allocator, std::addressof(element_at(pos)));
- }
- } else {
- alloc_traits::destroy(allocator, std::addressof(element_at(pos)));
- }
- }
- for(auto pos = from, last = payload.size(); pos < last; ++pos) {
- alloc_traits::deallocate(allocator, payload[pos], traits_type::page_size);
- }
- payload.resize(from);
- payload.shrink_to_fit();
- }
- void swap_at(const std::size_t lhs, const std::size_t rhs) {
- using std::swap;
- swap(element_at(lhs), element_at(rhs));
- }
- void move_to(const std::size_t lhs, const std::size_t rhs) {
- auto &elem = element_at(lhs);
- allocator_type allocator{get_allocator()};
- entt::uninitialized_construct_using_allocator(to_address(assure_at_least(rhs)), allocator, std::move(elem));
- alloc_traits::destroy(allocator, std::addressof(elem));
- }
- private:
- [[nodiscard]] const void *get_at(const std::size_t pos) const final {
- return std::addressof(element_at(pos));
- }
- void swap_or_move([[maybe_unused]] const std::size_t from, [[maybe_unused]] const std::size_t to) override {
- static constexpr bool is_pinned_type = !(std::is_move_constructible_v<Type> && std::is_move_assignable_v<Type>);
- // use a runtime value to avoid compile-time suppression that drives the code coverage tool crazy
- ENTT_ASSERT((from + 1u) && !is_pinned_type, "Pinned type");
- if constexpr(!is_pinned_type) {
- if constexpr(traits_type::in_place_delete) {
- (base_type::operator[](to) == tombstone) ? move_to(from, to) : swap_at(from, to);
- } else {
- swap_at(from, to);
- }
- }
- }
- protected:
- /**
- * @brief Erases entities from a storage.
- * @param first An iterator to the first element of the range of entities.
- * @param last An iterator past the last element of the range of entities.
- */
- void pop(underlying_iterator first, underlying_iterator last) override {
- for(allocator_type allocator{get_allocator()}; first != last; ++first) {
- // cannot use first.index() because it would break with cross iterators
- auto &elem = element_at(base_type::index(*first));
- if constexpr(traits_type::in_place_delete) {
- base_type::in_place_pop(first);
- alloc_traits::destroy(allocator, std::addressof(elem));
- } else {
- auto &other = element_at(base_type::size() - 1u);
- // destroying on exit allows reentrant destructors
- [[maybe_unused]] auto unused = std::exchange(elem, std::move(other));
- alloc_traits::destroy(allocator, std::addressof(other));
- base_type::swap_and_pop(first);
- }
- }
- }
- /*! @brief Erases all entities of a storage. */
- void pop_all() override {
- allocator_type allocator{get_allocator()};
- for(auto first = base_type::begin(); !(first.index() < 0); ++first) {
- if constexpr(traits_type::in_place_delete) {
- if(*first != tombstone) {
- base_type::in_place_pop(first);
- alloc_traits::destroy(allocator, std::addressof(element_at(static_cast<size_type>(first.index()))));
- }
- } else {
- base_type::swap_and_pop(first);
- alloc_traits::destroy(allocator, std::addressof(element_at(static_cast<size_type>(first.index()))));
- }
- }
- }
- /**
- * @brief Assigns an entity to a storage.
- * @param entt A valid identifier.
- * @param value Optional opaque value.
- * @param force_back Force back insertion.
- * @return Iterator pointing to the emplaced element.
- */
- underlying_iterator try_emplace([[maybe_unused]] const Entity entt, [[maybe_unused]] const bool force_back, const void *value) override {
- if(value != nullptr) {
- if constexpr(std::is_copy_constructible_v<element_type>) {
- return emplace_element(entt, force_back, *static_cast<const element_type *>(value));
- } else {
- return base_type::end();
- }
- } else {
- if constexpr(std::is_default_constructible_v<element_type>) {
- return emplace_element(entt, force_back);
- } else {
- return base_type::end();
- }
- }
- }
- public:
- /*! @brief Allocator type. */
- using allocator_type = Allocator;
- /*! @brief Base type. */
- using base_type = underlying_type;
- /*! @brief Element type. */
- using element_type = Type;
- /*! @brief Type of the objects assigned to entities. */
- using value_type = element_type;
- /*! @brief Underlying entity identifier. */
- using entity_type = Entity;
- /*! @brief Unsigned integer type. */
- using size_type = std::size_t;
- /*! @brief Signed integer type. */
- using difference_type = std::ptrdiff_t;
- /*! @brief Pointer type to contained elements. */
- using pointer = typename container_type::pointer;
- /*! @brief Constant pointer type to contained elements. */
- using const_pointer = typename alloc_traits::template rebind_traits<typename alloc_traits::const_pointer>::const_pointer;
- /*! @brief Random access iterator type. */
- using iterator = internal::storage_iterator<container_type, traits_type::page_size>;
- /*! @brief Constant random access iterator type. */
- using const_iterator = internal::storage_iterator<const container_type, traits_type::page_size>;
- /*! @brief Reverse iterator type. */
- using reverse_iterator = std::reverse_iterator<iterator>;
- /*! @brief Constant reverse iterator type. */
- using const_reverse_iterator = std::reverse_iterator<const_iterator>;
- /*! @brief Extended iterable storage proxy. */
- using iterable = iterable_adaptor<internal::extended_storage_iterator<typename base_type::iterator, iterator>>;
- /*! @brief Constant extended iterable storage proxy. */
- using const_iterable = iterable_adaptor<internal::extended_storage_iterator<typename base_type::const_iterator, const_iterator>>;
- /*! @brief Extended reverse iterable storage proxy. */
- using reverse_iterable = iterable_adaptor<internal::extended_storage_iterator<typename base_type::reverse_iterator, reverse_iterator>>;
- /*! @brief Constant extended reverse iterable storage proxy. */
- using const_reverse_iterable = iterable_adaptor<internal::extended_storage_iterator<typename base_type::const_reverse_iterator, const_reverse_iterator>>;
- /*! @brief Storage deletion policy. */
- static constexpr deletion_policy storage_policy{traits_type::in_place_delete};
- /*! @brief Default constructor. */
- basic_storage()
- : basic_storage{allocator_type{}} {}
- /**
- * @brief Constructs an empty storage with a given allocator.
- * @param allocator The allocator to use.
- */
- explicit basic_storage(const allocator_type &allocator)
- : base_type{type_id<element_type>(), storage_policy, allocator},
- payload{allocator} {}
- /*! @brief Default copy constructor, deleted on purpose. */
- basic_storage(const basic_storage &) = delete;
- /**
- * @brief Move constructor.
- * @param other The instance to move from.
- */
- basic_storage(basic_storage &&other) noexcept
- : base_type{static_cast<base_type &&>(other)},
- payload{std::move(other.payload)} {}
- /**
- * @brief Allocator-extended move constructor.
- * @param other The instance to move from.
- * @param allocator The allocator to use.
- */
- basic_storage(basic_storage &&other, const allocator_type &allocator)
- : base_type{static_cast<base_type &&>(other), allocator},
- payload{std::move(other.payload), allocator} {
- ENTT_ASSERT(alloc_traits::is_always_equal::value || get_allocator() == other.get_allocator(), "Copying a storage is not allowed");
- }
- /*! @brief Default destructor. */
- // NOLINTNEXTLINE(bugprone-exception-escape)
- ~basic_storage() override {
- shrink_to_size(0u);
- }
- /**
- * @brief Default copy assignment operator, deleted on purpose.
- * @return This storage.
- */
- basic_storage &operator=(const basic_storage &) = delete;
- /**
- * @brief Move assignment operator.
- * @param other The instance to move from.
- * @return This storage.
- */
- basic_storage &operator=(basic_storage &&other) noexcept {
- ENTT_ASSERT(alloc_traits::is_always_equal::value || get_allocator() == other.get_allocator(), "Copying a storage is not allowed");
- swap(other);
- return *this;
- }
- /**
- * @brief Exchanges the contents with those of a given storage.
- * @param other Storage to exchange the content with.
- */
- void swap(basic_storage &other) noexcept {
- using std::swap;
- swap(payload, other.payload);
- base_type::swap(other);
- }
- /**
- * @brief Returns the associated allocator.
- * @return The associated allocator.
- */
- [[nodiscard]] constexpr allocator_type get_allocator() const noexcept {
- return payload.get_allocator();
- }
- /**
- * @brief Increases the capacity of a storage.
- *
- * If the new capacity is greater than the current capacity, new storage is
- * allocated, otherwise the method does nothing.
- *
- * @param cap Desired capacity.
- */
- void reserve(const size_type cap) override {
- if(cap != 0u) {
- base_type::reserve(cap);
- assure_at_least(cap - 1u);
- }
- }
- /**
- * @brief Returns the number of elements that a storage has currently
- * allocated space for.
- * @return Capacity of the storage.
- */
- [[nodiscard]] size_type capacity() const noexcept override {
- return payload.size() * traits_type::page_size;
- }
- /*! @brief Requests the removal of unused capacity. */
- void shrink_to_fit() override {
- base_type::shrink_to_fit();
- shrink_to_size(base_type::size());
- }
- /**
- * @brief Direct access to the array of objects.
- * @return A pointer to the array of objects.
- */
- [[nodiscard]] const_pointer raw() const noexcept {
- return payload.data();
- }
- /*! @copydoc raw */
- [[nodiscard]] pointer raw() noexcept {
- return payload.data();
- }
- /**
- * @brief Returns an iterator to the beginning.
- *
- * If the storage is empty, the returned iterator will be equal to `end()`.
- *
- * @return An iterator to the first instance of the internal array.
- */
- [[nodiscard]] const_iterator cbegin() const noexcept {
- const auto pos = static_cast<difference_type>(base_type::size());
- return const_iterator{&payload, pos};
- }
- /*! @copydoc cbegin */
- [[nodiscard]] const_iterator begin() const noexcept {
- return cbegin();
- }
- /*! @copydoc begin */
- [[nodiscard]] iterator begin() noexcept {
- const auto pos = static_cast<difference_type>(base_type::size());
- return iterator{&payload, pos};
- }
- /**
- * @brief Returns an iterator to the end.
- * @return An iterator to the element following the last instance of the
- * internal array.
- */
- [[nodiscard]] const_iterator cend() const noexcept {
- return const_iterator{&payload, {}};
- }
- /*! @copydoc cend */
- [[nodiscard]] const_iterator end() const noexcept {
- return cend();
- }
- /*! @copydoc end */
- [[nodiscard]] iterator end() noexcept {
- return iterator{&payload, {}};
- }
- /**
- * @brief Returns a reverse iterator to the beginning.
- *
- * If the storage is empty, the returned iterator will be equal to `rend()`.
- *
- * @return An iterator to the first instance of the reversed internal array.
- */
- [[nodiscard]] const_reverse_iterator crbegin() const noexcept {
- return std::make_reverse_iterator(cend());
- }
- /*! @copydoc crbegin */
- [[nodiscard]] const_reverse_iterator rbegin() const noexcept {
- return crbegin();
- }
- /*! @copydoc rbegin */
- [[nodiscard]] reverse_iterator rbegin() noexcept {
- return std::make_reverse_iterator(end());
- }
- /**
- * @brief Returns a reverse iterator to the end.
- * @return An iterator to the element following the last instance of the
- * reversed internal array.
- */
- [[nodiscard]] const_reverse_iterator crend() const noexcept {
- return std::make_reverse_iterator(cbegin());
- }
- /*! @copydoc crend */
- [[nodiscard]] const_reverse_iterator rend() const noexcept {
- return crend();
- }
- /*! @copydoc rend */
- [[nodiscard]] reverse_iterator rend() noexcept {
- return std::make_reverse_iterator(begin());
- }
- /**
- * @brief Returns the object assigned to an entity.
- *
- * @warning
- * Attempting to use an entity that doesn't belong to the storage results in
- * undefined behavior.
- *
- * @param entt A valid identifier.
- * @return The object assigned to the entity.
- */
- [[nodiscard]] const value_type &get(const entity_type entt) const noexcept {
- return element_at(base_type::index(entt));
- }
- /*! @copydoc get */
- [[nodiscard]] value_type &get(const entity_type entt) noexcept {
- return const_cast<value_type &>(std::as_const(*this).get(entt));
- }
- /**
- * @brief Returns the object assigned to an entity as a tuple.
- * @param entt A valid identifier.
- * @return The object assigned to the entity as a tuple.
- */
- [[nodiscard]] std::tuple<const value_type &> get_as_tuple(const entity_type entt) const noexcept {
- return std::forward_as_tuple(get(entt));
- }
- /*! @copydoc get_as_tuple */
- [[nodiscard]] std::tuple<value_type &> get_as_tuple(const entity_type entt) noexcept {
- return std::forward_as_tuple(get(entt));
- }
- /**
- * @brief Assigns an entity to a storage and constructs its object.
- *
- * @warning
- * Attempting to use an entity that already belongs to the storage results
- * in undefined behavior.
- *
- * @tparam Args Types of arguments to use to construct the object.
- * @param entt A valid identifier.
- * @param args Parameters to use to construct an object for the entity.
- * @return A reference to the newly created object.
- */
- template<typename... Args>
- value_type &emplace(const entity_type entt, Args &&...args) {
- if constexpr(std::is_aggregate_v<value_type> && (sizeof...(Args) != 0u || !std::is_default_constructible_v<value_type>)) {
- const auto it = emplace_element(entt, false, Type{std::forward<Args>(args)...});
- return element_at(static_cast<size_type>(it.index()));
- } else {
- const auto it = emplace_element(entt, false, std::forward<Args>(args)...);
- return element_at(static_cast<size_type>(it.index()));
- }
- }
- /**
- * @brief Updates the instance assigned to a given entity in-place.
- * @tparam Func Types of the function objects to invoke.
- * @param entt A valid identifier.
- * @param func Valid function objects.
- * @return A reference to the updated instance.
- */
- template<typename... Func>
- value_type &patch(const entity_type entt, Func &&...func) {
- const auto idx = base_type::index(entt);
- auto &elem = element_at(idx);
- (std::forward<Func>(func)(elem), ...);
- return elem;
- }
- /**
- * @brief Assigns one or more entities to a storage and constructs their
- * objects from a given instance.
- *
- * @warning
- * Attempting to assign an entity that already belongs to the storage
- * results in undefined behavior.
- *
- * @tparam It Type of input iterator.
- * @param first An iterator to the first element of the range of entities.
- * @param last An iterator past the last element of the range of entities.
- * @param value An instance of the object to construct.
- * @return Iterator pointing to the first element inserted, if any.
- */
- template<typename It>
- iterator insert(It first, It last, const value_type &value = {}) {
- for(; first != last; ++first) {
- emplace_element(*first, true, value);
- }
- return begin();
- }
- /**
- * @brief Assigns one or more entities to a storage and constructs their
- * objects from a given range.
- *
- * @sa construct
- *
- * @tparam EIt Type of input iterator.
- * @tparam CIt Type of input iterator.
- * @param first An iterator to the first element of the range of entities.
- * @param last An iterator past the last element of the range of entities.
- * @param from An iterator to the first element of the range of objects.
- * @return Iterator pointing to the first element inserted, if any.
- */
- template<typename EIt, typename CIt, typename = std::enable_if_t<std::is_same_v<typename std::iterator_traits<CIt>::value_type, value_type>>>
- iterator insert(EIt first, EIt last, CIt from) {
- for(; first != last; ++first, ++from) {
- emplace_element(*first, true, *from);
- }
- return begin();
- }
- /**
- * @brief Returns an iterable object to use to _visit_ a storage.
- *
- * The iterable object returns a tuple that contains the current entity and
- * a reference to its element.
- *
- * @return An iterable object to use to _visit_ the storage.
- */
- [[nodiscard]] iterable each() noexcept {
- return iterable{{base_type::begin(), begin()}, {base_type::end(), end()}};
- }
- /*! @copydoc each */
- [[nodiscard]] const_iterable each() const noexcept {
- return const_iterable{{base_type::cbegin(), cbegin()}, {base_type::cend(), cend()}};
- }
- /**
- * @brief Returns a reverse iterable object to use to _visit_ a storage.
- *
- * @sa each
- *
- * @return A reverse iterable object to use to _visit_ the storage.
- */
- [[nodiscard]] reverse_iterable reach() noexcept {
- return reverse_iterable{{base_type::rbegin(), rbegin()}, {base_type::rend(), rend()}};
- }
- /*! @copydoc reach */
- [[nodiscard]] const_reverse_iterable reach() const noexcept {
- return const_reverse_iterable{{base_type::crbegin(), crbegin()}, {base_type::crend(), crend()}};
- }
- private:
- container_type payload;
- };
- /*! @copydoc basic_storage */
- template<typename Type, typename Entity, typename Allocator>
- class basic_storage<Type, Entity, Allocator, std::enable_if_t<component_traits<Type, Entity>::page_size == 0u>>
- : public basic_sparse_set<Entity, typename std::allocator_traits<Allocator>::template rebind_alloc<Entity>> {
- using alloc_traits = std::allocator_traits<Allocator>;
- static_assert(std::is_same_v<typename alloc_traits::value_type, Type>, "Invalid value type");
- using traits_type = component_traits<Type, Entity>;
- public:
- /*! @brief Allocator type. */
- using allocator_type = Allocator;
- /*! @brief Base type. */
- using base_type = basic_sparse_set<Entity, typename alloc_traits::template rebind_alloc<Entity>>;
- /*! @brief Element type. */
- using element_type = Type;
- /*! @brief Type of the objects assigned to entities. */
- using value_type = void;
- /*! @brief Underlying entity identifier. */
- using entity_type = Entity;
- /*! @brief Unsigned integer type. */
- using size_type = std::size_t;
- /*! @brief Signed integer type. */
- using difference_type = std::ptrdiff_t;
- /*! @brief Extended iterable storage proxy. */
- using iterable = iterable_adaptor<internal::extended_storage_iterator<typename base_type::iterator>>;
- /*! @brief Constant extended iterable storage proxy. */
- using const_iterable = iterable_adaptor<internal::extended_storage_iterator<typename base_type::const_iterator>>;
- /*! @brief Extended reverse iterable storage proxy. */
- using reverse_iterable = iterable_adaptor<internal::extended_storage_iterator<typename base_type::reverse_iterator>>;
- /*! @brief Constant extended reverse iterable storage proxy. */
- using const_reverse_iterable = iterable_adaptor<internal::extended_storage_iterator<typename base_type::const_reverse_iterator>>;
- /*! @brief Storage deletion policy. */
- static constexpr deletion_policy storage_policy{traits_type::in_place_delete};
- /*! @brief Default constructor. */
- basic_storage()
- : basic_storage{allocator_type{}} {}
- /**
- * @brief Constructs an empty container with a given allocator.
- * @param allocator The allocator to use.
- */
- explicit basic_storage(const allocator_type &allocator)
- : base_type{type_id<element_type>(), storage_policy, allocator} {}
- /*! @brief Default copy constructor, deleted on purpose. */
- basic_storage(const basic_storage &) = delete;
- /**
- * @brief Move constructor.
- * @param other The instance to move from.
- */
- basic_storage(basic_storage &&other) noexcept = default;
- /**
- * @brief Allocator-extended move constructor.
- * @param other The instance to move from.
- * @param allocator The allocator to use.
- */
- basic_storage(basic_storage &&other, const allocator_type &allocator)
- : base_type{std::move(other), allocator} {}
- /*! @brief Default destructor. */
- ~basic_storage() override = default;
- /**
- * @brief Default copy assignment operator, deleted on purpose.
- * @return This storage.
- */
- basic_storage &operator=(const basic_storage &) = delete;
- /**
- * @brief Move assignment operator.
- * @param other The instance to move from.
- * @return This storage.
- */
- basic_storage &operator=(basic_storage &&other) noexcept = default;
- /**
- * @brief Returns the associated allocator.
- * @return The associated allocator.
- */
- [[nodiscard]] constexpr allocator_type get_allocator() const noexcept {
- // std::allocator<void> has no cross constructors (waiting for C++20)
- if constexpr(std::is_void_v<element_type> && !std::is_constructible_v<allocator_type, typename base_type::allocator_type>) {
- return allocator_type{};
- } else {
- return allocator_type{base_type::get_allocator()};
- }
- }
- /**
- * @brief Returns the object assigned to an entity, that is `void`.
- *
- * @warning
- * Attempting to use an entity that doesn't belong to the storage results in
- * undefined behavior.
- *
- * @param entt A valid identifier.
- */
- void get([[maybe_unused]] const entity_type entt) const noexcept {
- ENTT_ASSERT(base_type::contains(entt), "Invalid entity");
- }
- /**
- * @brief Returns an empty tuple.
- * @param entt A valid identifier.
- * @return Returns an empty tuple.
- */
- [[nodiscard]] std::tuple<> get_as_tuple([[maybe_unused]] const entity_type entt) const noexcept {
- ENTT_ASSERT(base_type::contains(entt), "Invalid entity");
- return std::tuple{};
- }
- /**
- * @brief Assigns an entity to a storage and constructs its object.
- *
- * @warning
- * Attempting to use an entity that already belongs to the storage results
- * in undefined behavior.
- *
- * @param entt A valid identifier.
- */
- void emplace(const entity_type entt) {
- base_type::try_emplace(entt, false);
- }
- /**
- * @brief Updates the instance assigned to a given entity in-place.
- * @tparam Func Types of the function objects to invoke.
- * @param entt A valid identifier.
- * @param func Valid function objects.
- */
- template<typename... Func>
- void patch([[maybe_unused]] const entity_type entt, Func &&...func) {
- ENTT_ASSERT(base_type::contains(entt), "Invalid entity");
- (std::forward<Func>(func)(), ...);
- }
- /**
- * @brief Assigns entities to a storage.
- * @tparam It Type of input iterator.
- * @param first An iterator to the first element of the range of entities.
- * @param last An iterator past the last element of the range of entities.
- */
- template<typename It>
- void insert(It first, It last) {
- for(; first != last; ++first) {
- base_type::try_emplace(*first, true);
- }
- }
- /**
- * @brief Returns an iterable object to use to _visit_ a storage.
- *
- * The iterable object returns a tuple that contains the current entity.
- *
- * @return An iterable object to use to _visit_ the storage.
- */
- [[nodiscard]] iterable each() noexcept {
- return iterable{base_type::begin(), base_type::end()};
- }
- /*! @copydoc each */
- [[nodiscard]] const_iterable each() const noexcept {
- return const_iterable{base_type::cbegin(), base_type::cend()};
- }
- /**
- * @brief Returns a reverse iterable object to use to _visit_ a storage.
- *
- * @sa each
- *
- * @return A reverse iterable object to use to _visit_ the storage.
- */
- [[nodiscard]] reverse_iterable reach() noexcept {
- return reverse_iterable{{base_type::rbegin()}, {base_type::rend()}};
- }
- /*! @copydoc reach */
- [[nodiscard]] const_reverse_iterable reach() const noexcept {
- return const_reverse_iterable{{base_type::crbegin()}, {base_type::crend()}};
- }
- };
- /**
- * @brief Swap-only entity storage specialization.
- * @tparam Entity A valid entity type.
- * @tparam Allocator Type of allocator used to manage memory and elements.
- */
- template<typename Entity, typename Allocator>
- class basic_storage<Entity, Entity, Allocator>
- : public basic_sparse_set<Entity, Allocator> {
- using alloc_traits = std::allocator_traits<Allocator>;
- static_assert(std::is_same_v<typename alloc_traits::value_type, Entity>, "Invalid value type");
- using underlying_iterator = typename basic_sparse_set<Entity, Allocator>::basic_iterator;
- using traits_type = entt_traits<Entity>;
- auto from_placeholder() noexcept {
- const auto entt = traits_type::combine(static_cast<typename traits_type::entity_type>(placeholder), {});
- ENTT_ASSERT(entt != null, "No more entities available");
- placeholder += static_cast<size_type>(entt != null);
- return entt;
- }
- auto next() noexcept {
- entity_type entt = from_placeholder();
- while(base_type::current(entt) != traits_type::to_version(tombstone) && entt != null) {
- entt = from_placeholder();
- }
- return entt;
- }
- protected:
- /*! @brief Erases all entities of a storage. */
- void pop_all() override {
- base_type::pop_all();
- placeholder = {};
- }
- /**
- * @brief Assigns an entity to a storage.
- * @param hint A valid identifier.
- * @return Iterator pointing to the emplaced element.
- */
- underlying_iterator try_emplace(const Entity hint, const bool, const void *) override {
- return base_type::find(generate(hint));
- }
- public:
- /*! @brief Allocator type. */
- using allocator_type = Allocator;
- /*! @brief Base type. */
- using base_type = basic_sparse_set<Entity, Allocator>;
- /*! @brief Element type. */
- using element_type = Entity;
- /*! @brief Type of the objects assigned to entities. */
- using value_type = void;
- /*! @brief Underlying entity identifier. */
- using entity_type = Entity;
- /*! @brief Unsigned integer type. */
- using size_type = std::size_t;
- /*! @brief Signed integer type. */
- using difference_type = std::ptrdiff_t;
- /*! @brief Extended iterable storage proxy. */
- using iterable = iterable_adaptor<internal::extended_storage_iterator<typename base_type::iterator>>;
- /*! @brief Constant extended iterable storage proxy. */
- using const_iterable = iterable_adaptor<internal::extended_storage_iterator<typename base_type::const_iterator>>;
- /*! @brief Extended reverse iterable storage proxy. */
- using reverse_iterable = iterable_adaptor<internal::extended_storage_iterator<typename base_type::reverse_iterator>>;
- /*! @brief Constant extended reverse iterable storage proxy. */
- using const_reverse_iterable = iterable_adaptor<internal::extended_storage_iterator<typename base_type::const_reverse_iterator>>;
- /*! @brief Storage deletion policy. */
- static constexpr deletion_policy storage_policy = deletion_policy::swap_only;
- /*! @brief Default constructor. */
- basic_storage()
- : basic_storage{allocator_type{}} {
- }
- /**
- * @brief Constructs an empty container with a given allocator.
- * @param allocator The allocator to use.
- */
- explicit basic_storage(const allocator_type &allocator)
- : base_type{type_id<void>(), storage_policy, allocator} {}
- /*! @brief Default copy constructor, deleted on purpose. */
- basic_storage(const basic_storage &) = delete;
- /**
- * @brief Move constructor.
- * @param other The instance to move from.
- */
- // NOLINTNEXTLINE(cppcoreguidelines-rvalue-reference-param-not-moved)
- basic_storage(basic_storage &&other) noexcept
- : base_type{static_cast<base_type &&>(other)},
- placeholder{other.placeholder} {}
- /**
- * @brief Allocator-extended move constructor.
- * @param other The instance to move from.
- * @param allocator The allocator to use.
- */
- // NOLINTNEXTLINE(cppcoreguidelines-rvalue-reference-param-not-moved)
- basic_storage(basic_storage &&other, const allocator_type &allocator)
- : base_type{static_cast<base_type &&>(other), allocator},
- placeholder{other.placeholder} {}
- /*! @brief Default destructor. */
- ~basic_storage() override = default;
- /**
- * @brief Default copy assignment operator, deleted on purpose.
- * @return This storage.
- */
- basic_storage &operator=(const basic_storage &) = delete;
- /**
- * @brief Move assignment operator.
- * @param other The instance to move from.
- * @return This storage.
- */
- basic_storage &operator=(basic_storage &&other) noexcept {
- placeholder = other.placeholder;
- base_type::operator=(std::move(other));
- return *this;
- }
- /**
- * @brief Exchanges the contents with those of a given storage.
- * @param other Storage to exchange the content with.
- */
- void swap(basic_storage &other) noexcept {
- using std::swap;
- swap(placeholder, other.placeholder);
- base_type::swap(other);
- }
- /**
- * @brief Returns the object assigned to an entity, that is `void`.
- *
- * @warning
- * Attempting to use an entity that doesn't belong to the storage results in
- * undefined behavior.
- *
- * @param entt A valid identifier.
- */
- void get([[maybe_unused]] const entity_type entt) const noexcept {
- ENTT_ASSERT(base_type::index(entt) < base_type::free_list(), "The requested entity is not a live one");
- }
- /**
- * @brief Returns an empty tuple.
- * @param entt A valid identifier.
- * @return Returns an empty tuple.
- */
- [[nodiscard]] std::tuple<> get_as_tuple([[maybe_unused]] const entity_type entt) const noexcept {
- ENTT_ASSERT(base_type::index(entt) < base_type::free_list(), "The requested entity is not a live one");
- return std::tuple{};
- }
- /**
- * @brief Creates a new identifier or recycles a destroyed one.
- * @return A valid identifier.
- */
- entity_type generate() {
- const auto len = base_type::free_list();
- const auto entt = (len == base_type::size()) ? next() : base_type::data()[len];
- return *base_type::try_emplace(entt, true);
- }
- /**
- * @brief Creates a new identifier or recycles a destroyed one.
- *
- * If the requested identifier isn't in use, the suggested one is used.
- * Otherwise, a new identifier is returned.
- *
- * @param hint Required identifier.
- * @return A valid identifier.
- */
- entity_type generate(const entity_type hint) {
- if(hint != null && hint != tombstone) {
- if(const auto curr = traits_type::construct(traits_type::to_entity(hint), base_type::current(hint)); curr == tombstone || !(base_type::index(curr) < base_type::free_list())) {
- return *base_type::try_emplace(hint, true);
- }
- }
- return generate();
- }
- /**
- * @brief Assigns each element in a range an identifier.
- * @tparam It Type of mutable forward iterator.
- * @param first An iterator to the first element of the range to generate.
- * @param last An iterator past the last element of the range to generate.
- */
- template<typename It>
- void generate(It first, It last) {
- for(const auto sz = base_type::size(); first != last && base_type::free_list() != sz; ++first) {
- *first = *base_type::try_emplace(base_type::data()[base_type::free_list()], true);
- }
- for(; first != last; ++first) {
- *first = *base_type::try_emplace(next(), true);
- }
- }
- /**
- * @brief Updates a given identifier.
- * @tparam Func Types of the function objects to invoke.
- * @param entt A valid identifier.
- * @param func Valid function objects.
- */
- template<typename... Func>
- void patch([[maybe_unused]] const entity_type entt, Func &&...func) {
- ENTT_ASSERT(base_type::index(entt) < base_type::free_list(), "The requested entity is not a live one");
- (std::forward<Func>(func)(), ...);
- }
- /**
- * @brief Returns an iterable object to use to _visit_ a storage.
- *
- * The iterable object returns a tuple that contains the current entity.
- *
- * @return An iterable object to use to _visit_ the storage.
- */
- [[nodiscard]] iterable each() noexcept {
- return std::as_const(*this).each();
- }
- /*! @copydoc each */
- [[nodiscard]] const_iterable each() const noexcept {
- const auto it = base_type::cend();
- const auto offset = static_cast<difference_type>(base_type::free_list());
- return const_iterable{it - offset, it};
- }
- /**
- * @brief Returns a reverse iterable object to use to _visit_ a storage.
- *
- * @sa each
- *
- * @return A reverse iterable object to use to _visit_ the storage.
- */
- [[nodiscard]] reverse_iterable reach() noexcept {
- return std::as_const(*this).reach();
- }
- /*! @copydoc reach */
- [[nodiscard]] const_reverse_iterable reach() const noexcept {
- const auto it = base_type::crbegin();
- const auto offset = static_cast<difference_type>(base_type::free_list());
- return const_reverse_iterable{it, it + offset};
- }
- /**
- * @brief Sets the starting identifier for generation.
- *
- * The version is ignored, regardless of the value.
- *
- * @param hint A valid identifier.
- */
- void start_from(const entity_type hint) {
- placeholder = static_cast<size_type>(traits_type::to_entity(hint));
- }
- private:
- size_type placeholder{};
- };
- } // namespace entt
- #endif
- // #include "view.hpp"
- #ifndef ENTT_ENTITY_VIEW_HPP
- #define ENTT_ENTITY_VIEW_HPP
- #include <array>
- #include <cstddef>
- #include <iterator>
- #include <tuple>
- #include <type_traits>
- #include <utility>
- // #include "../config/config.h"
- // #include "../core/iterator.hpp"
- // #include "../core/type_traits.hpp"
- // #include "entity.hpp"
- // #include "fwd.hpp"
- namespace entt {
- /*! @cond TURN_OFF_DOXYGEN */
- namespace internal {
- template<typename... Type>
- // NOLINTNEXTLINE(misc-redundant-expression)
- static constexpr bool tombstone_check_v = ((sizeof...(Type) == 1u) && ... && (Type::storage_policy == deletion_policy::in_place));
- template<typename Type>
- const Type *view_placeholder() {
- static_assert(std::is_same_v<std::remove_const_t<std::remove_reference_t<Type>>, Type>, "Unexpected type");
- static const Type placeholder{};
- return &placeholder;
- }
- template<typename It, typename Entity>
- [[nodiscard]] bool all_of(It first, const It last, const Entity entt) noexcept {
- for(; (first != last) && (*first)->contains(entt); ++first) {}
- return first == last;
- }
- template<typename It, typename Entity>
- [[nodiscard]] bool none_of(It first, const It last, const Entity entt) noexcept {
- for(; (first != last) && !(*first)->contains(entt); ++first) {}
- return first == last;
- }
- template<typename It>
- [[nodiscard]] bool fully_initialized(It first, const It last, const std::remove_pointer_t<typename std::iterator_traits<It>::value_type> *placeholder) noexcept {
- for(; (first != last) && *first != placeholder; ++first) {}
- return first == last;
- }
- template<typename Result, typename View, typename Other, std::size_t... GLhs, std::size_t... ELhs, std::size_t... GRhs, std::size_t... ERhs>
- [[nodiscard]] Result view_pack(const View &view, const Other &other, std::index_sequence<GLhs...>, std::index_sequence<ELhs...>, std::index_sequence<GRhs...>, std::index_sequence<ERhs...>) {
- Result elem{};
- // friend-initialization, avoid multiple calls to refresh
- elem.pools = {view.template storage<GLhs>()..., other.template storage<GRhs>()...};
- auto filter_or_placeholder = [placeholder = elem.placeholder](auto *value) { return (value == nullptr) ? placeholder : value; };
- elem.filter = {filter_or_placeholder(view.template storage<sizeof...(GLhs) + ELhs>())..., filter_or_placeholder(other.template storage<sizeof...(GRhs) + ERhs>())...};
- elem.refresh();
- return elem;
- }
- template<typename Type, bool Checked, std::size_t Get, std::size_t Exclude>
- class view_iterator final {
- template<typename, typename...>
- friend class extended_view_iterator;
- using iterator_type = typename Type::const_iterator;
- using iterator_traits = std::iterator_traits<iterator_type>;
- [[nodiscard]] bool valid(const typename iterator_traits::value_type entt) const noexcept {
- return (!Checked || (entt != tombstone))
- && ((Get == 1u) || (internal::all_of(pools.begin(), pools.begin() + index, entt) && internal::all_of(pools.begin() + index + 1, pools.end(), entt)))
- && ((Exclude == 0u) || internal::none_of(filter.begin(), filter.end(), entt));
- }
- void seek_next() {
- for(constexpr iterator_type sentinel{}; it != sentinel && !valid(*it); ++it) {}
- }
- public:
- using value_type = typename iterator_traits::value_type;
- using pointer = typename iterator_traits::pointer;
- using reference = typename iterator_traits::reference;
- using difference_type = typename iterator_traits::difference_type;
- using iterator_category = std::forward_iterator_tag;
- constexpr view_iterator() noexcept
- : it{},
- pools{},
- filter{},
- index{} {}
- view_iterator(iterator_type first, std::array<const Type *, Get> value, std::array<const Type *, Exclude> excl, const std::size_t idx) noexcept
- : it{first},
- pools{value},
- filter{excl},
- index{static_cast<difference_type>(idx)} {
- ENTT_ASSERT((Get != 1u) || (Exclude != 0u) || pools[0u]->policy() == deletion_policy::in_place, "Non in-place storage view iterator");
- seek_next();
- }
- view_iterator &operator++() noexcept {
- ++it;
- seek_next();
- return *this;
- }
- view_iterator operator++(int) noexcept {
- const view_iterator orig = *this;
- return ++(*this), orig;
- }
- [[nodiscard]] pointer operator->() const noexcept {
- return &*it;
- }
- [[nodiscard]] reference operator*() const noexcept {
- return *operator->();
- }
- template<typename LhsType, auto... LhsArgs, typename RhsType, auto... RhsArgs>
- friend constexpr bool operator==(const view_iterator<LhsType, LhsArgs...> &, const view_iterator<RhsType, RhsArgs...> &) noexcept;
- private:
- iterator_type it;
- std::array<const Type *, Get> pools;
- std::array<const Type *, Exclude> filter;
- difference_type index;
- };
- template<typename LhsType, auto... LhsArgs, typename RhsType, auto... RhsArgs>
- [[nodiscard]] constexpr bool operator==(const view_iterator<LhsType, LhsArgs...> &lhs, const view_iterator<RhsType, RhsArgs...> &rhs) noexcept {
- return lhs.it == rhs.it;
- }
- template<typename LhsType, auto... LhsArgs, typename RhsType, auto... RhsArgs>
- [[nodiscard]] constexpr bool operator!=(const view_iterator<LhsType, LhsArgs...> &lhs, const view_iterator<RhsType, RhsArgs...> &rhs) noexcept {
- return !(lhs == rhs);
- }
- template<typename It, typename... Get>
- class extended_view_iterator final {
- template<std::size_t... Index>
- [[nodiscard]] auto dereference(std::index_sequence<Index...>) const noexcept {
- return std::tuple_cat(std::make_tuple(*it), static_cast<Get *>(const_cast<constness_as_t<typename Get::base_type, Get> *>(std::get<Index>(it.pools)))->get_as_tuple(*it)...);
- }
- public:
- using iterator_type = It;
- using value_type = decltype(std::tuple_cat(std::make_tuple(*std::declval<It>()), std::declval<Get>().get_as_tuple({})...));
- using pointer = input_iterator_pointer<value_type>;
- using reference = value_type;
- using difference_type = std::ptrdiff_t;
- using iterator_category = std::input_iterator_tag;
- using iterator_concept = std::forward_iterator_tag;
- constexpr extended_view_iterator()
- : it{} {}
- extended_view_iterator(iterator_type from)
- : it{from} {}
- extended_view_iterator &operator++() noexcept {
- return ++it, *this;
- }
- extended_view_iterator operator++(int) noexcept {
- const extended_view_iterator orig = *this;
- return ++(*this), orig;
- }
- [[nodiscard]] reference operator*() const noexcept {
- return dereference(std::index_sequence_for<Get...>{});
- }
- [[nodiscard]] pointer operator->() const noexcept {
- return operator*();
- }
- [[nodiscard]] constexpr iterator_type base() const noexcept {
- return it;
- }
- template<typename... Lhs, typename... Rhs>
- friend bool constexpr operator==(const extended_view_iterator<Lhs...> &, const extended_view_iterator<Rhs...> &) noexcept;
- private:
- It it;
- };
- template<typename... Lhs, typename... Rhs>
- [[nodiscard]] constexpr bool operator==(const extended_view_iterator<Lhs...> &lhs, const extended_view_iterator<Rhs...> &rhs) noexcept {
- return lhs.it == rhs.it;
- }
- template<typename... Lhs, typename... Rhs>
- [[nodiscard]] constexpr bool operator!=(const extended_view_iterator<Lhs...> &lhs, const extended_view_iterator<Rhs...> &rhs) noexcept {
- return !(lhs == rhs);
- }
- } // namespace internal
- /*! @endcond */
- /**
- * @brief View implementation.
- *
- * Primary template isn't defined on purpose. All the specializations give a
- * compile-time error, but for a few reasonable cases.
- *
- * @b Important
- *
- * View iterators aren't invalidated if:
- *
- * * New elements are added to the storage iterated by the view.
- * * The entity currently returned is modified (for example, elements are added
- * or removed from it).
- * * The entity currently returned is destroyed.
- *
- * In all other cases, modifying the storage iterated by a view in any way can
- * invalidate all iterators.
- */
- template<typename, typename, typename>
- class basic_view;
- /**
- * @brief Basic storage view implementation.
- * @warning For internal use only, backward compatibility not guaranteed.
- * @tparam Type Common type among all storage types.
- * @tparam Checked True to enable the tombstone check, false otherwise.
- * @tparam Get Number of storage iterated by the view.
- * @tparam Exclude Number of storage used to filter the view.
- */
- template<typename Type, bool Checked, std::size_t Get, std::size_t Exclude>
- class basic_common_view {
- static_assert(std::is_same_v<std::remove_const_t<std::remove_reference_t<Type>>, Type>, "Unexpected type");
- template<typename Return, typename View, typename Other, std::size_t... GLhs, std::size_t... ELhs, std::size_t... GRhs, std::size_t... ERhs>
- friend Return internal::view_pack(const View &, const Other &, std::index_sequence<GLhs...>, std::index_sequence<ELhs...>, std::index_sequence<GRhs...>, std::index_sequence<ERhs...>);
- [[nodiscard]] auto offset() const noexcept {
- ENTT_ASSERT(index != Get, "Invalid view");
- return (pools[index]->policy() == deletion_policy::swap_only) ? pools[index]->free_list() : pools[index]->size();
- }
- void unchecked_refresh() noexcept {
- index = 0u;
- if constexpr(Get > 1u) {
- for(size_type pos{1u}; pos < Get; ++pos) {
- if(pools[pos]->size() < pools[index]->size()) {
- index = pos;
- }
- }
- }
- }
- protected:
- /*! @cond TURN_OFF_DOXYGEN */
- basic_common_view() noexcept {
- for(size_type pos{}, last = filter.size(); pos < last; ++pos) {
- filter[pos] = placeholder;
- }
- }
- basic_common_view(std::array<const Type *, Get> value, std::array<const Type *, Exclude> excl) noexcept
- : pools{value},
- filter{excl},
- index{Get} {
- unchecked_refresh();
- }
- [[nodiscard]] const Type *pool_at(const std::size_t pos) const noexcept {
- return pools[pos];
- }
- void pool_at(const std::size_t pos, const Type *elem) noexcept {
- ENTT_ASSERT(elem != nullptr, "Unexpected element");
- pools[pos] = elem;
- refresh();
- }
- [[nodiscard]] const Type *filter_at(const std::size_t pos) const noexcept {
- return (filter[pos] == placeholder) ? nullptr : filter[pos];
- }
- void filter_at(const std::size_t pos, const Type *elem) noexcept {
- ENTT_ASSERT(elem != nullptr, "Unexpected element");
- filter[pos] = elem;
- }
- [[nodiscard]] bool none_of(const typename Type::entity_type entt) const noexcept {
- return internal::none_of(filter.begin(), filter.end(), entt);
- }
- void use(const std::size_t pos) noexcept {
- index = (index != Get) ? pos : Get;
- }
- /*! @endcond */
- public:
- /*! @brief Common type among all storage types. */
- using common_type = Type;
- /*! @brief Underlying entity identifier. */
- using entity_type = typename Type::entity_type;
- /*! @brief Unsigned integer type. */
- using size_type = std::size_t;
- /*! @brief Signed integer type. */
- using difference_type = std::ptrdiff_t;
- /*! @brief Forward iterator type. */
- using iterator = internal::view_iterator<common_type, Checked, Get, Exclude>;
- /*! @brief Updates the internal leading view if required. */
- void refresh() noexcept {
- size_type pos = static_cast<size_type>(index != Get) * Get;
- for(; pos < Get && pools[pos] != nullptr; ++pos) {}
- if(pos == Get) {
- unchecked_refresh();
- }
- }
- /**
- * @brief Returns the leading storage of a view, if any.
- * @return The leading storage of the view.
- */
- [[nodiscard]] const common_type *handle() const noexcept {
- return (index != Get) ? pools[index] : nullptr;
- }
- /**
- * @brief Estimates the number of entities iterated by the view.
- * @return Estimated number of entities iterated by the view.
- */
- [[nodiscard]] size_type size_hint() const noexcept {
- return (index != Get) ? offset() : size_type{};
- }
- /**
- * @brief Returns an iterator to the first entity of the view.
- *
- * If the view is empty, the returned iterator will be equal to `end()`.
- *
- * @return An iterator to the first entity of the view.
- */
- [[nodiscard]] iterator begin() const noexcept {
- return (index != Get) ? iterator{pools[index]->end() - static_cast<difference_type>(offset()), pools, filter, index} : iterator{};
- }
- /**
- * @brief Returns an iterator that is past the last entity of the view.
- * @return An iterator to the entity following the last entity of the view.
- */
- [[nodiscard]] iterator end() const noexcept {
- return (index != Get) ? iterator{pools[index]->end(), pools, filter, index} : iterator{};
- }
- /**
- * @brief Returns the first entity of the view, if any.
- * @return The first entity of the view if one exists, the null entity
- * otherwise.
- */
- [[nodiscard]] entity_type front() const noexcept {
- const auto it = begin();
- return it != end() ? *it : null;
- }
- /**
- * @brief Returns the last entity of the view, if any.
- * @return The last entity of the view if one exists, the null entity
- * otherwise.
- */
- [[nodiscard]] entity_type back() const noexcept {
- if(index != Get) {
- auto it = pools[index]->rbegin();
- const auto last = it + static_cast<difference_type>(offset());
- for(const auto idx = static_cast<difference_type>(index); it != last && !(internal::all_of(pools.begin(), pools.begin() + idx, *it) && internal::all_of(pools.begin() + idx + 1, pools.end(), *it) && internal::none_of(filter.begin(), filter.end(), *it)); ++it) {}
- return it == last ? null : *it;
- }
- return null;
- }
- /**
- * @brief Finds an entity.
- * @param entt A valid identifier.
- * @return An iterator to the given entity if it's found, past the end
- * iterator otherwise.
- */
- [[nodiscard]] iterator find(const entity_type entt) const noexcept {
- return contains(entt) ? iterator{pools[index]->find(entt), pools, filter, index} : end();
- }
- /**
- * @brief Checks if a view is fully initialized.
- * @return True if the view is fully initialized, false otherwise.
- */
- [[nodiscard]] explicit operator bool() const noexcept {
- return (index != Get) && internal::fully_initialized(filter.begin(), filter.end(), placeholder);
- }
- /**
- * @brief Checks if a view contains an entity.
- * @param entt A valid identifier.
- * @return True if the view contains the given entity, false otherwise.
- */
- [[nodiscard]] bool contains(const entity_type entt) const noexcept {
- return (index != Get)
- && internal::all_of(pools.begin(), pools.end(), entt)
- && internal::none_of(filter.begin(), filter.end(), entt)
- && pools[index]->index(entt) < offset();
- }
- private:
- std::array<const common_type *, Get> pools{};
- std::array<const common_type *, Exclude> filter{};
- const common_type *placeholder{internal::view_placeholder<common_type>()};
- size_type index{Get};
- };
- /**
- * @brief General purpose view.
- *
- * This view visits all entities that are at least in the given storage. During
- * initialization, it also looks at the number of elements available for each
- * storage and uses the smallest set in order to get a performance boost.
- *
- * @sa basic_view
- *
- * @tparam Get Types of storage iterated by the view.
- * @tparam Exclude Types of storage used to filter the view.
- */
- template<typename... Get, typename... Exclude>
- class basic_view<get_t<Get...>, exclude_t<Exclude...>, std::enable_if_t<(sizeof...(Get) != 0u)>>
- : public basic_common_view<std::common_type_t<typename Get::base_type...>, internal::tombstone_check_v<Get...>, sizeof...(Get), sizeof...(Exclude)> {
- using base_type = basic_common_view<std::common_type_t<typename Get::base_type...>, internal::tombstone_check_v<Get...>, sizeof...(Get), sizeof...(Exclude)>;
- template<std::size_t Index>
- using element_at = type_list_element_t<Index, type_list<Get..., Exclude...>>;
- template<typename Type>
- static constexpr std::size_t index_of = type_list_index_v<std::remove_const_t<Type>, type_list<typename Get::element_type..., typename Exclude::element_type...>>;
- template<std::size_t... Index>
- [[nodiscard]] auto get(const typename base_type::entity_type entt, std::index_sequence<Index...>) const noexcept {
- return std::tuple_cat(storage<Index>()->get_as_tuple(entt)...);
- }
- template<std::size_t Curr, std::size_t Other, typename... Args>
- [[nodiscard]] auto dispatch_get(const std::tuple<typename base_type::entity_type, Args...> &curr) const {
- if constexpr(Curr == Other) {
- return std::forward_as_tuple(std::get<Args>(curr)...);
- } else {
- return storage<Other>()->get_as_tuple(std::get<0>(curr));
- }
- }
- template<std::size_t Curr, typename Func, std::size_t... Index>
- void each(Func &func, std::index_sequence<Index...>) const {
- for(const auto curr: storage<Curr>()->each()) {
- if(const auto entt = std::get<0>(curr); (!internal::tombstone_check_v<Get...> || (entt != tombstone)) && ((Curr == Index || base_type::pool_at(Index)->contains(entt)) && ...) && base_type::none_of(entt)) {
- if constexpr(is_applicable_v<Func, decltype(std::tuple_cat(std::tuple<entity_type>{}, std::declval<basic_view>().get({})))>) {
- std::apply(func, std::tuple_cat(std::make_tuple(entt), dispatch_get<Curr, Index>(curr)...));
- } else {
- std::apply(func, std::tuple_cat(dispatch_get<Curr, Index>(curr)...));
- }
- }
- }
- }
- template<typename Func, std::size_t... Index>
- void pick_and_each(Func &func, std::index_sequence<Index...> seq) const {
- if(const auto *view = base_type::handle(); view != nullptr) {
- ((view == base_type::pool_at(Index) ? each<Index>(func, seq) : void()), ...);
- }
- }
- public:
- /*! @brief Common type among all storage types. */
- using common_type = typename base_type::common_type;
- /*! @brief Underlying entity identifier. */
- using entity_type = typename base_type::entity_type;
- /*! @brief Unsigned integer type. */
- using size_type = typename base_type::size_type;
- /*! @brief Signed integer type. */
- using difference_type = std::ptrdiff_t;
- /*! @brief Forward iterator type. */
- using iterator = typename base_type::iterator;
- /*! @brief Iterable view type. */
- using iterable = iterable_adaptor<internal::extended_view_iterator<iterator, Get...>>;
- /*! @brief Default constructor to use to create empty, invalid views. */
- basic_view() noexcept
- : base_type{} {}
- /**
- * @brief Constructs a view from a set of storage classes.
- * @param value The storage for the types to iterate.
- * @param excl The storage for the types used to filter the view.
- */
- basic_view(Get &...value, Exclude &...excl) noexcept
- : base_type{{&value...}, {&excl...}} {
- }
- /**
- * @brief Constructs a view from a set of storage classes.
- * @param value The storage for the types to iterate.
- * @param excl The storage for the types used to filter the view.
- */
- basic_view(std::tuple<Get &...> value, std::tuple<Exclude &...> excl = {}) noexcept
- : basic_view{std::make_from_tuple<basic_view>(std::tuple_cat(value, excl))} {}
- /**
- * @brief Forces a view to use a given element to drive iterations
- * @tparam Type Type of element to use to drive iterations.
- */
- template<typename Type>
- void use() noexcept {
- use<index_of<Type>>();
- }
- /**
- * @brief Forces a view to use a given element to drive iterations
- * @tparam Index Index of the element to use to drive iterations.
- */
- template<std::size_t Index>
- void use() noexcept {
- base_type::use(Index);
- }
- /**
- * @brief Returns the storage for a given element type, if any.
- * @tparam Type Type of element of which to return the storage.
- * @return The storage for the given element type.
- */
- template<typename Type>
- [[nodiscard]] auto *storage() const noexcept {
- return storage<index_of<Type>>();
- }
- /**
- * @brief Returns the storage for a given index, if any.
- * @tparam Index Index of the storage to return.
- * @return The storage for the given index.
- */
- template<std::size_t Index>
- [[nodiscard]] auto *storage() const noexcept {
- if constexpr(Index < sizeof...(Get)) {
- return static_cast<element_at<Index> *>(const_cast<constness_as_t<common_type, element_at<Index>> *>(base_type::pool_at(Index)));
- } else {
- return static_cast<element_at<Index> *>(const_cast<constness_as_t<common_type, element_at<Index>> *>(base_type::filter_at(Index - sizeof...(Get))));
- }
- }
- /**
- * @brief Assigns a storage to a view.
- * @tparam Type Type of storage to assign to the view.
- * @param elem A storage to assign to the view.
- */
- template<typename Type>
- void storage(Type &elem) noexcept {
- storage<index_of<typename Type::element_type>>(elem);
- }
- /**
- * @brief Assigns a storage to a view.
- * @tparam Index Index of the storage to assign to the view.
- * @tparam Type Type of storage to assign to the view.
- * @param elem A storage to assign to the view.
- */
- template<std::size_t Index, typename Type>
- void storage(Type &elem) noexcept {
- static_assert(std::is_convertible_v<Type &, element_at<Index> &>, "Unexpected type");
- if constexpr(Index < sizeof...(Get)) {
- base_type::pool_at(Index, &elem);
- } else {
- base_type::filter_at(Index - sizeof...(Get), &elem);
- }
- }
- /**
- * @brief Returns the elements assigned to the given entity.
- * @param entt A valid identifier.
- * @return The elements assigned to the given entity.
- */
- [[nodiscard]] decltype(auto) operator[](const entity_type entt) const {
- return get(entt);
- }
- /**
- * @brief Returns the elements assigned to the given entity.
- * @tparam Type Type of the element to get.
- * @tparam Other Other types of elements to get.
- * @param entt A valid identifier.
- * @return The elements assigned to the entity.
- */
- template<typename Type, typename... Other>
- [[nodiscard]] decltype(auto) get(const entity_type entt) const {
- return get<index_of<Type>, index_of<Other>...>(entt);
- }
- /**
- * @brief Returns the elements assigned to the given entity.
- * @tparam Index Indexes of the elements to get.
- * @param entt A valid identifier.
- * @return The elements assigned to the entity.
- */
- template<std::size_t... Index>
- [[nodiscard]] decltype(auto) get(const entity_type entt) const {
- if constexpr(sizeof...(Index) == 0) {
- return get(entt, std::index_sequence_for<Get...>{});
- } else if constexpr(sizeof...(Index) == 1) {
- return (storage<Index>()->get(entt), ...);
- } else {
- return std::tuple_cat(storage<Index>()->get_as_tuple(entt)...);
- }
- }
- /**
- * @brief Iterates entities and elements and applies the given function
- * object to them.
- *
- * The signature of the function must be equivalent to one of the following
- * (non-empty types only, constness as requested):
- *
- * @code{.cpp}
- * void(const entity_type, Type &...);
- * void(Type &...);
- * @endcode
- *
- * @tparam Func Type of the function object to invoke.
- * @param func A valid function object.
- */
- template<typename Func>
- void each(Func func) const {
- pick_and_each(func, std::index_sequence_for<Get...>{});
- }
- /**
- * @brief Returns an iterable object to use to _visit_ a view.
- *
- * The iterable object returns a tuple that contains the current entity and
- * a set of references to its non-empty elements. The _constness_ of the
- * elements is as requested.
- *
- * @return An iterable object to use to _visit_ the view.
- */
- [[nodiscard]] iterable each() const noexcept {
- return iterable{base_type::begin(), base_type::end()};
- }
- /**
- * @brief Combines a view and a storage in _more specific_ view.
- * @tparam OGet Type of storage to combine the view with.
- * @param other The storage for the type to combine the view with.
- * @return A more specific view.
- */
- template<typename OGet>
- [[nodiscard]] std::enable_if_t<std::is_base_of_v<common_type, OGet>, basic_view<get_t<Get..., OGet>, exclude_t<Exclude...>>> operator|(OGet &other) const noexcept {
- return *this | basic_view<get_t<OGet>, exclude_t<>>{other};
- }
- /**
- * @brief Combines two views in a _more specific_ one.
- * @tparam OGet Element list of the view to combine with.
- * @tparam OExclude Filter list of the view to combine with.
- * @param other The view to combine with.
- * @return A more specific view.
- */
- template<typename... OGet, typename... OExclude>
- [[nodiscard]] auto operator|(const basic_view<get_t<OGet...>, exclude_t<OExclude...>> &other) const noexcept {
- return internal::view_pack<basic_view<get_t<Get..., OGet...>, exclude_t<Exclude..., OExclude...>>>(
- *this, other, std::index_sequence_for<Get...>{}, std::index_sequence_for<Exclude...>{}, std::index_sequence_for<OGet...>{}, std::index_sequence_for<OExclude...>{});
- }
- };
- /**
- * @brief Basic storage view implementation.
- * @warning For internal use only, backward compatibility not guaranteed.
- * @tparam Type Common type among all storage types.
- * @tparam Policy Storage policy.
- */
- template<typename Type, deletion_policy Policy>
- class basic_storage_view {
- static_assert(std::is_same_v<std::remove_const_t<std::remove_reference_t<Type>>, Type>, "Unexpected type");
- protected:
- /*! @cond TURN_OFF_DOXYGEN */
- basic_storage_view() noexcept = default;
- basic_storage_view(const Type *value) noexcept
- : leading{value} {
- ENTT_ASSERT(leading->policy() == Policy, "Unexpected storage policy");
- }
- /*! @endcond */
- public:
- /*! @brief Common type among all storage types. */
- using common_type = Type;
- /*! @brief Underlying entity identifier. */
- using entity_type = typename common_type::entity_type;
- /*! @brief Unsigned integer type. */
- using size_type = std::size_t;
- /*! @brief Signed integer type. */
- using difference_type = std::ptrdiff_t;
- /*! @brief Random access iterator type. */
- using iterator = std::conditional_t<Policy == deletion_policy::in_place, internal::view_iterator<common_type, true, 1u, 0u>, typename common_type::iterator>;
- /*! @brief Reverse iterator type. */
- using reverse_iterator = std::conditional_t<Policy == deletion_policy::in_place, void, typename common_type::reverse_iterator>;
- /**
- * @brief Returns the leading storage of a view, if any.
- * @return The leading storage of the view.
- */
- [[nodiscard]] const common_type *handle() const noexcept {
- return leading;
- }
- /**
- * @brief Returns the number of entities that have the given element.
- * @tparam Pol Dummy template parameter used for sfinae purposes only.
- * @return Number of entities that have the given element.
- */
- template<typename..., deletion_policy Pol = Policy>
- [[nodiscard]] std::enable_if_t<Pol != deletion_policy::in_place, size_type> size() const noexcept {
- if constexpr(Policy == deletion_policy::swap_and_pop) {
- return leading ? leading->size() : size_type{};
- } else {
- static_assert(Policy == deletion_policy::swap_only, "Unexpected storage policy");
- return leading ? leading->free_list() : size_type{};
- }
- }
- /**
- * @brief Estimates the number of entities iterated by the view.
- * @tparam Pol Dummy template parameter used for sfinae purposes only.
- * @return Estimated number of entities iterated by the view.
- */
- template<typename..., deletion_policy Pol = Policy>
- [[nodiscard]] std::enable_if_t<Pol == deletion_policy::in_place, size_type> size_hint() const noexcept {
- return leading ? leading->size() : size_type{};
- }
- /**
- * @brief Checks whether a view is empty.
- * @tparam Pol Dummy template parameter used for sfinae purposes only.
- * @return True if the view is empty, false otherwise.
- */
- template<typename..., deletion_policy Pol = Policy>
- [[nodiscard]] std::enable_if_t<Pol != deletion_policy::in_place, bool> empty() const noexcept {
- if constexpr(Policy == deletion_policy::swap_and_pop) {
- return !leading || leading->empty();
- } else {
- static_assert(Policy == deletion_policy::swap_only, "Unexpected storage policy");
- return !leading || (leading->free_list() == 0u);
- }
- }
- /**
- * @brief Returns an iterator to the first entity of the view.
- *
- * If the view is empty, the returned iterator will be equal to `end()`.
- *
- * @return An iterator to the first entity of the view.
- */
- [[nodiscard]] iterator begin() const noexcept {
- if constexpr(Policy == deletion_policy::swap_and_pop) {
- return leading ? leading->begin() : iterator{};
- } else if constexpr(Policy == deletion_policy::swap_only) {
- return leading ? (leading->end() - static_cast<difference_type>(leading->free_list())) : iterator{};
- } else {
- static_assert(Policy == deletion_policy::in_place, "Unexpected storage policy");
- return leading ? iterator{leading->begin(), {leading}, {}, 0u} : iterator{};
- }
- }
- /**
- * @brief Returns an iterator that is past the last entity of the view.
- * @return An iterator to the entity following the last entity of the view.
- */
- [[nodiscard]] iterator end() const noexcept {
- if constexpr(Policy == deletion_policy::swap_and_pop || Policy == deletion_policy::swap_only) {
- return leading ? leading->end() : iterator{};
- } else {
- static_assert(Policy == deletion_policy::in_place, "Unexpected storage policy");
- return leading ? iterator{leading->end(), {leading}, {}, 0u} : iterator{};
- }
- }
- /**
- * @brief Returns an iterator to the first entity of the reversed view.
- *
- * If the view is empty, the returned iterator will be equal to `rend()`.
- *
- * @tparam Pol Dummy template parameter used for sfinae purposes only.
- * @return An iterator to the first entity of the reversed view.
- */
- template<typename..., deletion_policy Pol = Policy>
- [[nodiscard]] std::enable_if_t<Pol != deletion_policy::in_place, reverse_iterator> rbegin() const noexcept {
- return leading ? leading->rbegin() : reverse_iterator{};
- }
- /**
- * @brief Returns an iterator that is past the last entity of the reversed
- * view.
- * @tparam Pol Dummy template parameter used for sfinae purposes only.
- * @return An iterator to the entity following the last entity of the
- * reversed view.
- */
- template<typename..., deletion_policy Pol = Policy>
- [[nodiscard]] std::enable_if_t<Pol != deletion_policy::in_place, reverse_iterator> rend() const noexcept {
- if constexpr(Policy == deletion_policy::swap_and_pop) {
- return leading ? leading->rend() : reverse_iterator{};
- } else {
- static_assert(Policy == deletion_policy::swap_only, "Unexpected storage policy");
- return leading ? (leading->rbegin() + static_cast<difference_type>(leading->free_list())) : reverse_iterator{};
- }
- }
- /**
- * @brief Returns the first entity of the view, if any.
- * @return The first entity of the view if one exists, the null entity
- * otherwise.
- */
- [[nodiscard]] entity_type front() const noexcept {
- if constexpr(Policy == deletion_policy::swap_and_pop) {
- return empty() ? null : *leading->begin();
- } else if constexpr(Policy == deletion_policy::swap_only) {
- return empty() ? null : *(leading->end() - static_cast<difference_type>(leading->free_list()));
- } else {
- static_assert(Policy == deletion_policy::in_place, "Unexpected storage policy");
- const auto it = begin();
- return (it == end()) ? null : *it;
- }
- }
- /**
- * @brief Returns the last entity of the view, if any.
- * @return The last entity of the view if one exists, the null entity
- * otherwise.
- */
- [[nodiscard]] entity_type back() const noexcept {
- if constexpr(Policy == deletion_policy::swap_and_pop || Policy == deletion_policy::swap_only) {
- return empty() ? null : *leading->rbegin();
- } else {
- static_assert(Policy == deletion_policy::in_place, "Unexpected storage policy");
- if(leading) {
- auto it = leading->rbegin();
- const auto last = leading->rend();
- for(; (it != last) && (*it == tombstone); ++it) {}
- return it == last ? null : *it;
- }
- return null;
- }
- }
- /**
- * @brief Finds an entity.
- * @param entt A valid identifier.
- * @return An iterator to the given entity if it's found, past the end
- * iterator otherwise.
- */
- [[nodiscard]] iterator find(const entity_type entt) const noexcept {
- if constexpr(Policy == deletion_policy::swap_and_pop) {
- return leading ? leading->find(entt) : iterator{};
- } else if constexpr(Policy == deletion_policy::swap_only) {
- const auto it = leading ? leading->find(entt) : iterator{};
- return leading && (static_cast<size_type>(it.index()) < leading->free_list()) ? it : iterator{};
- } else {
- return leading ? iterator{leading->find(entt), {leading}, {}, 0u} : iterator{};
- }
- }
- /**
- * @brief Checks if a view is fully initialized.
- * @return True if the view is fully initialized, false otherwise.
- */
- [[nodiscard]] explicit operator bool() const noexcept {
- return (leading != nullptr);
- }
- /**
- * @brief Checks if a view contains an entity.
- * @param entt A valid identifier.
- * @return True if the view contains the given entity, false otherwise.
- */
- [[nodiscard]] bool contains(const entity_type entt) const noexcept {
- if constexpr(Policy == deletion_policy::swap_and_pop || Policy == deletion_policy::in_place) {
- return leading && leading->contains(entt);
- } else {
- static_assert(Policy == deletion_policy::swap_only, "Unexpected storage policy");
- return leading && leading->contains(entt) && (leading->index(entt) < leading->free_list());
- }
- }
- private:
- const common_type *leading{};
- };
- /**
- * @brief Storage view specialization.
- *
- * This specialization offers a boost in terms of performance. It can access the
- * underlying data structure directly and avoid superfluous checks.
- *
- * @sa basic_view
- *
- * @tparam Get Type of storage iterated by the view.
- */
- template<typename Get>
- class basic_view<get_t<Get>, exclude_t<>>
- : public basic_storage_view<typename Get::base_type, Get::storage_policy> {
- using base_type = basic_storage_view<typename Get::base_type, Get::storage_policy>;
- public:
- /*! @brief Common type among all storage types. */
- using common_type = typename base_type::common_type;
- /*! @brief Underlying entity identifier. */
- using entity_type = typename base_type::entity_type;
- /*! @brief Unsigned integer type. */
- using size_type = typename base_type::size_type;
- /*! @brief Signed integer type. */
- using difference_type = std::ptrdiff_t;
- /*! @brief Random access iterator type. */
- using iterator = typename base_type::iterator;
- /*! @brief Reverse iterator type. */
- using reverse_iterator = typename base_type::reverse_iterator;
- /*! @brief Iterable view type. */
- using iterable = std::conditional_t<Get::storage_policy == deletion_policy::in_place, iterable_adaptor<internal::extended_view_iterator<iterator, Get>>, decltype(std::declval<Get>().each())>;
- /*! @brief Default constructor to use to create empty, invalid views. */
- basic_view() noexcept
- : base_type{} {}
- /**
- * @brief Constructs a view from a storage class.
- * @param value The storage for the type to iterate.
- */
- basic_view(Get &value) noexcept
- : base_type{&value} {
- }
- /**
- * @brief Constructs a view from a storage class.
- * @param value The storage for the type to iterate.
- */
- basic_view(std::tuple<Get &> value, std::tuple<> = {}) noexcept
- : basic_view{std::get<0>(value)} {}
- /**
- * @brief Returns the storage for a given element type, if any.
- * @tparam Type Type of element of which to return the storage.
- * @return The storage for the given element type.
- */
- template<typename Type = typename Get::element_type>
- [[nodiscard]] auto *storage() const noexcept {
- static_assert(std::is_same_v<std::remove_const_t<Type>, typename Get::element_type>, "Invalid element type");
- return storage<0>();
- }
- /**
- * @brief Returns the storage for a given index, if any.
- * @tparam Index Index of the storage to return.
- * @return The storage for the given index.
- */
- template<std::size_t Index>
- [[nodiscard]] auto *storage() const noexcept {
- static_assert(Index == 0u, "Index out of bounds");
- return static_cast<Get *>(const_cast<constness_as_t<common_type, Get> *>(base_type::handle()));
- }
- /**
- * @brief Assigns a storage to a view.
- * @param elem A storage to assign to the view.
- */
- void storage(Get &elem) noexcept {
- storage<0>(elem);
- }
- /**
- * @brief Assigns a storage to a view.
- * @tparam Index Index of the storage to assign to the view.
- * @param elem A storage to assign to the view.
- */
- template<std::size_t Index>
- void storage(Get &elem) noexcept {
- static_assert(Index == 0u, "Index out of bounds");
- *this = basic_view{elem};
- }
- /**
- * @brief Returns a pointer to the underlying storage.
- * @return A pointer to the underlying storage.
- */
- [[nodiscard]] Get *operator->() const noexcept {
- return storage();
- }
- /**
- * @brief Returns the element assigned to the given entity.
- * @param entt A valid identifier.
- * @return The element assigned to the given entity.
- */
- [[nodiscard]] decltype(auto) operator[](const entity_type entt) const {
- return storage()->get(entt);
- }
- /**
- * @brief Returns the element assigned to the given entity.
- * @tparam Elem Type of the element to get.
- * @param entt A valid identifier.
- * @return The element assigned to the entity.
- */
- template<typename Elem>
- [[nodiscard]] decltype(auto) get(const entity_type entt) const {
- static_assert(std::is_same_v<std::remove_const_t<Elem>, typename Get::element_type>, "Invalid element type");
- return get<0>(entt);
- }
- /**
- * @brief Returns the element assigned to the given entity.
- * @tparam Index Index of the element to get.
- * @param entt A valid identifier.
- * @return The element assigned to the entity.
- */
- template<std::size_t... Index>
- [[nodiscard]] decltype(auto) get(const entity_type entt) const {
- if constexpr(sizeof...(Index) == 0) {
- return storage()->get_as_tuple(entt);
- } else {
- return storage<Index...>()->get(entt);
- }
- }
- /**
- * @brief Iterates entities and elements and applies the given function
- * object to them.
- *
- * The signature of the function must be equivalent to one of the following
- * (non-empty types only, constness as requested):
- *
- * @code{.cpp}
- * void(const entity_type, Type &);
- * void(typename Type &);
- * @endcode
- *
- * @tparam Func Type of the function object to invoke.
- * @param func A valid function object.
- */
- template<typename Func>
- void each(Func func) const {
- if constexpr(is_applicable_v<Func, decltype(std::tuple_cat(std::tuple<entity_type>{}, std::declval<basic_view>().get({})))>) {
- for(const auto pack: each()) {
- std::apply(func, pack);
- }
- } else if constexpr(Get::storage_policy == deletion_policy::swap_and_pop || Get::storage_policy == deletion_policy::swap_only) {
- if constexpr(std::is_void_v<typename Get::value_type>) {
- for(size_type pos = base_type::size(); pos; --pos) {
- func();
- }
- } else {
- if(const auto len = static_cast<difference_type>(base_type::size()); len != 0) {
- for(auto last = storage()->end(), first = last - len; first != last; ++first) {
- func(*first);
- }
- }
- }
- } else {
- static_assert(Get::storage_policy == deletion_policy::in_place, "Unexpected storage policy");
- for(const auto pack: each()) {
- std::apply([&func](const auto, auto &&...elem) { func(std::forward<decltype(elem)>(elem)...); }, pack);
- }
- }
- }
- /**
- * @brief Returns an iterable object to use to _visit_ a view.
- *
- * The iterable object returns a tuple that contains the current entity and
- * a reference to its element if it's a non-empty one. The _constness_ of
- * the element is as requested.
- *
- * @return An iterable object to use to _visit_ the view.
- */
- [[nodiscard]] iterable each() const noexcept {
- if constexpr(Get::storage_policy == deletion_policy::swap_and_pop || Get::storage_policy == deletion_policy::swap_only) {
- return base_type::handle() ? storage()->each() : iterable{};
- } else {
- static_assert(Get::storage_policy == deletion_policy::in_place, "Unexpected storage policy");
- return iterable{base_type::begin(), base_type::end()};
- }
- }
- /**
- * @brief Combines a view and a storage in _more specific_ view.
- * @tparam OGet Type of storage to combine the view with.
- * @param other The storage for the type to combine the view with.
- * @return A more specific view.
- */
- template<typename OGet>
- [[nodiscard]] std::enable_if_t<std::is_base_of_v<common_type, OGet>, basic_view<get_t<Get, OGet>, exclude_t<>>> operator|(OGet &other) const noexcept {
- return *this | basic_view<get_t<OGet>, exclude_t<>>{other};
- }
- /**
- * @brief Combines two views in a _more specific_ one.
- * @tparam OGet Element list of the view to combine with.
- * @tparam OExclude Filter list of the view to combine with.
- * @param other The view to combine with.
- * @return A more specific view.
- */
- template<typename... OGet, typename... OExclude>
- [[nodiscard]] auto operator|(const basic_view<get_t<OGet...>, exclude_t<OExclude...>> &other) const noexcept {
- return internal::view_pack<basic_view<get_t<Get, OGet...>, exclude_t<OExclude...>>>(
- *this, other, std::index_sequence_for<Get>{}, std::index_sequence_for<>{}, std::index_sequence_for<OGet...>{}, std::index_sequence_for<OExclude...>{});
- }
- };
- /**
- * @brief Deduction guide.
- * @tparam Type Type of storage classes used to create the view.
- * @param storage The storage for the types to iterate.
- */
- template<typename... Type>
- basic_view(Type &...storage) -> basic_view<get_t<Type...>, exclude_t<>>;
- /**
- * @brief Deduction guide.
- * @tparam Get Types of elements iterated by the view.
- * @tparam Exclude Types of elements used to filter the view.
- */
- template<typename... Get, typename... Exclude>
- basic_view(std::tuple<Get &...>, std::tuple<Exclude &...> = {}) -> basic_view<get_t<Get...>, exclude_t<Exclude...>>;
- } // namespace entt
- #endif
- namespace entt {
- /**
- * @brief Converts a registry to a view.
- * @tparam Registry Basic registry type.
- */
- template<typename Registry>
- class as_view {
- template<typename... Get, typename... Exclude>
- [[nodiscard]] auto dispatch(get_t<Get...>, exclude_t<Exclude...>) const {
- return reg->template view<constness_as_t<typename Get::element_type, Get>...>(exclude_t<constness_as_t<typename Exclude::element_type, Exclude>...>{});
- }
- public:
- /*! @brief Type of registry to convert. */
- using registry_type = Registry;
- /*! @brief Underlying entity identifier. */
- using entity_type = typename registry_type::entity_type;
- /**
- * @brief Constructs a converter for a given registry.
- * @param source A valid reference to a registry.
- */
- as_view(registry_type &source) noexcept
- : reg{&source} {}
- /**
- * @brief Conversion function from a registry to a view.
- * @tparam Get Type of storage used to construct the view.
- * @tparam Exclude Types of storage used to filter the view.
- * @return A newly created view.
- */
- template<typename Get, typename Exclude>
- operator basic_view<Get, Exclude>() const {
- return dispatch(Get{}, Exclude{});
- }
- private:
- registry_type *reg;
- };
- /**
- * @brief Converts a registry to a group.
- * @tparam Registry Basic registry type.
- */
- template<typename Registry>
- class as_group {
- template<typename... Owned, typename... Get, typename... Exclude>
- [[nodiscard]] auto dispatch(owned_t<Owned...>, get_t<Get...>, exclude_t<Exclude...>) const {
- if constexpr(std::is_const_v<registry_type>) {
- return reg->template group_if_exists<typename Owned::element_type...>(get_t<typename Get::element_type...>{}, exclude_t<typename Exclude::element_type...>{});
- } else {
- return reg->template group<constness_as_t<typename Owned::element_type, Owned>...>(get_t<constness_as_t<typename Get::element_type, Get>...>{}, exclude_t<constness_as_t<typename Exclude::element_type, Exclude>...>{});
- }
- }
- public:
- /*! @brief Type of registry to convert. */
- using registry_type = Registry;
- /*! @brief Underlying entity identifier. */
- using entity_type = typename registry_type::entity_type;
- /**
- * @brief Constructs a converter for a given registry.
- * @param source A valid reference to a registry.
- */
- as_group(registry_type &source) noexcept
- : reg{&source} {}
- /**
- * @brief Conversion function from a registry to a group.
- * @tparam Owned Types of _owned_ by the group.
- * @tparam Get Types of storage _observed_ by the group.
- * @tparam Exclude Types of storage used to filter the group.
- * @return A newly created group.
- */
- template<typename Owned, typename Get, typename Exclude>
- operator basic_group<Owned, Get, Exclude>() const {
- return dispatch(Owned{}, Get{}, Exclude{});
- }
- private:
- registry_type *reg;
- };
- /**
- * @brief Helper to create a listener that directly invokes a member function.
- * @tparam Member Member function to invoke on an element of the given type.
- * @tparam Registry Basic registry type.
- * @param reg A registry that contains the given entity and its elements.
- * @param entt Entity from which to get the element.
- */
- template<auto Member, typename Registry = std::decay_t<nth_argument_t<0u, decltype(Member)>>>
- void invoke(Registry ®, const typename Registry::entity_type entt) {
- static_assert(std::is_member_function_pointer_v<decltype(Member)>, "Invalid pointer to non-static member function");
- (reg.template get<member_class_t<decltype(Member)>>(entt).*Member)(reg, entt);
- }
- /**
- * @brief Returns the entity associated with a given element.
- *
- * @warning
- * Currently, this function only works correctly with the default storage as it
- * makes assumptions about how the elements are laid out.
- *
- * @tparam Args Storage type template parameters.
- * @param storage A storage that contains the given element.
- * @param instance A valid element instance.
- * @return The entity associated with the given element.
- */
- template<typename... Args>
- typename basic_storage<Args...>::entity_type to_entity(const basic_storage<Args...> &storage, const typename basic_storage<Args...>::value_type &instance) {
- using traits_type = component_traits<typename basic_storage<Args...>::value_type, typename basic_storage<Args...>::entity_type>;
- static_assert(traits_type::page_size != 0u, "Unexpected page size");
- const auto *page = storage.raw();
- // NOLINTBEGIN(cppcoreguidelines-pro-bounds-pointer-arithmetic)
- for(std::size_t pos{}, count = storage.size(); pos < count; pos += traits_type::page_size, ++page) {
- if(const auto dist = (std::addressof(instance) - *page); dist >= 0 && dist < static_cast<decltype(dist)>(traits_type::page_size)) {
- return *(static_cast<const typename basic_storage<Args...>::base_type &>(storage).rbegin() + static_cast<decltype(dist)>(pos) + dist);
- }
- }
- // NOLINTEND(cppcoreguidelines-pro-bounds-pointer-arithmetic)
- return null;
- }
- /*! @brief Primary template isn't defined on purpose. */
- template<typename...>
- struct sigh_helper;
- /**
- * @brief Signal connection helper for registries.
- * @tparam Registry Basic registry type.
- */
- template<typename Registry>
- struct sigh_helper<Registry> {
- /*! @brief Registry type. */
- using registry_type = Registry;
- /**
- * @brief Constructs a helper for a given registry.
- * @param ref A valid reference to a registry.
- */
- sigh_helper(registry_type &ref)
- : bucket{&ref} {}
- /**
- * @brief Binds a properly initialized helper to a given signal type.
- * @tparam Type Type of signal to bind the helper to.
- * @param id Optional name for the underlying storage to use.
- * @return A helper for a given registry and signal type.
- */
- template<typename Type>
- auto with(const id_type id = type_hash<Type>::value()) noexcept {
- return sigh_helper<registry_type, Type>{*bucket, id};
- }
- /**
- * @brief Returns a reference to the underlying registry.
- * @return A reference to the underlying registry.
- */
- [[nodiscard]] registry_type ®istry() noexcept {
- return *bucket;
- }
- private:
- registry_type *bucket;
- };
- /**
- * @brief Signal connection helper for registries.
- * @tparam Registry Basic registry type.
- * @tparam Type Type of signal to connect listeners to.
- */
- template<typename Registry, typename Type>
- struct sigh_helper<Registry, Type> final: sigh_helper<Registry> {
- /*! @brief Registry type. */
- using registry_type = Registry;
- /**
- * @brief Constructs a helper for a given registry.
- * @param ref A valid reference to a registry.
- * @param id Optional name for the underlying storage to use.
- */
- sigh_helper(registry_type &ref, const id_type id = type_hash<Type>::value())
- : sigh_helper<Registry>{ref},
- name{id} {}
- /**
- * @brief Forwards the call to `on_construct` on the underlying storage.
- * @tparam Candidate Function or member to connect.
- * @tparam Args Type of class or type of payload, if any.
- * @param args A valid object that fits the purpose, if any.
- * @return This helper.
- */
- template<auto Candidate, typename... Args>
- auto on_construct(Args &&...args) {
- this->registry().template on_construct<Type>(name).template connect<Candidate>(std::forward<Args>(args)...);
- return *this;
- }
- /**
- * @brief Forwards the call to `on_update` on the underlying storage.
- * @tparam Candidate Function or member to connect.
- * @tparam Args Type of class or type of payload, if any.
- * @param args A valid object that fits the purpose, if any.
- * @return This helper.
- */
- template<auto Candidate, typename... Args>
- auto on_update(Args &&...args) {
- this->registry().template on_update<Type>(name).template connect<Candidate>(std::forward<Args>(args)...);
- return *this;
- }
- /**
- * @brief Forwards the call to `on_destroy` on the underlying storage.
- * @tparam Candidate Function or member to connect.
- * @tparam Args Type of class or type of payload, if any.
- * @param args A valid object that fits the purpose, if any.
- * @return This helper.
- */
- template<auto Candidate, typename... Args>
- auto on_destroy(Args &&...args) {
- this->registry().template on_destroy<Type>(name).template connect<Candidate>(std::forward<Args>(args)...);
- return *this;
- }
- private:
- id_type name;
- };
- /**
- * @brief Deduction guide.
- * @tparam Registry Basic registry type.
- */
- template<typename Registry>
- sigh_helper(Registry &) -> sigh_helper<Registry>;
- } // namespace entt
- #endif
- // #include "entity/mixin.hpp"
- #ifndef ENTT_ENTITY_MIXIN_HPP
- #define ENTT_ENTITY_MIXIN_HPP
- #include <type_traits>
- #include <utility>
- // #include "../config/config.h"
- // #include "../core/any.hpp"
- // #include "../core/type_info.hpp"
- // #include "../signal/sigh.hpp"
- #ifndef ENTT_SIGNAL_SIGH_HPP
- #define ENTT_SIGNAL_SIGH_HPP
- #include <cstddef>
- #include <memory>
- #include <type_traits>
- #include <utility>
- #include <vector>
- // #include "delegate.hpp"
- #ifndef ENTT_SIGNAL_DELEGATE_HPP
- #define ENTT_SIGNAL_DELEGATE_HPP
- #include <cstddef>
- #include <functional>
- #include <tuple>
- #include <type_traits>
- #include <utility>
- // #include "../config/config.h"
- #ifndef ENTT_CONFIG_CONFIG_H
- #define ENTT_CONFIG_CONFIG_H
- // #include "version.h"
- #ifndef ENTT_CONFIG_VERSION_H
- #define ENTT_CONFIG_VERSION_H
- // #include "macro.h"
- #ifndef ENTT_CONFIG_MACRO_H
- #define ENTT_CONFIG_MACRO_H
- // NOLINTBEGIN(cppcoreguidelines-macro-usage)
- #define ENTT_STR(arg) #arg
- #define ENTT_XSTR(arg) ENTT_STR(arg)
- // NOLINTEND(cppcoreguidelines-macro-usage)
- #endif
- // NOLINTBEGIN(cppcoreguidelines-macro-*,modernize-macro-*)
- #define ENTT_VERSION_MAJOR 3
- #define ENTT_VERSION_MINOR 16
- #define ENTT_VERSION_PATCH 0
- #define ENTT_VERSION \
- ENTT_XSTR(ENTT_VERSION_MAJOR) \
- "." ENTT_XSTR(ENTT_VERSION_MINOR) "." ENTT_XSTR(ENTT_VERSION_PATCH)
- // NOLINTEND(cppcoreguidelines-macro-*,modernize-macro-*)
- #endif
- // NOLINTBEGIN(cppcoreguidelines-macro-usage)
- #if defined(__cpp_exceptions) && !defined(ENTT_NOEXCEPTION)
- # define ENTT_CONSTEXPR
- # define ENTT_THROW throw
- # define ENTT_TRY try
- # define ENTT_CATCH catch(...)
- #else
- # define ENTT_CONSTEXPR constexpr // use only with throwing functions (waiting for C++20)
- # define ENTT_THROW
- # define ENTT_TRY if(true)
- # define ENTT_CATCH if(false)
- #endif
- #if __has_include(<version>)
- # include <version>
- #
- # if defined(__cpp_consteval)
- # define ENTT_CONSTEVAL consteval
- # endif
- #endif
- #ifndef ENTT_CONSTEVAL
- # define ENTT_CONSTEVAL constexpr
- #endif
- #ifdef ENTT_USE_ATOMIC
- # include <atomic>
- # define ENTT_MAYBE_ATOMIC(Type) std::atomic<Type>
- #else
- # define ENTT_MAYBE_ATOMIC(Type) Type
- #endif
- #ifndef ENTT_ID_TYPE
- # include <cstdint>
- # define ENTT_ID_TYPE std::uint32_t
- #else
- # include <cstdint> // provides coverage for types in the std namespace
- #endif
- #ifndef ENTT_SPARSE_PAGE
- # define ENTT_SPARSE_PAGE 4096
- #endif
- #ifndef ENTT_PACKED_PAGE
- # define ENTT_PACKED_PAGE 1024
- #endif
- #ifdef ENTT_DISABLE_ASSERT
- # undef ENTT_ASSERT
- # define ENTT_ASSERT(condition, msg) (void(0))
- #elif !defined ENTT_ASSERT
- # include <cassert>
- # define ENTT_ASSERT(condition, msg) assert(((condition) && (msg)))
- #endif
- #ifdef ENTT_DISABLE_ASSERT
- # undef ENTT_ASSERT_CONSTEXPR
- # define ENTT_ASSERT_CONSTEXPR(condition, msg) (void(0))
- #elif !defined ENTT_ASSERT_CONSTEXPR
- # define ENTT_ASSERT_CONSTEXPR(condition, msg) ENTT_ASSERT(condition, msg)
- #endif
- #define ENTT_FAIL(msg) ENTT_ASSERT(false, msg);
- #ifdef ENTT_NO_ETO
- # define ENTT_ETO_TYPE(Type) void
- #else
- # define ENTT_ETO_TYPE(Type) Type
- #endif
- #ifdef ENTT_NO_MIXIN
- # define ENTT_STORAGE(Mixin, ...) __VA_ARGS__
- #else
- # define ENTT_STORAGE(Mixin, ...) Mixin<__VA_ARGS__>
- #endif
- #ifdef ENTT_STANDARD_CPP
- # define ENTT_NONSTD false
- #else
- # define ENTT_NONSTD true
- # if defined __clang__ || defined __GNUC__
- # define ENTT_PRETTY_FUNCTION __PRETTY_FUNCTION__
- # define ENTT_PRETTY_FUNCTION_PREFIX '='
- # define ENTT_PRETTY_FUNCTION_SUFFIX ']'
- # elif defined _MSC_VER
- # define ENTT_PRETTY_FUNCTION __FUNCSIG__
- # define ENTT_PRETTY_FUNCTION_PREFIX '<'
- # define ENTT_PRETTY_FUNCTION_SUFFIX '>'
- # endif
- #endif
- #ifndef ENTT_EXPORT
- # if defined _WIN32 || defined __CYGWIN__ || defined _MSC_VER
- # define ENTT_EXPORT __declspec(dllexport)
- # define ENTT_IMPORT __declspec(dllimport)
- # define ENTT_HIDDEN
- # elif defined __GNUC__ && __GNUC__ >= 4
- # define ENTT_EXPORT __attribute__((visibility("default")))
- # define ENTT_IMPORT __attribute__((visibility("default")))
- # define ENTT_HIDDEN __attribute__((visibility("hidden")))
- # else /* Unsupported compiler */
- # define ENTT_EXPORT
- # define ENTT_IMPORT
- # define ENTT_HIDDEN
- # endif
- #endif
- #ifndef ENTT_API
- # if defined ENTT_API_EXPORT
- # define ENTT_API ENTT_EXPORT
- # elif defined ENTT_API_IMPORT
- # define ENTT_API ENTT_IMPORT
- # else /* No API */
- # define ENTT_API
- # endif
- #endif
- #if defined _MSC_VER
- # pragma detect_mismatch("entt.version", ENTT_VERSION)
- # pragma detect_mismatch("entt.noexcept", ENTT_XSTR(ENTT_TRY))
- # pragma detect_mismatch("entt.id", ENTT_XSTR(ENTT_ID_TYPE))
- # pragma detect_mismatch("entt.nonstd", ENTT_XSTR(ENTT_NONSTD))
- #endif
- // NOLINTEND(cppcoreguidelines-macro-usage)
- #endif
- // #include "../core/type_traits.hpp"
- #ifndef ENTT_CORE_TYPE_TRAITS_HPP
- #define ENTT_CORE_TYPE_TRAITS_HPP
- #include <cstddef>
- #include <iterator>
- #include <tuple>
- #include <type_traits>
- #include <utility>
- // #include "../config/config.h"
- #ifndef ENTT_CONFIG_CONFIG_H
- #define ENTT_CONFIG_CONFIG_H
- // #include "version.h"
- #ifndef ENTT_CONFIG_VERSION_H
- #define ENTT_CONFIG_VERSION_H
- // #include "macro.h"
- #ifndef ENTT_CONFIG_MACRO_H
- #define ENTT_CONFIG_MACRO_H
- // NOLINTBEGIN(cppcoreguidelines-macro-usage)
- #define ENTT_STR(arg) #arg
- #define ENTT_XSTR(arg) ENTT_STR(arg)
- // NOLINTEND(cppcoreguidelines-macro-usage)
- #endif
- // NOLINTBEGIN(cppcoreguidelines-macro-*,modernize-macro-*)
- #define ENTT_VERSION_MAJOR 3
- #define ENTT_VERSION_MINOR 16
- #define ENTT_VERSION_PATCH 0
- #define ENTT_VERSION \
- ENTT_XSTR(ENTT_VERSION_MAJOR) \
- "." ENTT_XSTR(ENTT_VERSION_MINOR) "." ENTT_XSTR(ENTT_VERSION_PATCH)
- // NOLINTEND(cppcoreguidelines-macro-*,modernize-macro-*)
- #endif
- // NOLINTBEGIN(cppcoreguidelines-macro-usage)
- #if defined(__cpp_exceptions) && !defined(ENTT_NOEXCEPTION)
- # define ENTT_CONSTEXPR
- # define ENTT_THROW throw
- # define ENTT_TRY try
- # define ENTT_CATCH catch(...)
- #else
- # define ENTT_CONSTEXPR constexpr // use only with throwing functions (waiting for C++20)
- # define ENTT_THROW
- # define ENTT_TRY if(true)
- # define ENTT_CATCH if(false)
- #endif
- #if __has_include(<version>)
- # include <version>
- #
- # if defined(__cpp_consteval)
- # define ENTT_CONSTEVAL consteval
- # endif
- #endif
- #ifndef ENTT_CONSTEVAL
- # define ENTT_CONSTEVAL constexpr
- #endif
- #ifdef ENTT_USE_ATOMIC
- # include <atomic>
- # define ENTT_MAYBE_ATOMIC(Type) std::atomic<Type>
- #else
- # define ENTT_MAYBE_ATOMIC(Type) Type
- #endif
- #ifndef ENTT_ID_TYPE
- # include <cstdint>
- # define ENTT_ID_TYPE std::uint32_t
- #else
- # include <cstdint> // provides coverage for types in the std namespace
- #endif
- #ifndef ENTT_SPARSE_PAGE
- # define ENTT_SPARSE_PAGE 4096
- #endif
- #ifndef ENTT_PACKED_PAGE
- # define ENTT_PACKED_PAGE 1024
- #endif
- #ifdef ENTT_DISABLE_ASSERT
- # undef ENTT_ASSERT
- # define ENTT_ASSERT(condition, msg) (void(0))
- #elif !defined ENTT_ASSERT
- # include <cassert>
- # define ENTT_ASSERT(condition, msg) assert(((condition) && (msg)))
- #endif
- #ifdef ENTT_DISABLE_ASSERT
- # undef ENTT_ASSERT_CONSTEXPR
- # define ENTT_ASSERT_CONSTEXPR(condition, msg) (void(0))
- #elif !defined ENTT_ASSERT_CONSTEXPR
- # define ENTT_ASSERT_CONSTEXPR(condition, msg) ENTT_ASSERT(condition, msg)
- #endif
- #define ENTT_FAIL(msg) ENTT_ASSERT(false, msg);
- #ifdef ENTT_NO_ETO
- # define ENTT_ETO_TYPE(Type) void
- #else
- # define ENTT_ETO_TYPE(Type) Type
- #endif
- #ifdef ENTT_NO_MIXIN
- # define ENTT_STORAGE(Mixin, ...) __VA_ARGS__
- #else
- # define ENTT_STORAGE(Mixin, ...) Mixin<__VA_ARGS__>
- #endif
- #ifdef ENTT_STANDARD_CPP
- # define ENTT_NONSTD false
- #else
- # define ENTT_NONSTD true
- # if defined __clang__ || defined __GNUC__
- # define ENTT_PRETTY_FUNCTION __PRETTY_FUNCTION__
- # define ENTT_PRETTY_FUNCTION_PREFIX '='
- # define ENTT_PRETTY_FUNCTION_SUFFIX ']'
- # elif defined _MSC_VER
- # define ENTT_PRETTY_FUNCTION __FUNCSIG__
- # define ENTT_PRETTY_FUNCTION_PREFIX '<'
- # define ENTT_PRETTY_FUNCTION_SUFFIX '>'
- # endif
- #endif
- #ifndef ENTT_EXPORT
- # if defined _WIN32 || defined __CYGWIN__ || defined _MSC_VER
- # define ENTT_EXPORT __declspec(dllexport)
- # define ENTT_IMPORT __declspec(dllimport)
- # define ENTT_HIDDEN
- # elif defined __GNUC__ && __GNUC__ >= 4
- # define ENTT_EXPORT __attribute__((visibility("default")))
- # define ENTT_IMPORT __attribute__((visibility("default")))
- # define ENTT_HIDDEN __attribute__((visibility("hidden")))
- # else /* Unsupported compiler */
- # define ENTT_EXPORT
- # define ENTT_IMPORT
- # define ENTT_HIDDEN
- # endif
- #endif
- #ifndef ENTT_API
- # if defined ENTT_API_EXPORT
- # define ENTT_API ENTT_EXPORT
- # elif defined ENTT_API_IMPORT
- # define ENTT_API ENTT_IMPORT
- # else /* No API */
- # define ENTT_API
- # endif
- #endif
- #if defined _MSC_VER
- # pragma detect_mismatch("entt.version", ENTT_VERSION)
- # pragma detect_mismatch("entt.noexcept", ENTT_XSTR(ENTT_TRY))
- # pragma detect_mismatch("entt.id", ENTT_XSTR(ENTT_ID_TYPE))
- # pragma detect_mismatch("entt.nonstd", ENTT_XSTR(ENTT_NONSTD))
- #endif
- // NOLINTEND(cppcoreguidelines-macro-usage)
- #endif
- // #include "fwd.hpp"
- #ifndef ENTT_CORE_FWD_HPP
- #define ENTT_CORE_FWD_HPP
- #include <cstddef>
- #include <cstdint>
- // #include "../config/config.h"
- namespace entt {
- /*! @brief Possible modes of an any object. */
- enum class any_policy : std::uint8_t {
- /*! @brief Default mode, no element available. */
- empty,
- /*! @brief Owning mode, dynamically allocated element. */
- dynamic,
- /*! @brief Owning mode, embedded element. */
- embedded,
- /*! @brief Aliasing mode, non-const reference. */
- ref,
- /*! @brief Const aliasing mode, const reference. */
- cref
- };
- // NOLINTNEXTLINE(cppcoreguidelines-avoid-c-arrays, modernize-avoid-c-arrays)
- template<std::size_t Len = sizeof(double[2]), std::size_t = alignof(double[2])>
- class basic_any;
- /*! @brief Alias declaration for type identifiers. */
- using id_type = ENTT_ID_TYPE;
- /*! @brief Alias declaration for the most common use case. */
- using any = basic_any<>;
- template<typename, typename>
- class compressed_pair;
- template<typename>
- class basic_hashed_string;
- /*! @brief Aliases for common character types. */
- using hashed_string = basic_hashed_string<char>;
- /*! @brief Aliases for common character types. */
- using hashed_wstring = basic_hashed_string<wchar_t>;
- // NOLINTNEXTLINE(bugprone-forward-declaration-namespace)
- struct type_info;
- } // namespace entt
- #endif
- namespace entt {
- /**
- * @brief Utility class to disambiguate overloaded functions.
- * @tparam N Number of choices available.
- */
- template<std::size_t N>
- struct choice_t
- // unfortunately, doxygen cannot parse such a construct
- : /*! @cond TURN_OFF_DOXYGEN */ choice_t<N - 1> /*! @endcond */
- {};
- /*! @copybrief choice_t */
- template<>
- struct choice_t<0> {};
- /**
- * @brief Variable template for the choice trick.
- * @tparam N Number of choices available.
- */
- template<std::size_t N>
- inline constexpr choice_t<N> choice{};
- /**
- * @brief Identity type trait.
- *
- * Useful to establish non-deduced contexts in template argument deduction
- * (waiting for C++20) or to provide types through function arguments.
- *
- * @tparam Type A type.
- */
- template<typename Type>
- struct type_identity {
- /*! @brief Identity type. */
- using type = Type;
- };
- /**
- * @brief Helper type.
- * @tparam Type A type.
- */
- template<typename Type>
- using type_identity_t = typename type_identity<Type>::type;
- /**
- * @brief A type-only `sizeof` wrapper that returns 0 where `sizeof` complains.
- * @tparam Type The type of which to return the size.
- */
- template<typename Type, typename = void>
- struct size_of: std::integral_constant<std::size_t, 0u> {};
- /*! @copydoc size_of */
- template<typename Type>
- struct size_of<Type, std::void_t<decltype(sizeof(Type))>>
- // NOLINTNEXTLINE(bugprone-sizeof-expression)
- : std::integral_constant<std::size_t, sizeof(Type)> {};
- /**
- * @brief Helper variable template.
- * @tparam Type The type of which to return the size.
- */
- template<typename Type>
- inline constexpr std::size_t size_of_v = size_of<Type>::value;
- /**
- * @brief Using declaration to be used to _repeat_ the same type a number of
- * times equal to the size of a given parameter pack.
- * @tparam Type A type to repeat.
- */
- template<typename Type, typename>
- using unpack_as_type = Type;
- /**
- * @brief Helper variable template to be used to _repeat_ the same value a
- * number of times equal to the size of a given parameter pack.
- * @tparam Value A value to repeat.
- */
- template<auto Value, typename>
- inline constexpr auto unpack_as_value = Value;
- /**
- * @brief Wraps a static constant.
- * @tparam Value A static constant.
- */
- template<auto Value>
- using integral_constant = std::integral_constant<decltype(Value), Value>;
- /**
- * @brief Alias template to facilitate the creation of named values.
- * @tparam Value A constant value at least convertible to `id_type`.
- */
- template<id_type Value>
- using tag = integral_constant<Value>;
- /**
- * @brief A class to use to push around lists of types, nothing more.
- * @tparam Type Types provided by the type list.
- */
- template<typename... Type>
- struct type_list {
- /*! @brief Type list type. */
- using type = type_list;
- /*! @brief Compile-time number of elements in the type list. */
- static constexpr auto size = sizeof...(Type);
- };
- /*! @brief Primary template isn't defined on purpose. */
- template<std::size_t, typename>
- struct type_list_element;
- /**
- * @brief Provides compile-time indexed access to the types of a type list.
- * @tparam Index Index of the type to return.
- * @tparam First First type provided by the type list.
- * @tparam Other Other types provided by the type list.
- */
- template<std::size_t Index, typename First, typename... Other>
- struct type_list_element<Index, type_list<First, Other...>>
- : type_list_element<Index - 1u, type_list<Other...>> {};
- /**
- * @brief Provides compile-time indexed access to the types of a type list.
- * @tparam First First type provided by the type list.
- * @tparam Other Other types provided by the type list.
- */
- template<typename First, typename... Other>
- struct type_list_element<0u, type_list<First, Other...>> {
- /*! @brief Searched type. */
- using type = First;
- };
- /**
- * @brief Helper type.
- * @tparam Index Index of the type to return.
- * @tparam List Type list to search into.
- */
- template<std::size_t Index, typename List>
- using type_list_element_t = typename type_list_element<Index, List>::type;
- /*! @brief Primary template isn't defined on purpose. */
- template<typename, typename>
- struct type_list_index;
- /**
- * @brief Provides compile-time type access to the types of a type list.
- * @tparam Type Type to look for and for which to return the index.
- * @tparam First First type provided by the type list.
- * @tparam Other Other types provided by the type list.
- */
- template<typename Type, typename First, typename... Other>
- struct type_list_index<Type, type_list<First, Other...>> {
- /*! @brief Unsigned integer type. */
- using value_type = std::size_t;
- /*! @brief Compile-time position of the given type in the sublist. */
- static constexpr value_type value = 1u + type_list_index<Type, type_list<Other...>>::value;
- };
- /**
- * @brief Provides compile-time type access to the types of a type list.
- * @tparam Type Type to look for and for which to return the index.
- * @tparam Other Other types provided by the type list.
- */
- template<typename Type, typename... Other>
- struct type_list_index<Type, type_list<Type, Other...>> {
- static_assert(type_list_index<Type, type_list<Other...>>::value == sizeof...(Other), "Non-unique type");
- /*! @brief Unsigned integer type. */
- using value_type = std::size_t;
- /*! @brief Compile-time position of the given type in the sublist. */
- static constexpr value_type value = 0u;
- };
- /**
- * @brief Provides compile-time type access to the types of a type list.
- * @tparam Type Type to look for and for which to return the index.
- */
- template<typename Type>
- struct type_list_index<Type, type_list<>> {
- /*! @brief Unsigned integer type. */
- using value_type = std::size_t;
- /*! @brief Compile-time position of the given type in the sublist. */
- static constexpr value_type value = 0u;
- };
- /**
- * @brief Helper variable template.
- * @tparam List Type list.
- * @tparam Type Type to look for and for which to return the index.
- */
- template<typename Type, typename List>
- inline constexpr std::size_t type_list_index_v = type_list_index<Type, List>::value;
- /**
- * @brief Concatenates multiple type lists.
- * @tparam Type Types provided by the first type list.
- * @tparam Other Types provided by the second type list.
- * @return A type list composed by the types of both the type lists.
- */
- template<typename... Type, typename... Other>
- constexpr type_list<Type..., Other...> operator+(type_list<Type...>, type_list<Other...>) {
- return {};
- }
- /*! @brief Primary template isn't defined on purpose. */
- template<typename...>
- struct type_list_cat;
- /*! @brief Concatenates multiple type lists. */
- template<>
- struct type_list_cat<> {
- /*! @brief A type list composed by the types of all the type lists. */
- using type = type_list<>;
- };
- /**
- * @brief Concatenates multiple type lists.
- * @tparam Type Types provided by the first type list.
- * @tparam Other Types provided by the second type list.
- * @tparam List Other type lists, if any.
- */
- template<typename... Type, typename... Other, typename... List>
- struct type_list_cat<type_list<Type...>, type_list<Other...>, List...> {
- /*! @brief A type list composed by the types of all the type lists. */
- using type = typename type_list_cat<type_list<Type..., Other...>, List...>::type;
- };
- /**
- * @brief Concatenates multiple type lists.
- * @tparam Type Types provided by the type list.
- */
- template<typename... Type>
- struct type_list_cat<type_list<Type...>> {
- /*! @brief A type list composed by the types of all the type lists. */
- using type = type_list<Type...>;
- };
- /**
- * @brief Helper type.
- * @tparam List Type lists to concatenate.
- */
- template<typename... List>
- using type_list_cat_t = typename type_list_cat<List...>::type;
- /*! @cond TURN_OFF_DOXYGEN */
- namespace internal {
- template<typename...>
- struct type_list_unique;
- template<typename First, typename... Other, typename... Type>
- struct type_list_unique<type_list<First, Other...>, Type...>
- : std::conditional_t<(std::is_same_v<First, Type> || ...), type_list_unique<type_list<Other...>, Type...>, type_list_unique<type_list<Other...>, Type..., First>> {};
- template<typename... Type>
- struct type_list_unique<type_list<>, Type...> {
- using type = type_list<Type...>;
- };
- } // namespace internal
- /*! @endcond */
- /**
- * @brief Removes duplicates types from a type list.
- * @tparam List Type list.
- */
- template<typename List>
- struct type_list_unique {
- /*! @brief A type list without duplicate types. */
- using type = typename internal::type_list_unique<List>::type;
- };
- /**
- * @brief Helper type.
- * @tparam List Type list.
- */
- template<typename List>
- using type_list_unique_t = typename type_list_unique<List>::type;
- /**
- * @brief Provides the member constant `value` to true if a type list contains a
- * given type, false otherwise.
- * @tparam List Type list.
- * @tparam Type Type to look for.
- */
- template<typename List, typename Type>
- struct type_list_contains;
- /**
- * @copybrief type_list_contains
- * @tparam Type Types provided by the type list.
- * @tparam Other Type to look for.
- */
- template<typename... Type, typename Other>
- struct type_list_contains<type_list<Type...>, Other>
- : std::bool_constant<(std::is_same_v<Type, Other> || ...)> {};
- /**
- * @brief Helper variable template.
- * @tparam List Type list.
- * @tparam Type Type to look for.
- */
- template<typename List, typename Type>
- inline constexpr bool type_list_contains_v = type_list_contains<List, Type>::value;
- /*! @brief Primary template isn't defined on purpose. */
- template<typename...>
- struct type_list_diff;
- /**
- * @brief Computes the difference between two type lists.
- * @tparam Type Types provided by the first type list.
- * @tparam Other Types provided by the second type list.
- */
- template<typename... Type, typename... Other>
- struct type_list_diff<type_list<Type...>, type_list<Other...>> {
- /*! @brief A type list that is the difference between the two type lists. */
- using type = type_list_cat_t<std::conditional_t<type_list_contains_v<type_list<Other...>, Type>, type_list<>, type_list<Type>>...>;
- };
- /**
- * @brief Helper type.
- * @tparam List Type lists between which to compute the difference.
- */
- template<typename... List>
- using type_list_diff_t = typename type_list_diff<List...>::type;
- /*! @brief Primary template isn't defined on purpose. */
- template<typename, template<typename...> class>
- struct type_list_transform;
- /**
- * @brief Applies a given _function_ to a type list and generate a new list.
- * @tparam Type Types provided by the type list.
- * @tparam Op Unary operation as template class with a type member named `type`.
- */
- template<typename... Type, template<typename...> class Op>
- struct type_list_transform<type_list<Type...>, Op> {
- /*! @brief Resulting type list after applying the transform function. */
- // NOLINTNEXTLINE(modernize-type-traits)
- using type = type_list<typename Op<Type>::type...>;
- };
- /**
- * @brief Helper type.
- * @tparam List Type list.
- * @tparam Op Unary operation as template class with a type member named `type`.
- */
- template<typename List, template<typename...> class Op>
- using type_list_transform_t = typename type_list_transform<List, Op>::type;
- /**
- * @brief A class to use to push around lists of constant values, nothing more.
- * @tparam Value Values provided by the value list.
- */
- template<auto... Value>
- struct value_list {
- /*! @brief Value list type. */
- using type = value_list;
- /*! @brief Compile-time number of elements in the value list. */
- static constexpr auto size = sizeof...(Value);
- };
- /*! @brief Primary template isn't defined on purpose. */
- template<std::size_t, typename>
- struct value_list_element;
- /**
- * @brief Provides compile-time indexed access to the values of a value list.
- * @tparam Index Index of the value to return.
- * @tparam Value First value provided by the value list.
- * @tparam Other Other values provided by the value list.
- */
- template<std::size_t Index, auto Value, auto... Other>
- struct value_list_element<Index, value_list<Value, Other...>>
- : value_list_element<Index - 1u, value_list<Other...>> {};
- /**
- * @brief Provides compile-time indexed access to the types of a type list.
- * @tparam Value First value provided by the value list.
- * @tparam Other Other values provided by the value list.
- */
- template<auto Value, auto... Other>
- struct value_list_element<0u, value_list<Value, Other...>> {
- /*! @brief Searched type. */
- using type = decltype(Value);
- /*! @brief Searched value. */
- static constexpr auto value = Value;
- };
- /**
- * @brief Helper type.
- * @tparam Index Index of the type to return.
- * @tparam List Value list to search into.
- */
- template<std::size_t Index, typename List>
- using value_list_element_t = typename value_list_element<Index, List>::type;
- /**
- * @brief Helper type.
- * @tparam Index Index of the value to return.
- * @tparam List Value list to search into.
- */
- template<std::size_t Index, typename List>
- inline constexpr auto value_list_element_v = value_list_element<Index, List>::value;
- /*! @brief Primary template isn't defined on purpose. */
- template<auto, typename>
- struct value_list_index;
- /**
- * @brief Provides compile-time type access to the values of a value list.
- * @tparam Value Value to look for and for which to return the index.
- * @tparam First First value provided by the value list.
- * @tparam Other Other values provided by the value list.
- */
- template<auto Value, auto First, auto... Other>
- struct value_list_index<Value, value_list<First, Other...>> {
- /*! @brief Unsigned integer type. */
- using value_type = std::size_t;
- /*! @brief Compile-time position of the given value in the sublist. */
- static constexpr value_type value = 1u + value_list_index<Value, value_list<Other...>>::value;
- };
- /**
- * @brief Provides compile-time type access to the values of a value list.
- * @tparam Value Value to look for and for which to return the index.
- * @tparam Other Other values provided by the value list.
- */
- template<auto Value, auto... Other>
- struct value_list_index<Value, value_list<Value, Other...>> {
- static_assert(value_list_index<Value, value_list<Other...>>::value == sizeof...(Other), "Non-unique type");
- /*! @brief Unsigned integer type. */
- using value_type = std::size_t;
- /*! @brief Compile-time position of the given value in the sublist. */
- static constexpr value_type value = 0u;
- };
- /**
- * @brief Provides compile-time type access to the values of a value list.
- * @tparam Value Value to look for and for which to return the index.
- */
- template<auto Value>
- struct value_list_index<Value, value_list<>> {
- /*! @brief Unsigned integer type. */
- using value_type = std::size_t;
- /*! @brief Compile-time position of the given type in the sublist. */
- static constexpr value_type value = 0u;
- };
- /**
- * @brief Helper variable template.
- * @tparam List Value list.
- * @tparam Value Value to look for and for which to return the index.
- */
- template<auto Value, typename List>
- inline constexpr std::size_t value_list_index_v = value_list_index<Value, List>::value;
- /**
- * @brief Concatenates multiple value lists.
- * @tparam Value Values provided by the first value list.
- * @tparam Other Values provided by the second value list.
- * @return A value list composed by the values of both the value lists.
- */
- template<auto... Value, auto... Other>
- constexpr value_list<Value..., Other...> operator+(value_list<Value...>, value_list<Other...>) {
- return {};
- }
- /*! @brief Primary template isn't defined on purpose. */
- template<typename...>
- struct value_list_cat;
- /*! @brief Concatenates multiple value lists. */
- template<>
- struct value_list_cat<> {
- /*! @brief A value list composed by the values of all the value lists. */
- using type = value_list<>;
- };
- /**
- * @brief Concatenates multiple value lists.
- * @tparam Value Values provided by the first value list.
- * @tparam Other Values provided by the second value list.
- * @tparam List Other value lists, if any.
- */
- template<auto... Value, auto... Other, typename... List>
- struct value_list_cat<value_list<Value...>, value_list<Other...>, List...> {
- /*! @brief A value list composed by the values of all the value lists. */
- using type = typename value_list_cat<value_list<Value..., Other...>, List...>::type;
- };
- /**
- * @brief Concatenates multiple value lists.
- * @tparam Value Values provided by the value list.
- */
- template<auto... Value>
- struct value_list_cat<value_list<Value...>> {
- /*! @brief A value list composed by the values of all the value lists. */
- using type = value_list<Value...>;
- };
- /**
- * @brief Helper type.
- * @tparam List Value lists to concatenate.
- */
- template<typename... List>
- using value_list_cat_t = typename value_list_cat<List...>::type;
- /*! @brief Primary template isn't defined on purpose. */
- template<typename>
- struct value_list_unique;
- /**
- * @brief Removes duplicates values from a value list.
- * @tparam Value One of the values provided by the given value list.
- * @tparam Other The other values provided by the given value list.
- */
- template<auto Value, auto... Other>
- struct value_list_unique<value_list<Value, Other...>> {
- /*! @brief A value list without duplicate types. */
- using type = std::conditional_t<
- ((Value == Other) || ...),
- typename value_list_unique<value_list<Other...>>::type,
- value_list_cat_t<value_list<Value>, typename value_list_unique<value_list<Other...>>::type>>;
- };
- /*! @brief Removes duplicates values from a value list. */
- template<>
- struct value_list_unique<value_list<>> {
- /*! @brief A value list without duplicate types. */
- using type = value_list<>;
- };
- /**
- * @brief Helper type.
- * @tparam Type A value list.
- */
- template<typename Type>
- using value_list_unique_t = typename value_list_unique<Type>::type;
- /**
- * @brief Provides the member constant `value` to true if a value list contains
- * a given value, false otherwise.
- * @tparam List Value list.
- * @tparam Value Value to look for.
- */
- template<typename List, auto Value>
- struct value_list_contains;
- /**
- * @copybrief value_list_contains
- * @tparam Value Values provided by the value list.
- * @tparam Other Value to look for.
- */
- template<auto... Value, auto Other>
- struct value_list_contains<value_list<Value...>, Other>
- : std::bool_constant<((Value == Other) || ...)> {};
- /**
- * @brief Helper variable template.
- * @tparam List Value list.
- * @tparam Value Value to look for.
- */
- template<typename List, auto Value>
- inline constexpr bool value_list_contains_v = value_list_contains<List, Value>::value;
- /*! @brief Primary template isn't defined on purpose. */
- template<typename...>
- struct value_list_diff;
- /**
- * @brief Computes the difference between two value lists.
- * @tparam Value Values provided by the first value list.
- * @tparam Other Values provided by the second value list.
- */
- template<auto... Value, auto... Other>
- struct value_list_diff<value_list<Value...>, value_list<Other...>> {
- /*! @brief A value list that is the difference between the two value lists. */
- using type = value_list_cat_t<std::conditional_t<value_list_contains_v<value_list<Other...>, Value>, value_list<>, value_list<Value>>...>;
- };
- /**
- * @brief Helper type.
- * @tparam List Value lists between which to compute the difference.
- */
- template<typename... List>
- using value_list_diff_t = typename value_list_diff<List...>::type;
- /*! @brief Same as std::is_invocable, but with tuples. */
- template<typename, typename>
- struct is_applicable: std::false_type {};
- /**
- * @copybrief is_applicable
- * @tparam Func A valid function type.
- * @tparam Tuple Tuple-like type.
- * @tparam Args The list of arguments to use to probe the function type.
- */
- template<typename Func, template<typename...> class Tuple, typename... Args>
- struct is_applicable<Func, Tuple<Args...>>: std::is_invocable<Func, Args...> {};
- /**
- * @copybrief is_applicable
- * @tparam Func A valid function type.
- * @tparam Tuple Tuple-like type.
- * @tparam Args The list of arguments to use to probe the function type.
- */
- template<typename Func, template<typename...> class Tuple, typename... Args>
- struct is_applicable<Func, const Tuple<Args...>>: std::is_invocable<Func, Args...> {};
- /**
- * @brief Helper variable template.
- * @tparam Func A valid function type.
- * @tparam Args The list of arguments to use to probe the function type.
- */
- template<typename Func, typename Args>
- inline constexpr bool is_applicable_v = is_applicable<Func, Args>::value;
- /*! @brief Same as std::is_invocable_r, but with tuples for arguments. */
- template<typename, typename, typename>
- struct is_applicable_r: std::false_type {};
- /**
- * @copybrief is_applicable_r
- * @tparam Ret The type to which the return type of the function should be
- * convertible.
- * @tparam Func A valid function type.
- * @tparam Args The list of arguments to use to probe the function type.
- */
- template<typename Ret, typename Func, typename... Args>
- struct is_applicable_r<Ret, Func, std::tuple<Args...>>: std::is_invocable_r<Ret, Func, Args...> {};
- /**
- * @brief Helper variable template.
- * @tparam Ret The type to which the return type of the function should be
- * convertible.
- * @tparam Func A valid function type.
- * @tparam Args The list of arguments to use to probe the function type.
- */
- template<typename Ret, typename Func, typename Args>
- inline constexpr bool is_applicable_r_v = is_applicable_r<Ret, Func, Args>::value;
- /**
- * @brief Provides the member constant `value` to true if a given type is
- * complete, false otherwise.
- * @tparam Type The type to test.
- */
- template<typename Type, typename = void>
- struct is_complete: std::false_type {};
- /*! @copydoc is_complete */
- template<typename Type>
- struct is_complete<Type, std::void_t<decltype(sizeof(Type))>>: std::true_type {};
- /**
- * @brief Helper variable template.
- * @tparam Type The type to test.
- */
- template<typename Type>
- inline constexpr bool is_complete_v = is_complete<Type>::value;
- /**
- * @brief Provides the member constant `value` to true if a given type is an
- * iterator, false otherwise.
- * @tparam Type The type to test.
- */
- template<typename Type, typename = void>
- struct is_iterator: std::false_type {};
- /*! @cond TURN_OFF_DOXYGEN */
- namespace internal {
- template<typename, typename = void>
- struct has_iterator_category: std::false_type {};
- template<typename Type>
- struct has_iterator_category<Type, std::void_t<typename std::iterator_traits<Type>::iterator_category>>: std::true_type {};
- } // namespace internal
- /*! @endcond */
- /*! @copydoc is_iterator */
- template<typename Type>
- struct is_iterator<Type, std::enable_if_t<!std::is_void_v<std::remove_const_t<std::remove_pointer_t<Type>>>>>
- : internal::has_iterator_category<Type> {};
- /**
- * @brief Helper variable template.
- * @tparam Type The type to test.
- */
- template<typename Type>
- inline constexpr bool is_iterator_v = is_iterator<Type>::value;
- /**
- * @brief Provides the member constant `value` to true if a given type is both
- * an empty and non-final class, false otherwise.
- * @tparam Type The type to test
- */
- template<typename Type>
- struct is_ebco_eligible
- : std::bool_constant<std::is_empty_v<Type> && !std::is_final_v<Type>> {};
- /**
- * @brief Helper variable template.
- * @tparam Type The type to test.
- */
- template<typename Type>
- inline constexpr bool is_ebco_eligible_v = is_ebco_eligible<Type>::value;
- /**
- * @brief Provides the member constant `value` to true if `Type::is_transparent`
- * is valid and denotes a type, false otherwise.
- * @tparam Type The type to test.
- */
- template<typename Type, typename = void>
- struct is_transparent: std::false_type {};
- /*! @copydoc is_transparent */
- template<typename Type>
- struct is_transparent<Type, std::void_t<typename Type::is_transparent>>: std::true_type {};
- /**
- * @brief Helper variable template.
- * @tparam Type The type to test.
- */
- template<typename Type>
- inline constexpr bool is_transparent_v = is_transparent<Type>::value;
- /*! @cond TURN_OFF_DOXYGEN */
- namespace internal {
- template<typename, typename = void>
- struct has_tuple_size_value: std::false_type {};
- template<typename Type>
- struct has_tuple_size_value<Type, std::void_t<decltype(std::tuple_size<const Type>::value)>>: std::true_type {};
- template<typename, typename = void>
- struct has_value_type: std::false_type {};
- template<typename Type>
- struct has_value_type<Type, std::void_t<typename Type::value_type>>: std::true_type {};
- template<typename>
- [[nodiscard]] constexpr bool dispatch_is_equality_comparable();
- template<typename Type, std::size_t... Index>
- [[nodiscard]] constexpr bool unpack_maybe_equality_comparable(std::index_sequence<Index...>) {
- return (dispatch_is_equality_comparable<std::tuple_element_t<Index, Type>>() && ...);
- }
- template<typename>
- [[nodiscard]] constexpr bool maybe_equality_comparable(char) {
- return false;
- }
- template<typename Type>
- [[nodiscard]] constexpr auto maybe_equality_comparable(int) -> decltype(std::declval<Type>() == std::declval<Type>()) {
- return true;
- }
- template<typename Type>
- [[nodiscard]] constexpr bool dispatch_is_equality_comparable() {
- // NOLINTBEGIN(modernize-use-transparent-functors)
- if constexpr(std::is_array_v<Type>) {
- return false;
- } else if constexpr(is_complete_v<std::tuple_size<std::remove_const_t<Type>>>) {
- if constexpr(has_tuple_size_value<Type>::value) {
- return maybe_equality_comparable<Type>(0) && unpack_maybe_equality_comparable<Type>(std::make_index_sequence<std::tuple_size<Type>::value>{});
- } else {
- return maybe_equality_comparable<Type>(0);
- }
- } else if constexpr(has_value_type<Type>::value) {
- if constexpr(is_iterator_v<Type> || std::is_same_v<typename Type::value_type, Type> || dispatch_is_equality_comparable<typename Type::value_type>()) {
- return maybe_equality_comparable<Type>(0);
- } else {
- return false;
- }
- } else {
- return maybe_equality_comparable<Type>(0);
- }
- // NOLINTEND(modernize-use-transparent-functors)
- }
- } // namespace internal
- /*! @endcond */
- /**
- * @brief Provides the member constant `value` to true if a given type is
- * equality comparable, false otherwise.
- * @tparam Type The type to test.
- */
- template<typename Type>
- struct is_equality_comparable: std::bool_constant<internal::dispatch_is_equality_comparable<Type>()> {};
- /*! @copydoc is_equality_comparable */
- template<typename Type>
- struct is_equality_comparable<const Type>: is_equality_comparable<Type> {};
- /**
- * @brief Helper variable template.
- * @tparam Type The type to test.
- */
- template<typename Type>
- inline constexpr bool is_equality_comparable_v = is_equality_comparable<Type>::value;
- /**
- * @brief Transcribes the constness of a type to another type.
- * @tparam To The type to which to transcribe the constness.
- * @tparam From The type from which to transcribe the constness.
- */
- template<typename To, typename From>
- struct constness_as {
- /*! @brief The type resulting from the transcription of the constness. */
- using type = std::remove_const_t<To>;
- };
- /*! @copydoc constness_as */
- template<typename To, typename From>
- struct constness_as<To, const From> {
- /*! @brief The type resulting from the transcription of the constness. */
- using type = const To;
- };
- /**
- * @brief Alias template to facilitate the transcription of the constness.
- * @tparam To The type to which to transcribe the constness.
- * @tparam From The type from which to transcribe the constness.
- */
- template<typename To, typename From>
- using constness_as_t = typename constness_as<To, From>::type;
- /**
- * @brief Extracts the class of a non-static member object or function.
- * @tparam Member A pointer to a non-static member object or function.
- */
- template<typename Member>
- class member_class {
- static_assert(std::is_member_pointer_v<Member>, "Invalid pointer type to non-static member object or function");
- template<typename Class, typename Ret, typename... Args>
- static Class *clazz(Ret (Class::*)(Args...));
- template<typename Class, typename Ret, typename... Args>
- static Class *clazz(Ret (Class::*)(Args...) const);
- template<typename Class, typename Type>
- static Class *clazz(Type Class::*);
- public:
- /*! @brief The class of the given non-static member object or function. */
- using type = std::remove_pointer_t<decltype(clazz(std::declval<Member>()))>;
- };
- /**
- * @brief Helper type.
- * @tparam Member A pointer to a non-static member object or function.
- */
- template<typename Member>
- using member_class_t = typename member_class<Member>::type;
- /**
- * @brief Extracts the n-th argument of a _callable_ type.
- * @tparam Index The index of the argument to extract.
- * @tparam Candidate A valid _callable_ type.
- */
- template<std::size_t Index, typename Candidate>
- class nth_argument {
- template<typename Ret, typename... Args>
- static constexpr type_list<Args...> pick_up(Ret (*)(Args...));
- template<typename Ret, typename Class, typename... Args>
- static constexpr type_list<Args...> pick_up(Ret (Class ::*)(Args...));
- template<typename Ret, typename Class, typename... Args>
- static constexpr type_list<Args...> pick_up(Ret (Class ::*)(Args...) const);
- template<typename Type, typename Class>
- static constexpr type_list<Type> pick_up(Type Class ::*);
- template<typename Type>
- static constexpr decltype(pick_up(&Type::operator())) pick_up(Type &&);
- public:
- /*! @brief N-th argument of the _callable_ type. */
- using type = type_list_element_t<Index, decltype(pick_up(std::declval<Candidate>()))>;
- };
- /**
- * @brief Helper type.
- * @tparam Index The index of the argument to extract.
- * @tparam Candidate A valid function, member function or data member type.
- */
- template<std::size_t Index, typename Candidate>
- using nth_argument_t = typename nth_argument<Index, Candidate>::type;
- } // namespace entt
- template<typename... Type>
- struct std::tuple_size<entt::type_list<Type...>>: std::integral_constant<std::size_t, entt::type_list<Type...>::size> {};
- template<std::size_t Index, typename... Type>
- struct std::tuple_element<Index, entt::type_list<Type...>>: entt::type_list_element<Index, entt::type_list<Type...>> {};
- template<auto... Value>
- struct std::tuple_size<entt::value_list<Value...>>: std::integral_constant<std::size_t, entt::value_list<Value...>::size> {};
- template<std::size_t Index, auto... Value>
- struct std::tuple_element<Index, entt::value_list<Value...>>: entt::value_list_element<Index, entt::value_list<Value...>> {};
- #endif
- // #include "fwd.hpp"
- #ifndef ENTT_SIGNAL_FWD_HPP
- #define ENTT_SIGNAL_FWD_HPP
- #include <memory>
- namespace entt {
- template<typename>
- class delegate;
- template<typename = std::allocator<void>>
- class basic_dispatcher;
- template<typename, typename = std::allocator<void>>
- class emitter;
- class connection;
- struct scoped_connection;
- template<typename>
- class sink;
- template<typename Type, typename = std::allocator<void>>
- class sigh;
- /*! @brief Alias declaration for the most common use case. */
- using dispatcher = basic_dispatcher<>;
- /*! @brief Disambiguation tag for constructors and the like. */
- template<auto>
- struct connect_arg_t {
- /*! @brief Default constructor. */
- explicit connect_arg_t() = default;
- };
- /**
- * @brief Constant of type connect_arg_t used to disambiguate calls.
- * @tparam Candidate Element to connect (likely a free or member function).
- */
- template<auto Candidate>
- inline constexpr connect_arg_t<Candidate> connect_arg{};
- } // namespace entt
- #endif
- namespace entt {
- /*! @cond TURN_OFF_DOXYGEN */
- namespace internal {
- template<typename Ret, typename... Args>
- constexpr auto function_pointer(Ret (*)(Args...)) -> Ret (*)(Args...);
- template<typename Ret, typename Type, typename... Args, typename Other>
- constexpr auto function_pointer(Ret (*)(Type, Args...), Other &&) -> Ret (*)(Args...);
- template<typename Class, typename Ret, typename... Args, typename... Other>
- constexpr auto function_pointer(Ret (Class::*)(Args...), Other &&...) -> Ret (*)(Args...);
- template<typename Class, typename Ret, typename... Args, typename... Other>
- constexpr auto function_pointer(Ret (Class::*)(Args...) const, Other &&...) -> Ret (*)(Args...);
- template<typename Class, typename Type, typename... Other, typename = std::enable_if_t<std::is_member_object_pointer_v<Type Class::*>>>
- constexpr auto function_pointer(Type Class::*, Other &&...) -> Type (*)();
- template<typename... Type>
- using function_pointer_t = decltype(function_pointer(std::declval<Type>()...));
- template<typename... Class, typename Ret, typename... Args>
- [[nodiscard]] constexpr auto index_sequence_for(Ret (*)(Args...)) {
- return std::index_sequence_for<Class..., Args...>{};
- }
- } // namespace internal
- /*! @endcond */
- /**
- * @brief Basic delegate implementation.
- *
- * Primary template isn't defined on purpose. All the specializations give a
- * compile-time error unless the template parameter is a function type.
- */
- template<typename>
- class delegate;
- /**
- * @brief Utility class to use to send around functions and members.
- *
- * Unmanaged delegate for function pointers and members. Users of this class are
- * in charge of disconnecting instances before deleting them.
- *
- * A delegate can be used as a general purpose invoker without memory overhead
- * for free functions possibly with payloads and bound or unbound members.
- *
- * @tparam Ret Return type of a function type.
- * @tparam Args Types of arguments of a function type.
- */
- template<typename Ret, typename... Args>
- class delegate<Ret(Args...)> {
- using return_type = std::remove_const_t<Ret>;
- using delegate_type = return_type(const void *, Args...);
- template<auto Candidate, std::size_t... Index>
- [[nodiscard]] auto wrap(std::index_sequence<Index...>) noexcept {
- return [](const void *, Args... args) -> return_type {
- [[maybe_unused]] const auto arguments = std::forward_as_tuple(std::forward<Args>(args)...);
- [[maybe_unused]] constexpr auto offset = !std::is_invocable_r_v<Ret, decltype(Candidate), type_list_element_t<Index, type_list<Args...>>...> * (sizeof...(Args) - sizeof...(Index));
- return static_cast<Ret>(std::invoke(Candidate, std::forward<type_list_element_t<Index + offset, type_list<Args...>>>(std::get<Index + offset>(arguments))...));
- };
- }
- template<auto Candidate, typename Type, std::size_t... Index>
- [[nodiscard]] auto wrap(Type &, std::index_sequence<Index...>) noexcept {
- return [](const void *payload, Args... args) -> return_type {
- Type *curr = static_cast<Type *>(const_cast<constness_as_t<void, Type> *>(payload));
- [[maybe_unused]] const auto arguments = std::forward_as_tuple(std::forward<Args>(args)...);
- [[maybe_unused]] constexpr auto offset = !std::is_invocable_r_v<Ret, decltype(Candidate), Type &, type_list_element_t<Index, type_list<Args...>>...> * (sizeof...(Args) - sizeof...(Index));
- return static_cast<Ret>(std::invoke(Candidate, *curr, std::forward<type_list_element_t<Index + offset, type_list<Args...>>>(std::get<Index + offset>(arguments))...));
- };
- }
- template<auto Candidate, typename Type, std::size_t... Index>
- [[nodiscard]] auto wrap(Type *, std::index_sequence<Index...>) noexcept {
- return [](const void *payload, Args... args) -> return_type {
- Type *curr = static_cast<Type *>(const_cast<constness_as_t<void, Type> *>(payload));
- [[maybe_unused]] const auto arguments = std::forward_as_tuple(std::forward<Args>(args)...);
- [[maybe_unused]] constexpr auto offset = !std::is_invocable_r_v<Ret, decltype(Candidate), Type *, type_list_element_t<Index, type_list<Args...>>...> * (sizeof...(Args) - sizeof...(Index));
- return static_cast<Ret>(std::invoke(Candidate, curr, std::forward<type_list_element_t<Index + offset, type_list<Args...>>>(std::get<Index + offset>(arguments))...));
- };
- }
- public:
- /*! @brief Function type of the contained target. */
- using function_type = Ret(const void *, Args...);
- /*! @brief Function type of the delegate. */
- using type = Ret(Args...);
- /*! @brief Return type of the delegate. */
- using result_type = Ret;
- /*! @brief Default constructor. */
- delegate() noexcept = default;
- /**
- * @brief Constructs a delegate with a given object or payload, if any.
- * @tparam Candidate Function or member to connect to the delegate.
- * @tparam Type Type of class or type of payload, if any.
- * @param value_or_instance Optional valid object that fits the purpose.
- */
- template<auto Candidate, typename... Type>
- delegate(connect_arg_t<Candidate>, Type &&...value_or_instance) noexcept {
- connect<Candidate>(std::forward<Type>(value_or_instance)...);
- }
- /**
- * @brief Constructs a delegate and connects an user defined function with
- * optional payload.
- * @param function Function to connect to the delegate.
- * @param payload User defined arbitrary data.
- */
- delegate(function_type *function, const void *payload = nullptr) noexcept {
- connect(function, payload);
- }
- /**
- * @brief Connects a free function or an unbound member to a delegate.
- * @tparam Candidate Function or member to connect to the delegate.
- */
- template<auto Candidate>
- void connect() noexcept {
- instance = nullptr;
- if constexpr(std::is_invocable_r_v<Ret, decltype(Candidate), Args...>) {
- fn = [](const void *, Args... args) -> return_type {
- return Ret(std::invoke(Candidate, std::forward<Args>(args)...));
- };
- } else if constexpr(std::is_member_pointer_v<decltype(Candidate)>) {
- fn = wrap<Candidate>(internal::index_sequence_for<type_list_element_t<0, type_list<Args...>>>(internal::function_pointer_t<decltype(Candidate)>{}));
- } else {
- fn = wrap<Candidate>(internal::index_sequence_for(internal::function_pointer_t<decltype(Candidate)>{}));
- }
- }
- /**
- * @brief Connects a free function with payload or a bound member to a
- * delegate.
- *
- * The delegate isn't responsible for the connected object or the payload.
- * Users must always guarantee that the lifetime of the instance overcomes
- * the one of the delegate.<br/>
- * When used to connect a free function with payload, its signature must be
- * such that the instance is the first argument before the ones used to
- * define the delegate itself.
- *
- * @tparam Candidate Function or member to connect to the delegate.
- * @tparam Type Type of class or type of payload.
- * @param value_or_instance A valid reference that fits the purpose.
- */
- template<auto Candidate, typename Type>
- void connect(Type &value_or_instance) noexcept {
- instance = &value_or_instance;
- if constexpr(std::is_invocable_r_v<Ret, decltype(Candidate), Type &, Args...>) {
- fn = [](const void *payload, Args... args) -> return_type {
- Type *curr = static_cast<Type *>(const_cast<constness_as_t<void, Type> *>(payload));
- return Ret(std::invoke(Candidate, *curr, std::forward<Args>(args)...));
- };
- } else {
- fn = wrap<Candidate>(value_or_instance, internal::index_sequence_for(internal::function_pointer_t<decltype(Candidate), Type>{}));
- }
- }
- /**
- * @brief Connects a free function with payload or a bound member to a
- * delegate.
- *
- * @sa connect(Type &)
- *
- * @tparam Candidate Function or member to connect to the delegate.
- * @tparam Type Type of class or type of payload.
- * @param value_or_instance A valid pointer that fits the purpose.
- */
- template<auto Candidate, typename Type>
- void connect(Type *value_or_instance) noexcept {
- instance = value_or_instance;
- if constexpr(std::is_invocable_r_v<Ret, decltype(Candidate), Type *, Args...>) {
- fn = [](const void *payload, Args... args) -> return_type {
- Type *curr = static_cast<Type *>(const_cast<constness_as_t<void, Type> *>(payload));
- return Ret(std::invoke(Candidate, curr, std::forward<Args>(args)...));
- };
- } else {
- fn = wrap<Candidate>(value_or_instance, internal::index_sequence_for(internal::function_pointer_t<decltype(Candidate), Type>{}));
- }
- }
- /**
- * @brief Connects an user defined function with optional payload to a
- * delegate.
- *
- * The delegate isn't responsible for the connected object or the payload.
- * Users must always guarantee that the lifetime of an instance overcomes
- * the one of the delegate.<br/>
- * The payload is returned as the first argument to the target function in
- * all cases.
- *
- * @param function Function to connect to the delegate.
- * @param payload User defined arbitrary data.
- */
- void connect(function_type *function, const void *payload = nullptr) noexcept {
- ENTT_ASSERT(function != nullptr, "Uninitialized function pointer");
- instance = payload;
- fn = function;
- }
- /**
- * @brief Resets a delegate.
- *
- * After a reset, a delegate cannot be invoked anymore.
- */
- void reset() noexcept {
- instance = nullptr;
- fn = nullptr;
- }
- /**
- * @brief Returns a pointer to the stored callable function target, if any.
- * @return An opaque pointer to the stored callable function target.
- */
- [[nodiscard]] function_type *target() const noexcept {
- return fn;
- }
- /**
- * @brief Returns the instance or the payload linked to a delegate, if any.
- * @return An opaque pointer to the underlying data.
- */
- [[nodiscard]] const void *data() const noexcept {
- return instance;
- }
- /**
- * @brief Triggers a delegate.
- *
- * The delegate invokes the underlying function and returns the result.
- *
- * @warning
- * Attempting to trigger an invalid delegate results in undefined
- * behavior.
- *
- * @param args Arguments to use to invoke the underlying function.
- * @return The value returned by the underlying function.
- */
- Ret operator()(Args... args) const {
- ENTT_ASSERT(static_cast<bool>(*this), "Uninitialized delegate");
- return fn(instance, std::forward<Args>(args)...);
- }
- /**
- * @brief Checks whether a delegate actually stores a listener.
- * @return False if the delegate is empty, true otherwise.
- */
- [[nodiscard]] explicit operator bool() const noexcept {
- // no need to also test instance
- return !(fn == nullptr);
- }
- /**
- * @brief Compares the contents of two delegates.
- * @param other Delegate with which to compare.
- * @return False if the two contents differ, true otherwise.
- */
- [[nodiscard]] bool operator==(const delegate<Ret(Args...)> &other) const noexcept {
- return fn == other.fn && instance == other.instance;
- }
- private:
- const void *instance{};
- delegate_type *fn{};
- };
- /**
- * @brief Compares the contents of two delegates.
- * @tparam Ret Return type of a function type.
- * @tparam Args Types of arguments of a function type.
- * @param lhs A valid delegate object.
- * @param rhs A valid delegate object.
- * @return True if the two contents differ, false otherwise.
- */
- template<typename Ret, typename... Args>
- [[nodiscard]] bool operator!=(const delegate<Ret(Args...)> &lhs, const delegate<Ret(Args...)> &rhs) noexcept {
- return !(lhs == rhs);
- }
- /**
- * @brief Deduction guide.
- * @tparam Candidate Function or member to connect to the delegate.
- */
- template<auto Candidate>
- delegate(connect_arg_t<Candidate>) -> delegate<std::remove_pointer_t<internal::function_pointer_t<decltype(Candidate)>>>;
- /**
- * @brief Deduction guide.
- * @tparam Candidate Function or member to connect to the delegate.
- * @tparam Type Type of class or type of payload.
- */
- template<auto Candidate, typename Type>
- delegate(connect_arg_t<Candidate>, Type &&) -> delegate<std::remove_pointer_t<internal::function_pointer_t<decltype(Candidate), Type>>>;
- /**
- * @brief Deduction guide.
- * @tparam Ret Return type of a function type.
- * @tparam Args Types of arguments of a function type.
- */
- template<typename Ret, typename... Args>
- delegate(Ret (*)(const void *, Args...), const void * = nullptr) -> delegate<Ret(Args...)>;
- } // namespace entt
- #endif
- // #include "fwd.hpp"
- namespace entt {
- /**
- * @brief Sink class.
- *
- * Primary template isn't defined on purpose. All the specializations give a
- * compile-time error unless the template parameter is a function type.
- *
- * @tparam Type A valid signal handler type.
- */
- template<typename Type>
- class sink;
- /**
- * @brief Unmanaged signal handler.
- *
- * Primary template isn't defined on purpose. All the specializations give a
- * compile-time error unless the template parameter is a function type.
- *
- * @tparam Type A valid function type.
- * @tparam Allocator Type of allocator used to manage memory and elements.
- */
- template<typename Type, typename Allocator>
- class sigh;
- /**
- * @brief Unmanaged signal handler.
- *
- * It works directly with references to classes and pointers to member functions
- * as well as pointers to free functions. Users of this class are in charge of
- * disconnecting instances before deleting them.
- *
- * This class serves mainly two purposes:
- *
- * * Creating signals to use later to notify a bunch of listeners.
- * * Collecting results from a set of functions like in a voting system.
- *
- * @tparam Ret Return type of a function type.
- * @tparam Args Types of arguments of a function type.
- * @tparam Allocator Type of allocator used to manage memory and elements.
- */
- template<typename Ret, typename... Args, typename Allocator>
- class sigh<Ret(Args...), Allocator> {
- friend class sink<sigh<Ret(Args...), Allocator>>;
- using alloc_traits = std::allocator_traits<Allocator>;
- using delegate_type = delegate<Ret(Args...)>;
- using container_type = std::vector<delegate_type, typename alloc_traits::template rebind_alloc<delegate_type>>;
- public:
- /*! @brief Allocator type. */
- using allocator_type = Allocator;
- /*! @brief Unsigned integer type. */
- using size_type = std::size_t;
- /*! @brief Sink type. */
- using sink_type = sink<sigh<Ret(Args...), Allocator>>;
- /*! @brief Default constructor. */
- sigh() noexcept(noexcept(allocator_type{}))
- : sigh{allocator_type{}} {}
- /**
- * @brief Constructs a signal handler with a given allocator.
- * @param allocator The allocator to use.
- */
- explicit sigh(const allocator_type &allocator) noexcept
- : calls{allocator} {}
- /**
- * @brief Copy constructor.
- * @param other The instance to copy from.
- */
- sigh(const sigh &other)
- : calls{other.calls} {}
- /**
- * @brief Allocator-extended copy constructor.
- * @param other The instance to copy from.
- * @param allocator The allocator to use.
- */
- sigh(const sigh &other, const allocator_type &allocator)
- : calls{other.calls, allocator} {}
- /**
- * @brief Move constructor.
- * @param other The instance to move from.
- */
- sigh(sigh &&other) noexcept
- : calls{std::move(other.calls)} {}
- /**
- * @brief Allocator-extended move constructor.
- * @param other The instance to move from.
- * @param allocator The allocator to use.
- */
- sigh(sigh &&other, const allocator_type &allocator)
- : calls{std::move(other.calls), allocator} {}
- /*! @brief Default destructor. */
- ~sigh() = default;
- /**
- * @brief Copy assignment operator.
- * @param other The instance to copy from.
- * @return This signal handler.
- */
- sigh &operator=(const sigh &other) {
- calls = other.calls;
- return *this;
- }
- /**
- * @brief Move assignment operator.
- * @param other The instance to move from.
- * @return This signal handler.
- */
- sigh &operator=(sigh &&other) noexcept {
- swap(other);
- return *this;
- }
- /**
- * @brief Exchanges the contents with those of a given signal handler.
- * @param other Signal handler to exchange the content with.
- */
- void swap(sigh &other) noexcept {
- using std::swap;
- swap(calls, other.calls);
- }
- /**
- * @brief Returns the associated allocator.
- * @return The associated allocator.
- */
- [[nodiscard]] constexpr allocator_type get_allocator() const noexcept {
- return calls.get_allocator();
- }
- /**
- * @brief Number of listeners connected to the signal.
- * @return Number of listeners currently connected.
- */
- [[nodiscard]] size_type size() const noexcept {
- return calls.size();
- }
- /**
- * @brief Returns false if at least a listener is connected to the signal.
- * @return True if the signal has no listeners connected, false otherwise.
- */
- [[nodiscard]] bool empty() const noexcept {
- return calls.empty();
- }
- /**
- * @brief Triggers a signal.
- *
- * All the listeners are notified. Order isn't guaranteed.
- *
- * @param args Arguments to use to invoke listeners.
- */
- void publish(Args... args) const {
- for(auto pos = calls.size(); pos; --pos) {
- calls[pos - 1u](args...);
- }
- }
- /**
- * @brief Collects return values from the listeners.
- *
- * The collector must expose a call operator with the following properties:
- *
- * * The return type is either `void` or such that it's convertible to
- * `bool`. In the second case, a true value will stop the iteration.
- * * The list of parameters is empty if `Ret` is `void`, otherwise it
- * contains a single element such that `Ret` is convertible to it.
- *
- * @tparam Func Type of collector to use, if any.
- * @param func A valid function object.
- * @param args Arguments to use to invoke listeners.
- */
- template<typename Func>
- void collect(Func func, Args... args) const {
- for(auto pos = calls.size(); pos; --pos) {
- if constexpr(std::is_void_v<Ret> || !std::is_invocable_v<Func, Ret>) {
- calls[pos - 1u](args...);
- if constexpr(std::is_invocable_r_v<bool, Func>) {
- if(func()) {
- break;
- }
- } else {
- func();
- }
- } else {
- if constexpr(std::is_invocable_r_v<bool, Func, Ret>) {
- if(func(calls[pos - 1u](args...))) {
- break;
- }
- } else {
- func(calls[pos - 1u](args...));
- }
- }
- }
- }
- private:
- container_type calls;
- };
- /**
- * @brief Connection class.
- *
- * Opaque object the aim of which is to allow users to release an already
- * estabilished connection without having to keep a reference to the signal or
- * the sink that generated it.
- */
- class connection {
- template<typename>
- friend class sink;
- connection(delegate<void(void *)> fn, void *ref)
- : disconnect{fn}, signal{ref} {}
- public:
- /*! @brief Default constructor. */
- connection()
- : signal{} {}
- /**
- * @brief Checks whether a connection is properly initialized.
- * @return True if the connection is properly initialized, false otherwise.
- */
- [[nodiscard]] explicit operator bool() const noexcept {
- return static_cast<bool>(disconnect);
- }
- /*! @brief Breaks the connection. */
- void release() {
- if(disconnect) {
- disconnect(signal);
- disconnect.reset();
- }
- }
- private:
- delegate<void(void *)> disconnect;
- void *signal;
- };
- /**
- * @brief Scoped connection class.
- *
- * Opaque object the aim of which is to allow users to release an already
- * estabilished connection without having to keep a reference to the signal or
- * the sink that generated it.<br/>
- * A scoped connection automatically breaks the link between the two objects
- * when it goes out of scope.
- */
- struct scoped_connection {
- /*! @brief Default constructor. */
- scoped_connection() = default;
- /**
- * @brief Constructs a scoped connection from a basic connection.
- * @param other A valid connection object.
- */
- scoped_connection(const connection &other)
- : conn{other} {}
- /*! @brief Default copy constructor, deleted on purpose. */
- scoped_connection(const scoped_connection &) = delete;
- /**
- * @brief Move constructor.
- * @param other The scoped connection to move from.
- */
- scoped_connection(scoped_connection &&other) noexcept
- : conn{std::exchange(other.conn, {})} {}
- /*! @brief Automatically breaks the link on destruction. */
- ~scoped_connection() {
- conn.release();
- }
- /**
- * @brief Default copy assignment operator, deleted on purpose.
- * @return This scoped connection.
- */
- scoped_connection &operator=(const scoped_connection &) = delete;
- /**
- * @brief Move assignment operator.
- * @param other The scoped connection to move from.
- * @return This scoped connection.
- */
- scoped_connection &operator=(scoped_connection &&other) noexcept {
- conn = std::exchange(other.conn, {});
- return *this;
- }
- /**
- * @brief Acquires a connection.
- * @param other The connection object to acquire.
- * @return This scoped connection.
- */
- scoped_connection &operator=(connection other) {
- conn = other;
- return *this;
- }
- /**
- * @brief Checks whether a scoped connection is properly initialized.
- * @return True if the connection is properly initialized, false otherwise.
- */
- [[nodiscard]] explicit operator bool() const noexcept {
- return static_cast<bool>(conn);
- }
- /*! @brief Breaks the connection. */
- void release() {
- conn.release();
- }
- private:
- connection conn;
- };
- /**
- * @brief Sink class.
- *
- * A sink is used to connect listeners to signals and to disconnect them.<br/>
- * The function type for a listener is the one of the signal to which it
- * belongs.
- *
- * The clear separation between a signal and a sink permits to store the former
- * as private data member without exposing the publish functionality to the
- * users of the class.
- *
- * @warning
- * Lifetime of a sink must not overcome that of the signal to which it refers.
- * In any other case, attempting to use a sink results in undefined behavior.
- *
- * @tparam Ret Return type of a function type.
- * @tparam Args Types of arguments of a function type.
- * @tparam Allocator Type of allocator used to manage memory and elements.
- */
- template<typename Ret, typename... Args, typename Allocator>
- class sink<sigh<Ret(Args...), Allocator>> {
- using signal_type = sigh<Ret(Args...), Allocator>;
- using delegate_type = typename signal_type::delegate_type;
- using difference_type = typename signal_type::container_type::difference_type;
- template<auto Candidate, typename Type>
- static void release(Type value_or_instance, void *signal) {
- sink{*static_cast<signal_type *>(signal)}.disconnect<Candidate>(value_or_instance);
- }
- template<auto Candidate>
- static void release(void *signal) {
- sink{*static_cast<signal_type *>(signal)}.disconnect<Candidate>();
- }
- template<typename Func>
- void disconnect_if(Func callback) {
- auto &ref = signal_or_assert();
- for(auto pos = ref.calls.size(); pos; --pos) {
- if(auto &elem = ref.calls[pos - 1u]; callback(elem)) {
- elem = std::move(ref.calls.back());
- ref.calls.pop_back();
- }
- }
- }
- [[nodiscard]] auto &signal_or_assert() const noexcept {
- ENTT_ASSERT(signal != nullptr, "Invalid pointer to signal");
- return *signal;
- }
- public:
- /*! @brief Constructs an invalid sink. */
- sink() noexcept
- : signal{} {}
- /**
- * @brief Constructs a sink that is allowed to modify a given signal.
- * @param ref A valid reference to a signal object.
- */
- sink(sigh<Ret(Args...), Allocator> &ref) noexcept
- : signal{&ref} {}
- /**
- * @brief Returns false if at least a listener is connected to the sink.
- * @return True if the sink has no listeners connected, false otherwise.
- */
- [[nodiscard]] bool empty() const noexcept {
- return signal_or_assert().calls.empty();
- }
- /**
- * @brief Connects a free function or an unbound member to a signal.
- * @tparam Candidate Function or member to connect to the signal.
- * @return A properly initialized connection object.
- */
- template<auto Candidate>
- connection connect() {
- disconnect<Candidate>();
- delegate_type call{};
- call.template connect<Candidate>();
- signal_or_assert().calls.push_back(std::move(call));
- delegate<void(void *)> conn{};
- conn.template connect<&release<Candidate>>();
- return {conn, signal};
- }
- /**
- * @brief Connects a free function with payload or a bound member to a
- * signal.
- *
- * The signal isn't responsible for the connected object or the payload.
- * Users must always guarantee that the lifetime of the instance overcomes
- * the one of the signal.<br/>
- * When used to connect a free function with payload, its signature must be
- * such that the instance is the first argument before the ones used to
- * define the signal itself.
- *
- * @tparam Candidate Function or member to connect to the signal.
- * @tparam Type Type of class or type of payload.
- * @param value_or_instance A valid reference that fits the purpose.
- * @return A properly initialized connection object.
- */
- template<auto Candidate, typename Type>
- connection connect(Type &value_or_instance) {
- disconnect<Candidate>(value_or_instance);
- delegate_type call{};
- call.template connect<Candidate>(value_or_instance);
- signal_or_assert().calls.push_back(std::move(call));
- delegate<void(void *)> conn{};
- conn.template connect<&release<Candidate, Type &>>(value_or_instance);
- return {conn, signal};
- }
- /**
- * @brief Connects a free function with payload or a bound member to a
- * signal.
- *
- * @sa connect(Type &)
- *
- * @tparam Candidate Function or member to connect to the signal.
- * @tparam Type Type of class or type of payload.
- * @param value_or_instance A valid pointer that fits the purpose.
- * @return A properly initialized connection object.
- */
- template<auto Candidate, typename Type>
- connection connect(Type *value_or_instance) {
- disconnect<Candidate>(value_or_instance);
- delegate_type call{};
- call.template connect<Candidate>(value_or_instance);
- signal_or_assert().calls.push_back(std::move(call));
- delegate<void(void *)> conn{};
- conn.template connect<&release<Candidate, Type *>>(value_or_instance);
- return {conn, signal};
- }
- /**
- * @brief Disconnects a free function or an unbound member from a signal.
- * @tparam Candidate Function or member to disconnect from the signal.
- */
- template<auto Candidate>
- void disconnect() {
- delegate_type call{};
- call.template connect<Candidate>();
- disconnect_if([&call](const auto &elem) { return elem == call; });
- }
- /**
- * @brief Disconnects a free function with payload or a bound member from a
- * signal.
- *
- * The signal isn't responsible for the connected object or the payload.
- * Users must always guarantee that the lifetime of the instance overcomes
- * the one of the signal.<br/>
- * When used to connect a free function with payload, its signature must be
- * such that the instance is the first argument before the ones used to
- * define the signal itself.
- *
- * @tparam Candidate Function or member to disconnect from the signal.
- * @tparam Type Type of class or type of payload, if any.
- * @param value_or_instance A valid reference that fits the purpose.
- */
- template<auto Candidate, typename Type>
- void disconnect(Type &value_or_instance) {
- delegate_type call{};
- call.template connect<Candidate>(value_or_instance);
- disconnect_if([&call](const auto &elem) { return elem == call; });
- }
- /**
- * @brief Disconnects a free function with payload or a bound member from a
- * signal.
- *
- * @sa disconnect(Type &)
- *
- * @tparam Candidate Function or member to disconnect from the signal.
- * @tparam Type Type of class or type of payload, if any.
- * @param value_or_instance A valid pointer that fits the purpose.
- */
- template<auto Candidate, typename Type>
- void disconnect(Type *value_or_instance) {
- delegate_type call{};
- call.template connect<Candidate>(value_or_instance);
- disconnect_if([&call](const auto &elem) { return elem == call; });
- }
- /**
- * @brief Disconnects free functions with payload or bound members from a
- * signal.
- * @param value_or_instance A valid object that fits the purpose.
- */
- void disconnect(const void *value_or_instance) {
- ENTT_ASSERT(value_or_instance != nullptr, "Invalid value or instance");
- disconnect_if([value_or_instance](const auto &elem) { return elem.data() == value_or_instance; });
- }
- /*! @brief Disconnects all the listeners from a signal. */
- void disconnect() {
- signal_or_assert().calls.clear();
- }
- /**
- * @brief Returns true if a sink is correctly initialized, false otherwise.
- * @return True if a sink is correctly initialized, false otherwise.
- */
- [[nodiscard]] explicit operator bool() const noexcept {
- return signal != nullptr;
- }
- private:
- signal_type *signal;
- };
- /**
- * @brief Deduction guide.
- *
- * It allows to deduce the signal handler type of a sink directly from the
- * signal it refers to.
- *
- * @tparam Ret Return type of a function type.
- * @tparam Args Types of arguments of a function type.
- * @tparam Allocator Type of allocator used to manage memory and elements.
- */
- template<typename Ret, typename... Args, typename Allocator>
- sink(sigh<Ret(Args...), Allocator> &) -> sink<sigh<Ret(Args...), Allocator>>;
- } // namespace entt
- #endif
- // #include "entity.hpp"
- // #include "fwd.hpp"
- namespace entt {
- /*! @cond TURN_OFF_DOXYGEN */
- namespace internal {
- template<typename, typename, typename = void>
- struct has_on_construct final: std::false_type {};
- template<typename Type, typename Registry>
- struct has_on_construct<Type, Registry, std::void_t<decltype(Type::on_construct(std::declval<Registry &>(), std::declval<Registry>().create()))>>
- : std::true_type {};
- template<typename, typename, typename = void>
- struct has_on_update final: std::false_type {};
- template<typename Type, typename Registry>
- struct has_on_update<Type, Registry, std::void_t<decltype(Type::on_update(std::declval<Registry &>(), std::declval<Registry>().create()))>>
- : std::true_type {};
- template<typename, typename, typename = void>
- struct has_on_destroy final: std::false_type {};
- template<typename Type, typename Registry>
- struct has_on_destroy<Type, Registry, std::void_t<decltype(Type::on_destroy(std::declval<Registry &>(), std::declval<Registry>().create()))>>
- : std::true_type {};
- } // namespace internal
- /*! @endcond */
- /**
- * @brief Mixin type used to add signal support to storage types.
- *
- * The function type of a listener is equivalent to:
- *
- * @code{.cpp}
- * void(basic_registry<entity_type> &, entity_type);
- * @endcode
- *
- * This applies to all signals made available.
- *
- * @tparam Type Underlying storage type.
- * @tparam Registry Basic registry type.
- */
- template<typename Type, typename Registry>
- class basic_sigh_mixin final: public Type {
- using underlying_type = Type;
- using owner_type = Registry;
- using basic_registry_type = basic_registry<typename owner_type::entity_type, typename owner_type::allocator_type>;
- using sigh_type = sigh<void(owner_type &, const typename underlying_type::entity_type), typename underlying_type::allocator_type>;
- using underlying_iterator = typename underlying_type::base_type::basic_iterator;
- static_assert(std::is_base_of_v<basic_registry_type, owner_type>, "Invalid registry type");
- [[nodiscard]] auto &owner_or_assert() const noexcept {
- ENTT_ASSERT(owner != nullptr, "Invalid pointer to registry");
- return static_cast<owner_type &>(*owner);
- }
- private:
- void pop(underlying_iterator first, underlying_iterator last) final {
- if(auto ® = owner_or_assert(); destruction.empty()) {
- underlying_type::pop(first, last);
- } else {
- for(; first != last; ++first) {
- const auto entt = *first;
- destruction.publish(reg, entt);
- const auto it = underlying_type::find(entt);
- underlying_type::pop(it, it + 1u);
- }
- }
- }
- void pop_all() final {
- if(auto ® = owner_or_assert(); !destruction.empty()) {
- if constexpr(std::is_same_v<typename underlying_type::element_type, entity_type>) {
- for(typename underlying_type::size_type pos{}, last = underlying_type::free_list(); pos < last; ++pos) {
- destruction.publish(reg, underlying_type::base_type::operator[](pos));
- }
- } else {
- for(auto entt: static_cast<typename underlying_type::base_type &>(*this)) {
- if constexpr(underlying_type::storage_policy == deletion_policy::in_place) {
- if(entt != tombstone) {
- destruction.publish(reg, entt);
- }
- } else {
- destruction.publish(reg, entt);
- }
- }
- }
- }
- underlying_type::pop_all();
- }
- underlying_iterator try_emplace(const typename underlying_type::entity_type entt, const bool force_back, const void *value) final {
- const auto it = underlying_type::try_emplace(entt, force_back, value);
- if(auto ® = owner_or_assert(); it != underlying_type::base_type::end()) {
- construction.publish(reg, *it);
- }
- return it;
- }
- void bind_any(any value) noexcept final {
- owner = any_cast<basic_registry_type>(&value);
- if constexpr(!std::is_same_v<registry_type, basic_registry_type>) {
- if(owner == nullptr) {
- owner = any_cast<registry_type>(&value);
- }
- }
- underlying_type::bind_any(std::move(value));
- }
- public:
- /*! @brief Allocator type. */
- using allocator_type = typename underlying_type::allocator_type;
- /*! @brief Underlying entity identifier. */
- using entity_type = typename underlying_type::entity_type;
- /*! @brief Expected registry type. */
- using registry_type = owner_type;
- /*! @brief Default constructor. */
- basic_sigh_mixin()
- : basic_sigh_mixin{allocator_type{}} {}
- /**
- * @brief Constructs an empty storage with a given allocator.
- * @param allocator The allocator to use.
- */
- explicit basic_sigh_mixin(const allocator_type &allocator)
- : underlying_type{allocator},
- owner{},
- construction{allocator},
- destruction{allocator},
- update{allocator} {
- if constexpr(internal::has_on_construct<typename underlying_type::element_type, Registry>::value) {
- sink{construction}.template connect<&underlying_type::element_type::on_construct>();
- }
- if constexpr(internal::has_on_update<typename underlying_type::element_type, Registry>::value) {
- sink{update}.template connect<&underlying_type::element_type::on_update>();
- }
- if constexpr(internal::has_on_destroy<typename underlying_type::element_type, Registry>::value) {
- sink{destruction}.template connect<&underlying_type::element_type::on_destroy>();
- }
- }
- /*! @brief Default copy constructor, deleted on purpose. */
- basic_sigh_mixin(const basic_sigh_mixin &) = delete;
- /**
- * @brief Move constructor.
- * @param other The instance to move from.
- */
- basic_sigh_mixin(basic_sigh_mixin &&other) noexcept
- : underlying_type{static_cast<underlying_type &&>(other)},
- owner{other.owner},
- construction{std::move(other.construction)},
- destruction{std::move(other.destruction)},
- update{std::move(other.update)} {}
- /**
- * @brief Allocator-extended move constructor.
- * @param other The instance to move from.
- * @param allocator The allocator to use.
- */
- basic_sigh_mixin(basic_sigh_mixin &&other, const allocator_type &allocator)
- : underlying_type{static_cast<underlying_type &&>(other), allocator},
- owner{other.owner},
- construction{std::move(other.construction), allocator},
- destruction{std::move(other.destruction), allocator},
- update{std::move(other.update), allocator} {}
- /*! @brief Default destructor. */
- ~basic_sigh_mixin() override = default;
- /**
- * @brief Default copy assignment operator, deleted on purpose.
- * @return This mixin.
- */
- basic_sigh_mixin &operator=(const basic_sigh_mixin &) = delete;
- /**
- * @brief Move assignment operator.
- * @param other The instance to move from.
- * @return This mixin.
- */
- basic_sigh_mixin &operator=(basic_sigh_mixin &&other) noexcept {
- swap(other);
- return *this;
- }
- /**
- * @brief Exchanges the contents with those of a given storage.
- * @param other Storage to exchange the content with.
- */
- void swap(basic_sigh_mixin &other) noexcept {
- using std::swap;
- swap(owner, other.owner);
- swap(construction, other.construction);
- swap(destruction, other.destruction);
- swap(update, other.update);
- underlying_type::swap(other);
- }
- /**
- * @brief Returns a sink object.
- *
- * The sink returned by this function can be used to receive notifications
- * whenever a new instance is created and assigned to an entity.<br/>
- * Listeners are invoked after the object has been assigned to the entity.
- *
- * @sa sink
- *
- * @return A temporary sink object.
- */
- [[nodiscard]] auto on_construct() noexcept {
- return sink{construction};
- }
- /**
- * @brief Returns a sink object.
- *
- * The sink returned by this function can be used to receive notifications
- * whenever an instance is explicitly updated.<br/>
- * Listeners are invoked after the object has been updated.
- *
- * @sa sink
- *
- * @return A temporary sink object.
- */
- [[nodiscard]] auto on_update() noexcept {
- return sink{update};
- }
- /**
- * @brief Returns a sink object.
- *
- * The sink returned by this function can be used to receive notifications
- * whenever an instance is removed from an entity and thus destroyed.<br/>
- * Listeners are invoked before the object has been removed from the entity.
- *
- * @sa sink
- *
- * @return A temporary sink object.
- */
- [[nodiscard]] auto on_destroy() noexcept {
- return sink{destruction};
- }
- /**
- * @brief Checks if a mixin refers to a valid registry.
- * @return True if the mixin refers to a valid registry, false otherwise.
- */
- [[nodiscard]] explicit operator bool() const noexcept {
- return (owner != nullptr);
- }
- /**
- * @brief Returns a pointer to the underlying registry, if any.
- * @return A pointer to the underlying registry, if any.
- */
- [[nodiscard]] const registry_type ®istry() const noexcept {
- return owner_or_assert();
- }
- /*! @copydoc registry */
- [[nodiscard]] registry_type ®istry() noexcept {
- return owner_or_assert();
- }
- /**
- * @brief Creates a new identifier or recycles a destroyed one.
- * @return A valid identifier.
- */
- auto generate() {
- const auto entt = underlying_type::generate();
- construction.publish(owner_or_assert(), entt);
- return entt;
- }
- /**
- * @brief Creates a new identifier or recycles a destroyed one.
- * @param hint Required identifier.
- * @return A valid identifier.
- */
- entity_type generate(const entity_type hint) {
- const auto entt = underlying_type::generate(hint);
- construction.publish(owner_or_assert(), entt);
- return entt;
- }
- /**
- * @brief Assigns each element in a range an identifier.
- * @tparam It Type of mutable forward iterator.
- * @param first An iterator to the first element of the range to generate.
- * @param last An iterator past the last element of the range to generate.
- */
- template<typename It>
- void generate(It first, It last) {
- underlying_type::generate(first, last);
- if(auto ® = owner_or_assert(); !construction.empty()) {
- for(; first != last; ++first) {
- construction.publish(reg, *first);
- }
- }
- }
- /**
- * @brief Assigns an entity to a storage and constructs its object.
- * @tparam Args Types of arguments to forward to the underlying storage.
- * @param entt A valid identifier.
- * @param args Parameters to forward to the underlying storage.
- * @return A reference to the newly created object.
- */
- template<typename... Args>
- decltype(auto) emplace(const entity_type entt, Args &&...args) {
- underlying_type::emplace(entt, std::forward<Args>(args)...);
- construction.publish(owner_or_assert(), entt);
- return this->get(entt);
- }
- /**
- * @brief Updates the instance assigned to a given entity in-place.
- * @tparam Func Types of the function objects to invoke.
- * @param entt A valid identifier.
- * @param func Valid function objects.
- * @return A reference to the patched instance.
- */
- template<typename... Func>
- decltype(auto) patch(const entity_type entt, Func &&...func) {
- underlying_type::patch(entt, std::forward<Func>(func)...);
- update.publish(owner_or_assert(), entt);
- return this->get(entt);
- }
- /**
- * @brief Assigns one or more entities to a storage and constructs their
- * objects from a given instance.
- * @tparam It Type of input iterator.
- * @tparam Args Types of arguments to forward to the underlying storage.
- * @param first An iterator to the first element of the range of entities.
- * @param last An iterator past the last element of the range of entities.
- * @param args Parameters to use to forward to the underlying storage.
- */
- template<typename It, typename... Args>
- void insert(It first, It last, Args &&...args) {
- auto from = underlying_type::size();
- underlying_type::insert(first, last, std::forward<Args>(args)...);
- if(auto ® = owner_or_assert(); !construction.empty()) {
- // fine as long as insert passes force_back true to try_emplace
- for(const auto to = underlying_type::size(); from != to; ++from) {
- construction.publish(reg, underlying_type::operator[](from));
- }
- }
- }
- private:
- basic_registry_type *owner;
- sigh_type construction;
- sigh_type destruction;
- sigh_type update;
- };
- /**
- * @brief Mixin type used to add _reactive_ support to storage types.
- * @tparam Type Underlying storage type.
- * @tparam Registry Basic registry type.
- */
- template<typename Type, typename Registry>
- class basic_reactive_mixin final: public Type {
- using underlying_type = Type;
- using owner_type = Registry;
- using alloc_traits = std::allocator_traits<typename underlying_type::allocator_type>;
- using basic_registry_type = basic_registry<typename owner_type::entity_type, typename owner_type::allocator_type>;
- using container_type = std::vector<connection, typename alloc_traits::template rebind_alloc<connection>>;
- static_assert(std::is_base_of_v<basic_registry_type, owner_type>, "Invalid registry type");
- [[nodiscard]] auto &owner_or_assert() const noexcept {
- ENTT_ASSERT(owner != nullptr, "Invalid pointer to registry");
- return static_cast<owner_type &>(*owner);
- }
- void emplace_element(const Registry &, typename underlying_type::entity_type entity) {
- if(!underlying_type::contains(entity)) {
- underlying_type::emplace(entity);
- }
- }
- private:
- void bind_any(any value) noexcept final {
- owner = any_cast<basic_registry_type>(&value);
- if constexpr(!std::is_same_v<registry_type, basic_registry_type>) {
- if(owner == nullptr) {
- owner = any_cast<registry_type>(&value);
- }
- }
- underlying_type::bind_any(std::move(value));
- }
- public:
- /*! @brief Allocator type. */
- using allocator_type = typename underlying_type::allocator_type;
- /*! @brief Underlying entity identifier. */
- using entity_type = typename underlying_type::entity_type;
- /*! @brief Expected registry type. */
- using registry_type = owner_type;
- /*! @brief Default constructor. */
- basic_reactive_mixin()
- : basic_reactive_mixin{allocator_type{}} {}
- /**
- * @brief Constructs an empty storage with a given allocator.
- * @param allocator The allocator to use.
- */
- explicit basic_reactive_mixin(const allocator_type &allocator)
- : underlying_type{allocator},
- owner{},
- conn{allocator} {
- }
- /*! @brief Default copy constructor, deleted on purpose. */
- basic_reactive_mixin(const basic_reactive_mixin &) = delete;
- /**
- * @brief Move constructor.
- * @param other The instance to move from.
- */
- basic_reactive_mixin(basic_reactive_mixin &&other) noexcept
- : underlying_type{static_cast<underlying_type &&>(other)},
- owner{other.owner},
- conn{std::move(other.conn)} {
- }
- /**
- * @brief Allocator-extended move constructor.
- * @param other The instance to move from.
- * @param allocator The allocator to use.
- */
- basic_reactive_mixin(basic_reactive_mixin &&other, const allocator_type &allocator)
- : underlying_type{static_cast<underlying_type &&>(other), allocator},
- owner{other.owner},
- conn{std::move(other.conn), allocator} {
- }
- /*! @brief Default destructor. */
- ~basic_reactive_mixin() override = default;
- /**
- * @brief Default copy assignment operator, deleted on purpose.
- * @return This mixin.
- */
- basic_reactive_mixin &operator=(const basic_reactive_mixin &) = delete;
- /**
- * @brief Move assignment operator.
- * @param other The instance to move from.
- * @return This mixin.
- */
- basic_reactive_mixin &operator=(basic_reactive_mixin &&other) noexcept {
- underlying_type::swap(other);
- return *this;
- }
- /**
- * @brief Makes storage _react_ to creation of objects of the given type.
- * @tparam Clazz Type of element to _react_ to.
- * @tparam Candidate Function to use to _react_ to the event.
- * @param id Optional name used to map the storage within the registry.
- * @return This mixin.
- */
- template<typename Clazz, auto Candidate = &basic_reactive_mixin::emplace_element>
- basic_reactive_mixin &on_construct(const id_type id = type_hash<Clazz>::value()) {
- auto curr = owner_or_assert().template storage<Clazz>(id).on_construct().template connect<Candidate>(*this);
- conn.push_back(std::move(curr));
- return *this;
- }
- /**
- * @brief Makes storage _react_ to update of objects of the given type.
- * @tparam Clazz Type of element to _react_ to.
- * @tparam Candidate Function to use to _react_ to the event.
- * @param id Optional name used to map the storage within the registry.
- * @return This mixin.
- */
- template<typename Clazz, auto Candidate = &basic_reactive_mixin::emplace_element>
- basic_reactive_mixin &on_update(const id_type id = type_hash<Clazz>::value()) {
- auto curr = owner_or_assert().template storage<Clazz>(id).on_update().template connect<Candidate>(*this);
- conn.push_back(std::move(curr));
- return *this;
- }
- /**
- * @brief Makes storage _react_ to destruction of objects of the given type.
- * @tparam Clazz Type of element to _react_ to.
- * @tparam Candidate Function to use to _react_ to the event.
- * @param id Optional name used to map the storage within the registry.
- * @return This mixin.
- */
- template<typename Clazz, auto Candidate = &basic_reactive_mixin::emplace_element>
- basic_reactive_mixin &on_destroy(const id_type id = type_hash<Clazz>::value()) {
- auto curr = owner_or_assert().template storage<Clazz>(id).on_destroy().template connect<Candidate>(*this);
- conn.push_back(std::move(curr));
- return *this;
- }
- /**
- * @brief Checks if a mixin refers to a valid registry.
- * @return True if the mixin refers to a valid registry, false otherwise.
- */
- [[nodiscard]] explicit operator bool() const noexcept {
- return (owner != nullptr);
- }
- /**
- * @brief Returns a pointer to the underlying registry, if any.
- * @return A pointer to the underlying registry, if any.
- */
- [[nodiscard]] const registry_type ®istry() const noexcept {
- return owner_or_assert();
- }
- /*! @copydoc registry */
- [[nodiscard]] registry_type ®istry() noexcept {
- return owner_or_assert();
- }
- /**
- * @brief Returns a view that is filtered by the underlying storage.
- * @tparam Get Types of elements used to construct the view.
- * @tparam Exclude Types of elements used to filter the view.
- * @return A newly created view.
- */
- template<typename... Get, typename... Exclude>
- [[nodiscard]] basic_view<get_t<const basic_reactive_mixin, typename basic_registry_type::template storage_for_type<const Get>...>, exclude_t<typename basic_registry_type::template storage_for_type<const Exclude>...>>
- view(exclude_t<Exclude...> = exclude_t{}) const {
- const owner_type &parent = owner_or_assert();
- basic_view<get_t<const basic_reactive_mixin, typename basic_registry_type::template storage_for_type<const Get>...>, exclude_t<typename basic_registry_type::template storage_for_type<const Exclude>...>> elem{};
- [&elem](const auto *...curr) { ((curr ? elem.storage(*curr) : void()), ...); }(parent.template storage<std::remove_const_t<Exclude>>()..., parent.template storage<std::remove_const_t<Get>>()..., this);
- return elem;
- }
- /*! @copydoc view */
- template<typename... Get, typename... Exclude>
- [[nodiscard]] basic_view<get_t<const basic_reactive_mixin, typename basic_registry_type::template storage_for_type<Get>...>, exclude_t<typename basic_registry_type::template storage_for_type<Exclude>...>>
- view(exclude_t<Exclude...> = exclude_t{}) {
- std::conditional_t<((std::is_const_v<Get> && ...) && (std::is_const_v<Exclude> && ...)), const owner_type, owner_type> &parent = owner_or_assert();
- return {*this, parent.template storage<std::remove_const_t<Get>>()..., parent.template storage<std::remove_const_t<Exclude>>()...};
- }
- /*! @brief Releases all connections to the underlying registry, if any. */
- void reset() {
- for(auto &&curr: conn) {
- curr.release();
- }
- conn.clear();
- }
- private:
- basic_registry_type *owner;
- container_type conn;
- };
- } // namespace entt
- #endif
- // #include "entity/organizer.hpp"
- #ifndef ENTT_ENTITY_ORGANIZER_HPP
- #define ENTT_ENTITY_ORGANIZER_HPP
- #include <cstddef>
- #include <type_traits>
- #include <utility>
- #include <vector>
- // #include "../core/type_info.hpp"
- // #include "../core/type_traits.hpp"
- // #include "../core/utility.hpp"
- #ifndef ENTT_CORE_UTILITY_HPP
- #define ENTT_CORE_UTILITY_HPP
- #include <type_traits>
- #include <utility>
- namespace entt {
- /*! @brief Identity function object (waiting for C++20). */
- struct identity {
- /*! @brief Indicates that this is a transparent function object. */
- using is_transparent = void;
- /**
- * @brief Returns its argument unchanged.
- * @tparam Type Type of the argument.
- * @param value The actual argument.
- * @return The submitted value as-is.
- */
- template<typename Type>
- [[nodiscard]] constexpr Type &&operator()(Type &&value) const noexcept {
- return std::forward<Type>(value);
- }
- };
- /**
- * @brief Constant utility to disambiguate overloaded members of a class.
- * @tparam Type Type of the desired overload.
- * @tparam Class Type of class to which the member belongs.
- * @param member A valid pointer to a member.
- * @return Pointer to the member.
- */
- template<typename Type, typename Class>
- [[nodiscard]] constexpr auto overload(Type Class::*member) noexcept {
- return member;
- }
- /**
- * @brief Constant utility to disambiguate overloaded functions.
- * @tparam Func Function type of the desired overload.
- * @param func A valid pointer to a function.
- * @return Pointer to the function.
- */
- template<typename Func>
- [[nodiscard]] constexpr auto overload(Func *func) noexcept {
- return func;
- }
- /**
- * @brief Helper type for visitors.
- * @tparam Func Types of function objects.
- */
- template<typename... Func>
- struct overloaded: Func... {
- using Func::operator()...;
- };
- /**
- * @brief Deduction guide.
- * @tparam Func Types of function objects.
- */
- template<typename... Func>
- overloaded(Func...) -> overloaded<Func...>;
- /**
- * @brief Basic implementation of a y-combinator.
- * @tparam Func Type of a potentially recursive function.
- */
- template<typename Func>
- struct y_combinator {
- /**
- * @brief Constructs a y-combinator from a given function.
- * @param recursive A potentially recursive function.
- */
- constexpr y_combinator(Func recursive) noexcept(std::is_nothrow_move_constructible_v<Func>)
- : func{std::move(recursive)} {}
- /**
- * @brief Invokes a y-combinator and therefore its underlying function.
- * @tparam Args Types of arguments to use to invoke the underlying function.
- * @param args Parameters to use to invoke the underlying function.
- * @return Return value of the underlying function, if any.
- */
- template<typename... Args>
- constexpr decltype(auto) operator()(Args &&...args) const noexcept(std::is_nothrow_invocable_v<Func, const y_combinator &, Args...>) {
- return func(*this, std::forward<Args>(args)...);
- }
- /*! @copydoc operator()() */
- template<typename... Args>
- constexpr decltype(auto) operator()(Args &&...args) noexcept(std::is_nothrow_invocable_v<Func, y_combinator &, Args...>) {
- return func(*this, std::forward<Args>(args)...);
- }
- private:
- Func func;
- };
- } // namespace entt
- #endif
- // #include "../graph/adjacency_matrix.hpp"
- #ifndef ENTT_GRAPH_ADJACENCY_MATRIX_HPP
- #define ENTT_GRAPH_ADJACENCY_MATRIX_HPP
- #include <cstddef>
- #include <iterator>
- #include <memory>
- #include <type_traits>
- #include <utility>
- #include <vector>
- // #include "../config/config.h"
- #ifndef ENTT_CONFIG_CONFIG_H
- #define ENTT_CONFIG_CONFIG_H
- // #include "version.h"
- #ifndef ENTT_CONFIG_VERSION_H
- #define ENTT_CONFIG_VERSION_H
- // #include "macro.h"
- #ifndef ENTT_CONFIG_MACRO_H
- #define ENTT_CONFIG_MACRO_H
- // NOLINTBEGIN(cppcoreguidelines-macro-usage)
- #define ENTT_STR(arg) #arg
- #define ENTT_XSTR(arg) ENTT_STR(arg)
- // NOLINTEND(cppcoreguidelines-macro-usage)
- #endif
- // NOLINTBEGIN(cppcoreguidelines-macro-*,modernize-macro-*)
- #define ENTT_VERSION_MAJOR 3
- #define ENTT_VERSION_MINOR 16
- #define ENTT_VERSION_PATCH 0
- #define ENTT_VERSION \
- ENTT_XSTR(ENTT_VERSION_MAJOR) \
- "." ENTT_XSTR(ENTT_VERSION_MINOR) "." ENTT_XSTR(ENTT_VERSION_PATCH)
- // NOLINTEND(cppcoreguidelines-macro-*,modernize-macro-*)
- #endif
- // NOLINTBEGIN(cppcoreguidelines-macro-usage)
- #if defined(__cpp_exceptions) && !defined(ENTT_NOEXCEPTION)
- # define ENTT_CONSTEXPR
- # define ENTT_THROW throw
- # define ENTT_TRY try
- # define ENTT_CATCH catch(...)
- #else
- # define ENTT_CONSTEXPR constexpr // use only with throwing functions (waiting for C++20)
- # define ENTT_THROW
- # define ENTT_TRY if(true)
- # define ENTT_CATCH if(false)
- #endif
- #if __has_include(<version>)
- # include <version>
- #
- # if defined(__cpp_consteval)
- # define ENTT_CONSTEVAL consteval
- # endif
- #endif
- #ifndef ENTT_CONSTEVAL
- # define ENTT_CONSTEVAL constexpr
- #endif
- #ifdef ENTT_USE_ATOMIC
- # include <atomic>
- # define ENTT_MAYBE_ATOMIC(Type) std::atomic<Type>
- #else
- # define ENTT_MAYBE_ATOMIC(Type) Type
- #endif
- #ifndef ENTT_ID_TYPE
- # include <cstdint>
- # define ENTT_ID_TYPE std::uint32_t
- #else
- # include <cstdint> // provides coverage for types in the std namespace
- #endif
- #ifndef ENTT_SPARSE_PAGE
- # define ENTT_SPARSE_PAGE 4096
- #endif
- #ifndef ENTT_PACKED_PAGE
- # define ENTT_PACKED_PAGE 1024
- #endif
- #ifdef ENTT_DISABLE_ASSERT
- # undef ENTT_ASSERT
- # define ENTT_ASSERT(condition, msg) (void(0))
- #elif !defined ENTT_ASSERT
- # include <cassert>
- # define ENTT_ASSERT(condition, msg) assert(((condition) && (msg)))
- #endif
- #ifdef ENTT_DISABLE_ASSERT
- # undef ENTT_ASSERT_CONSTEXPR
- # define ENTT_ASSERT_CONSTEXPR(condition, msg) (void(0))
- #elif !defined ENTT_ASSERT_CONSTEXPR
- # define ENTT_ASSERT_CONSTEXPR(condition, msg) ENTT_ASSERT(condition, msg)
- #endif
- #define ENTT_FAIL(msg) ENTT_ASSERT(false, msg);
- #ifdef ENTT_NO_ETO
- # define ENTT_ETO_TYPE(Type) void
- #else
- # define ENTT_ETO_TYPE(Type) Type
- #endif
- #ifdef ENTT_NO_MIXIN
- # define ENTT_STORAGE(Mixin, ...) __VA_ARGS__
- #else
- # define ENTT_STORAGE(Mixin, ...) Mixin<__VA_ARGS__>
- #endif
- #ifdef ENTT_STANDARD_CPP
- # define ENTT_NONSTD false
- #else
- # define ENTT_NONSTD true
- # if defined __clang__ || defined __GNUC__
- # define ENTT_PRETTY_FUNCTION __PRETTY_FUNCTION__
- # define ENTT_PRETTY_FUNCTION_PREFIX '='
- # define ENTT_PRETTY_FUNCTION_SUFFIX ']'
- # elif defined _MSC_VER
- # define ENTT_PRETTY_FUNCTION __FUNCSIG__
- # define ENTT_PRETTY_FUNCTION_PREFIX '<'
- # define ENTT_PRETTY_FUNCTION_SUFFIX '>'
- # endif
- #endif
- #ifndef ENTT_EXPORT
- # if defined _WIN32 || defined __CYGWIN__ || defined _MSC_VER
- # define ENTT_EXPORT __declspec(dllexport)
- # define ENTT_IMPORT __declspec(dllimport)
- # define ENTT_HIDDEN
- # elif defined __GNUC__ && __GNUC__ >= 4
- # define ENTT_EXPORT __attribute__((visibility("default")))
- # define ENTT_IMPORT __attribute__((visibility("default")))
- # define ENTT_HIDDEN __attribute__((visibility("hidden")))
- # else /* Unsupported compiler */
- # define ENTT_EXPORT
- # define ENTT_IMPORT
- # define ENTT_HIDDEN
- # endif
- #endif
- #ifndef ENTT_API
- # if defined ENTT_API_EXPORT
- # define ENTT_API ENTT_EXPORT
- # elif defined ENTT_API_IMPORT
- # define ENTT_API ENTT_IMPORT
- # else /* No API */
- # define ENTT_API
- # endif
- #endif
- #if defined _MSC_VER
- # pragma detect_mismatch("entt.version", ENTT_VERSION)
- # pragma detect_mismatch("entt.noexcept", ENTT_XSTR(ENTT_TRY))
- # pragma detect_mismatch("entt.id", ENTT_XSTR(ENTT_ID_TYPE))
- # pragma detect_mismatch("entt.nonstd", ENTT_XSTR(ENTT_NONSTD))
- #endif
- // NOLINTEND(cppcoreguidelines-macro-usage)
- #endif
- // #include "../core/iterator.hpp"
- #ifndef ENTT_CORE_ITERATOR_HPP
- #define ENTT_CORE_ITERATOR_HPP
- #include <iterator>
- #include <memory>
- #include <type_traits>
- #include <utility>
- namespace entt {
- /**
- * @brief Helper type to use as pointer with input iterators.
- * @tparam Type of wrapped value.
- */
- template<typename Type>
- struct input_iterator_pointer final {
- /*! @brief Value type. */
- using value_type = Type;
- /*! @brief Pointer type. */
- using pointer = Type *;
- /*! @brief Reference type. */
- using reference = Type &;
- /**
- * @brief Constructs a proxy object by move.
- * @param val Value to use to initialize the proxy object.
- */
- constexpr input_iterator_pointer(value_type &&val) noexcept(std::is_nothrow_move_constructible_v<value_type>)
- : value{std::move(val)} {}
- /**
- * @brief Access operator for accessing wrapped values.
- * @return A pointer to the wrapped value.
- */
- [[nodiscard]] constexpr pointer operator->() noexcept {
- return std::addressof(value);
- }
- /**
- * @brief Dereference operator for accessing wrapped values.
- * @return A reference to the wrapped value.
- */
- [[nodiscard]] constexpr reference operator*() noexcept {
- return value;
- }
- private:
- Type value;
- };
- /**
- * @brief Plain iota iterator (waiting for C++20).
- * @tparam Type Value type.
- */
- template<typename Type>
- class iota_iterator final {
- static_assert(std::is_integral_v<Type>, "Not an integral type");
- public:
- /*! @brief Value type, likely an integral one. */
- using value_type = Type;
- /*! @brief Invalid pointer type. */
- using pointer = void;
- /*! @brief Non-reference type, same as value type. */
- using reference = value_type;
- /*! @brief Difference type. */
- using difference_type = std::ptrdiff_t;
- /*! @brief Iterator category. */
- using iterator_category = std::input_iterator_tag;
- /*! @brief Default constructor. */
- constexpr iota_iterator() noexcept
- : current{} {}
- /**
- * @brief Constructs an iota iterator from a given value.
- * @param init The initial value assigned to the iota iterator.
- */
- constexpr iota_iterator(const value_type init) noexcept
- : current{init} {}
- /**
- * @brief Pre-increment operator.
- * @return This iota iterator.
- */
- constexpr iota_iterator &operator++() noexcept {
- return ++current, *this;
- }
- /**
- * @brief Post-increment operator.
- * @return This iota iterator.
- */
- constexpr iota_iterator operator++(int) noexcept {
- const iota_iterator orig = *this;
- return ++(*this), orig;
- }
- /**
- * @brief Dereference operator.
- * @return The underlying value.
- */
- [[nodiscard]] constexpr reference operator*() const noexcept {
- return current;
- }
- private:
- value_type current;
- };
- /**
- * @brief Comparison operator.
- * @tparam Type Value type of the iota iterator.
- * @param lhs A properly initialized iota iterator.
- * @param rhs A properly initialized iota iterator.
- * @return True if the two iterators are identical, false otherwise.
- */
- template<typename Type>
- [[nodiscard]] constexpr bool operator==(const iota_iterator<Type> &lhs, const iota_iterator<Type> &rhs) noexcept {
- return *lhs == *rhs;
- }
- /**
- * @brief Comparison operator.
- * @tparam Type Value type of the iota iterator.
- * @param lhs A properly initialized iota iterator.
- * @param rhs A properly initialized iota iterator.
- * @return True if the two iterators differ, false otherwise.
- */
- template<typename Type>
- [[nodiscard]] constexpr bool operator!=(const iota_iterator<Type> &lhs, const iota_iterator<Type> &rhs) noexcept {
- return !(lhs == rhs);
- }
- /**
- * @brief Utility class to create an iterable object from a pair of iterators.
- * @tparam It Type of iterator.
- * @tparam Sentinel Type of sentinel.
- */
- template<typename It, typename Sentinel = It>
- struct iterable_adaptor final {
- /*! @brief Value type. */
- using value_type = typename std::iterator_traits<It>::value_type;
- /*! @brief Iterator type. */
- using iterator = It;
- /*! @brief Sentinel type. */
- using sentinel = Sentinel;
- /*! @brief Default constructor. */
- constexpr iterable_adaptor() noexcept(std::is_nothrow_default_constructible_v<iterator> && std::is_nothrow_default_constructible_v<sentinel>)
- : first{},
- last{} {}
- /**
- * @brief Creates an iterable object from a pair of iterators.
- * @param from Begin iterator.
- * @param to End iterator.
- */
- constexpr iterable_adaptor(iterator from, sentinel to) noexcept(std::is_nothrow_move_constructible_v<iterator> && std::is_nothrow_move_constructible_v<sentinel>)
- : first{std::move(from)},
- last{std::move(to)} {}
- /**
- * @brief Returns an iterator to the beginning.
- * @return An iterator to the first element of the range.
- */
- [[nodiscard]] constexpr iterator begin() const noexcept {
- return first;
- }
- /**
- * @brief Returns an iterator to the end.
- * @return An iterator to the element following the last element of the
- * range.
- */
- [[nodiscard]] constexpr sentinel end() const noexcept {
- return last;
- }
- /*! @copydoc begin */
- [[nodiscard]] constexpr iterator cbegin() const noexcept {
- return begin();
- }
- /*! @copydoc end */
- [[nodiscard]] constexpr sentinel cend() const noexcept {
- return end();
- }
- private:
- It first;
- Sentinel last;
- };
- } // namespace entt
- #endif
- // #include "fwd.hpp"
- #ifndef ENTT_GRAPH_FWD_HPP
- #define ENTT_GRAPH_FWD_HPP
- #include <cstddef>
- #include <memory>
- // #include "../core/fwd.hpp"
- #ifndef ENTT_CORE_FWD_HPP
- #define ENTT_CORE_FWD_HPP
- #include <cstddef>
- #include <cstdint>
- // #include "../config/config.h"
- #ifndef ENTT_CONFIG_CONFIG_H
- #define ENTT_CONFIG_CONFIG_H
- // #include "version.h"
- #ifndef ENTT_CONFIG_VERSION_H
- #define ENTT_CONFIG_VERSION_H
- // #include "macro.h"
- #ifndef ENTT_CONFIG_MACRO_H
- #define ENTT_CONFIG_MACRO_H
- // NOLINTBEGIN(cppcoreguidelines-macro-usage)
- #define ENTT_STR(arg) #arg
- #define ENTT_XSTR(arg) ENTT_STR(arg)
- // NOLINTEND(cppcoreguidelines-macro-usage)
- #endif
- // NOLINTBEGIN(cppcoreguidelines-macro-*,modernize-macro-*)
- #define ENTT_VERSION_MAJOR 3
- #define ENTT_VERSION_MINOR 16
- #define ENTT_VERSION_PATCH 0
- #define ENTT_VERSION \
- ENTT_XSTR(ENTT_VERSION_MAJOR) \
- "." ENTT_XSTR(ENTT_VERSION_MINOR) "." ENTT_XSTR(ENTT_VERSION_PATCH)
- // NOLINTEND(cppcoreguidelines-macro-*,modernize-macro-*)
- #endif
- // NOLINTBEGIN(cppcoreguidelines-macro-usage)
- #if defined(__cpp_exceptions) && !defined(ENTT_NOEXCEPTION)
- # define ENTT_CONSTEXPR
- # define ENTT_THROW throw
- # define ENTT_TRY try
- # define ENTT_CATCH catch(...)
- #else
- # define ENTT_CONSTEXPR constexpr // use only with throwing functions (waiting for C++20)
- # define ENTT_THROW
- # define ENTT_TRY if(true)
- # define ENTT_CATCH if(false)
- #endif
- #if __has_include(<version>)
- # include <version>
- #
- # if defined(__cpp_consteval)
- # define ENTT_CONSTEVAL consteval
- # endif
- #endif
- #ifndef ENTT_CONSTEVAL
- # define ENTT_CONSTEVAL constexpr
- #endif
- #ifdef ENTT_USE_ATOMIC
- # include <atomic>
- # define ENTT_MAYBE_ATOMIC(Type) std::atomic<Type>
- #else
- # define ENTT_MAYBE_ATOMIC(Type) Type
- #endif
- #ifndef ENTT_ID_TYPE
- # include <cstdint>
- # define ENTT_ID_TYPE std::uint32_t
- #else
- # include <cstdint> // provides coverage for types in the std namespace
- #endif
- #ifndef ENTT_SPARSE_PAGE
- # define ENTT_SPARSE_PAGE 4096
- #endif
- #ifndef ENTT_PACKED_PAGE
- # define ENTT_PACKED_PAGE 1024
- #endif
- #ifdef ENTT_DISABLE_ASSERT
- # undef ENTT_ASSERT
- # define ENTT_ASSERT(condition, msg) (void(0))
- #elif !defined ENTT_ASSERT
- # include <cassert>
- # define ENTT_ASSERT(condition, msg) assert(((condition) && (msg)))
- #endif
- #ifdef ENTT_DISABLE_ASSERT
- # undef ENTT_ASSERT_CONSTEXPR
- # define ENTT_ASSERT_CONSTEXPR(condition, msg) (void(0))
- #elif !defined ENTT_ASSERT_CONSTEXPR
- # define ENTT_ASSERT_CONSTEXPR(condition, msg) ENTT_ASSERT(condition, msg)
- #endif
- #define ENTT_FAIL(msg) ENTT_ASSERT(false, msg);
- #ifdef ENTT_NO_ETO
- # define ENTT_ETO_TYPE(Type) void
- #else
- # define ENTT_ETO_TYPE(Type) Type
- #endif
- #ifdef ENTT_NO_MIXIN
- # define ENTT_STORAGE(Mixin, ...) __VA_ARGS__
- #else
- # define ENTT_STORAGE(Mixin, ...) Mixin<__VA_ARGS__>
- #endif
- #ifdef ENTT_STANDARD_CPP
- # define ENTT_NONSTD false
- #else
- # define ENTT_NONSTD true
- # if defined __clang__ || defined __GNUC__
- # define ENTT_PRETTY_FUNCTION __PRETTY_FUNCTION__
- # define ENTT_PRETTY_FUNCTION_PREFIX '='
- # define ENTT_PRETTY_FUNCTION_SUFFIX ']'
- # elif defined _MSC_VER
- # define ENTT_PRETTY_FUNCTION __FUNCSIG__
- # define ENTT_PRETTY_FUNCTION_PREFIX '<'
- # define ENTT_PRETTY_FUNCTION_SUFFIX '>'
- # endif
- #endif
- #ifndef ENTT_EXPORT
- # if defined _WIN32 || defined __CYGWIN__ || defined _MSC_VER
- # define ENTT_EXPORT __declspec(dllexport)
- # define ENTT_IMPORT __declspec(dllimport)
- # define ENTT_HIDDEN
- # elif defined __GNUC__ && __GNUC__ >= 4
- # define ENTT_EXPORT __attribute__((visibility("default")))
- # define ENTT_IMPORT __attribute__((visibility("default")))
- # define ENTT_HIDDEN __attribute__((visibility("hidden")))
- # else /* Unsupported compiler */
- # define ENTT_EXPORT
- # define ENTT_IMPORT
- # define ENTT_HIDDEN
- # endif
- #endif
- #ifndef ENTT_API
- # if defined ENTT_API_EXPORT
- # define ENTT_API ENTT_EXPORT
- # elif defined ENTT_API_IMPORT
- # define ENTT_API ENTT_IMPORT
- # else /* No API */
- # define ENTT_API
- # endif
- #endif
- #if defined _MSC_VER
- # pragma detect_mismatch("entt.version", ENTT_VERSION)
- # pragma detect_mismatch("entt.noexcept", ENTT_XSTR(ENTT_TRY))
- # pragma detect_mismatch("entt.id", ENTT_XSTR(ENTT_ID_TYPE))
- # pragma detect_mismatch("entt.nonstd", ENTT_XSTR(ENTT_NONSTD))
- #endif
- // NOLINTEND(cppcoreguidelines-macro-usage)
- #endif
- namespace entt {
- /*! @brief Possible modes of an any object. */
- enum class any_policy : std::uint8_t {
- /*! @brief Default mode, no element available. */
- empty,
- /*! @brief Owning mode, dynamically allocated element. */
- dynamic,
- /*! @brief Owning mode, embedded element. */
- embedded,
- /*! @brief Aliasing mode, non-const reference. */
- ref,
- /*! @brief Const aliasing mode, const reference. */
- cref
- };
- // NOLINTNEXTLINE(cppcoreguidelines-avoid-c-arrays, modernize-avoid-c-arrays)
- template<std::size_t Len = sizeof(double[2]), std::size_t = alignof(double[2])>
- class basic_any;
- /*! @brief Alias declaration for type identifiers. */
- using id_type = ENTT_ID_TYPE;
- /*! @brief Alias declaration for the most common use case. */
- using any = basic_any<>;
- template<typename, typename>
- class compressed_pair;
- template<typename>
- class basic_hashed_string;
- /*! @brief Aliases for common character types. */
- using hashed_string = basic_hashed_string<char>;
- /*! @brief Aliases for common character types. */
- using hashed_wstring = basic_hashed_string<wchar_t>;
- // NOLINTNEXTLINE(bugprone-forward-declaration-namespace)
- struct type_info;
- } // namespace entt
- #endif
- namespace entt {
- /*! @brief Undirected graph category tag. */
- struct directed_tag {};
- /*! @brief Directed graph category tag. */
- struct undirected_tag: directed_tag {};
- template<typename, typename = std::allocator<std::size_t>>
- class adjacency_matrix;
- template<typename = std::allocator<id_type>>
- class basic_flow;
- /*! @brief Alias declaration for the most common use case. */
- using flow = basic_flow<>;
- } // namespace entt
- #endif
- namespace entt {
- /*! @cond TURN_OFF_DOXYGEN */
- namespace internal {
- template<typename It>
- class edge_iterator {
- using size_type = std::size_t;
- void find_next() noexcept {
- for(; pos != last && !it[static_cast<typename It::difference_type>(pos)]; pos += offset) {}
- }
- public:
- using value_type = std::pair<size_type, size_type>;
- using pointer = input_iterator_pointer<value_type>;
- using reference = value_type;
- using difference_type = std::ptrdiff_t;
- using iterator_category = std::input_iterator_tag;
- using iterator_concept = std::forward_iterator_tag;
- constexpr edge_iterator() noexcept = default;
- // NOLINTNEXTLINE(bugprone-easily-swappable-parameters)
- constexpr edge_iterator(It base, const size_type vertices, const size_type from, const size_type to, const size_type step) noexcept
- : it{std::move(base)},
- vert{vertices},
- pos{from},
- last{to},
- offset{step} {
- find_next();
- }
- constexpr edge_iterator &operator++() noexcept {
- pos += offset;
- find_next();
- return *this;
- }
- constexpr edge_iterator operator++(int) noexcept {
- const edge_iterator orig = *this;
- return ++(*this), orig;
- }
- [[nodiscard]] constexpr reference operator*() const noexcept {
- return *operator->();
- }
- [[nodiscard]] constexpr pointer operator->() const noexcept {
- return std::make_pair<size_type>(pos / vert, pos % vert);
- }
- template<typename Type>
- friend constexpr bool operator==(const edge_iterator<Type> &, const edge_iterator<Type> &) noexcept;
- private:
- It it{};
- size_type vert{};
- size_type pos{};
- size_type last{};
- size_type offset{};
- };
- template<typename Container>
- [[nodiscard]] constexpr bool operator==(const edge_iterator<Container> &lhs, const edge_iterator<Container> &rhs) noexcept {
- return lhs.pos == rhs.pos;
- }
- template<typename Container>
- [[nodiscard]] constexpr bool operator!=(const edge_iterator<Container> &lhs, const edge_iterator<Container> &rhs) noexcept {
- return !(lhs == rhs);
- }
- } // namespace internal
- /*! @endcond */
- /**
- * @brief Basic implementation of a directed adjacency matrix.
- * @tparam Category Either a directed or undirected category tag.
- * @tparam Allocator Type of allocator used to manage memory and elements.
- */
- template<typename Category, typename Allocator>
- class adjacency_matrix {
- using alloc_traits = std::allocator_traits<Allocator>;
- static_assert(std::is_base_of_v<directed_tag, Category>, "Invalid graph category");
- static_assert(std::is_same_v<typename alloc_traits::value_type, std::size_t>, "Invalid value type");
- using container_type = std::vector<std::size_t, typename alloc_traits::template rebind_alloc<std::size_t>>;
- public:
- /*! @brief Allocator type. */
- using allocator_type = Allocator;
- /*! @brief Unsigned integer type. */
- using size_type = std::size_t;
- /*! @brief Vertex type. */
- using vertex_type = size_type;
- /*! @brief Edge type. */
- using edge_type = std::pair<vertex_type, vertex_type>;
- /*! @brief Vertex iterator type. */
- using vertex_iterator = iota_iterator<vertex_type>;
- /*! @brief Edge iterator type. */
- using edge_iterator = internal::edge_iterator<typename container_type::const_iterator>;
- /*! @brief Out-edge iterator type. */
- using out_edge_iterator = edge_iterator;
- /*! @brief In-edge iterator type. */
- using in_edge_iterator = edge_iterator;
- /*! @brief Graph category tag. */
- using graph_category = Category;
- /*! @brief Default constructor. */
- adjacency_matrix() noexcept(noexcept(allocator_type{}))
- : adjacency_matrix{0u} {
- }
- /**
- * @brief Constructs an empty container with a given allocator.
- * @param allocator The allocator to use.
- */
- explicit adjacency_matrix(const allocator_type &allocator) noexcept
- : adjacency_matrix{0u, allocator} {}
- /**
- * @brief Constructs an empty container with a given allocator and user
- * supplied number of vertices.
- * @param vertices Number of vertices.
- * @param allocator The allocator to use.
- */
- adjacency_matrix(const size_type vertices, const allocator_type &allocator = allocator_type{})
- : matrix{vertices * vertices, allocator},
- vert{vertices} {}
- /*! @brief Default copy constructor. */
- adjacency_matrix(const adjacency_matrix &) = default;
- /**
- * @brief Allocator-extended copy constructor.
- * @param other The instance to copy from.
- * @param allocator The allocator to use.
- */
- adjacency_matrix(const adjacency_matrix &other, const allocator_type &allocator)
- : matrix{other.matrix, allocator},
- vert{other.vert} {}
- /*! @brief Default move constructor. */
- adjacency_matrix(adjacency_matrix &&) noexcept = default;
- /**
- * @brief Allocator-extended move constructor.
- * @param other The instance to move from.
- * @param allocator The allocator to use.
- */
- adjacency_matrix(adjacency_matrix &&other, const allocator_type &allocator)
- : matrix{std::move(other.matrix), allocator},
- vert{other.vert} {}
- /*! @brief Default destructor. */
- ~adjacency_matrix() = default;
- /**
- * @brief Default copy assignment operator.
- * @return This container.
- */
- adjacency_matrix &operator=(const adjacency_matrix &) = default;
- /**
- * @brief Default move assignment operator.
- * @return This container.
- */
- adjacency_matrix &operator=(adjacency_matrix &&) noexcept = default;
- /**
- * @brief Exchanges the contents with those of a given adjacency matrix.
- * @param other Adjacency matrix to exchange the content with.
- */
- void swap(adjacency_matrix &other) noexcept {
- using std::swap;
- swap(matrix, other.matrix);
- swap(vert, other.vert);
- }
- /**
- * @brief Returns the associated allocator.
- * @return The associated allocator.
- */
- [[nodiscard]] constexpr allocator_type get_allocator() const noexcept {
- return matrix.get_allocator();
- }
- /*! @brief Clears the adjacency matrix. */
- void clear() noexcept {
- matrix.clear();
- vert = {};
- }
- /**
- * @brief Returns true if an adjacency matrix is empty, false otherwise.
- *
- * @warning
- * Potentially expensive, try to avoid it on hot paths.
- *
- * @return True if the adjacency matrix is empty, false otherwise.
- */
- [[nodiscard]] bool empty() const noexcept {
- const auto iterable = edges();
- return (iterable.begin() == iterable.end());
- }
- /**
- * @brief Returns the number of vertices.
- * @return The number of vertices.
- */
- [[nodiscard]] size_type size() const noexcept {
- return vert;
- }
- /**
- * @brief Returns an iterable object to visit all vertices of a matrix.
- * @return An iterable object to visit all vertices of a matrix.
- */
- [[nodiscard]] iterable_adaptor<vertex_iterator> vertices() const noexcept {
- return {0u, vert};
- }
- /**
- * @brief Returns an iterable object to visit all edges of a matrix.
- * @return An iterable object to visit all edges of a matrix.
- */
- [[nodiscard]] iterable_adaptor<edge_iterator> edges() const noexcept {
- const auto it = matrix.cbegin();
- const auto sz = matrix.size();
- return {{it, vert, 0u, sz, 1u}, {it, vert, sz, sz, 1u}};
- }
- /**
- * @brief Returns an iterable object to visit all out-edges of a vertex.
- * @param vertex The vertex of which to return all out-edges.
- * @return An iterable object to visit all out-edges of a vertex.
- */
- [[nodiscard]] iterable_adaptor<out_edge_iterator> out_edges(const vertex_type vertex) const noexcept {
- const auto it = matrix.cbegin();
- const auto from = vertex * vert;
- const auto to = from + vert;
- return {{it, vert, from, to, 1u}, {it, vert, to, to, 1u}};
- }
- /**
- * @brief Returns an iterable object to visit all in-edges of a vertex.
- * @param vertex The vertex of which to return all in-edges.
- * @return An iterable object to visit all in-edges of a vertex.
- */
- [[nodiscard]] iterable_adaptor<in_edge_iterator> in_edges(const vertex_type vertex) const noexcept {
- const auto it = matrix.cbegin();
- const auto from = vertex;
- const auto to = vert * vert + from;
- return {{it, vert, from, to, vert}, {it, vert, to, to, vert}};
- }
- /**
- * @brief Resizes an adjacency matrix.
- * @param vertices The new number of vertices.
- */
- void resize(const size_type vertices) {
- adjacency_matrix other{vertices, get_allocator()};
- for(auto [lhs, rhs]: edges()) {
- other.insert(lhs, rhs);
- }
- other.swap(*this);
- }
- /**
- * @brief Inserts an edge into the adjacency matrix, if it does not exist.
- * @param lhs The left hand vertex of the edge.
- * @param rhs The right hand vertex of the edge.
- * @return A pair consisting of an iterator to the inserted element (or to
- * the element that prevented the insertion) and a bool denoting whether the
- * insertion took place.
- */
- std::pair<edge_iterator, bool> insert(const vertex_type lhs, const vertex_type rhs) {
- const auto pos = lhs * vert + rhs;
- if constexpr(std::is_same_v<graph_category, undirected_tag>) {
- const auto rev = rhs * vert + lhs;
- ENTT_ASSERT(matrix[pos] == matrix[rev], "Something went really wrong");
- matrix[rev] = 1u;
- }
- const auto inserted = !std::exchange(matrix[pos], 1u);
- return {edge_iterator{matrix.cbegin(), vert, pos, matrix.size(), 1u}, inserted};
- }
- /**
- * @brief Removes the edge associated with a pair of given vertices.
- * @param lhs The left hand vertex of the edge.
- * @param rhs The right hand vertex of the edge.
- * @return Number of elements removed (either 0 or 1).
- */
- size_type erase(const vertex_type lhs, const vertex_type rhs) {
- const auto pos = lhs * vert + rhs;
- if constexpr(std::is_same_v<graph_category, undirected_tag>) {
- const auto rev = rhs * vert + lhs;
- ENTT_ASSERT(matrix[pos] == matrix[rev], "Something went really wrong");
- matrix[rev] = 0u;
- }
- return std::exchange(matrix[pos], 0u);
- }
- /**
- * @brief Checks if an adjacency matrix contains a given edge.
- * @param lhs The left hand vertex of the edge.
- * @param rhs The right hand vertex of the edge.
- * @return True if there is such an edge, false otherwise.
- */
- [[nodiscard]] bool contains(const vertex_type lhs, const vertex_type rhs) const {
- const auto pos = lhs * vert + rhs;
- return pos < matrix.size() && matrix[pos];
- }
- private:
- container_type matrix;
- size_type vert;
- };
- } // namespace entt
- #endif
- // #include "../graph/flow.hpp"
- #ifndef ENTT_GRAPH_FLOW_HPP
- #define ENTT_GRAPH_FLOW_HPP
- #include <algorithm>
- #include <cstddef>
- #include <functional>
- #include <iterator>
- #include <memory>
- #include <type_traits>
- #include <utility>
- #include <vector>
- // #include "../config/config.h"
- // #include "../container/dense_map.hpp"
- #ifndef ENTT_CONTAINER_DENSE_MAP_HPP
- #define ENTT_CONTAINER_DENSE_MAP_HPP
- #include <cmath>
- #include <cstddef>
- #include <functional>
- #include <iterator>
- #include <limits>
- #include <memory>
- #include <tuple>
- #include <type_traits>
- #include <utility>
- #include <vector>
- // #include "../config/config.h"
- #ifndef ENTT_CONFIG_CONFIG_H
- #define ENTT_CONFIG_CONFIG_H
- // #include "version.h"
- #ifndef ENTT_CONFIG_VERSION_H
- #define ENTT_CONFIG_VERSION_H
- // #include "macro.h"
- #ifndef ENTT_CONFIG_MACRO_H
- #define ENTT_CONFIG_MACRO_H
- // NOLINTBEGIN(cppcoreguidelines-macro-usage)
- #define ENTT_STR(arg) #arg
- #define ENTT_XSTR(arg) ENTT_STR(arg)
- // NOLINTEND(cppcoreguidelines-macro-usage)
- #endif
- // NOLINTBEGIN(cppcoreguidelines-macro-*,modernize-macro-*)
- #define ENTT_VERSION_MAJOR 3
- #define ENTT_VERSION_MINOR 16
- #define ENTT_VERSION_PATCH 0
- #define ENTT_VERSION \
- ENTT_XSTR(ENTT_VERSION_MAJOR) \
- "." ENTT_XSTR(ENTT_VERSION_MINOR) "." ENTT_XSTR(ENTT_VERSION_PATCH)
- // NOLINTEND(cppcoreguidelines-macro-*,modernize-macro-*)
- #endif
- // NOLINTBEGIN(cppcoreguidelines-macro-usage)
- #if defined(__cpp_exceptions) && !defined(ENTT_NOEXCEPTION)
- # define ENTT_CONSTEXPR
- # define ENTT_THROW throw
- # define ENTT_TRY try
- # define ENTT_CATCH catch(...)
- #else
- # define ENTT_CONSTEXPR constexpr // use only with throwing functions (waiting for C++20)
- # define ENTT_THROW
- # define ENTT_TRY if(true)
- # define ENTT_CATCH if(false)
- #endif
- #if __has_include(<version>)
- # include <version>
- #
- # if defined(__cpp_consteval)
- # define ENTT_CONSTEVAL consteval
- # endif
- #endif
- #ifndef ENTT_CONSTEVAL
- # define ENTT_CONSTEVAL constexpr
- #endif
- #ifdef ENTT_USE_ATOMIC
- # include <atomic>
- # define ENTT_MAYBE_ATOMIC(Type) std::atomic<Type>
- #else
- # define ENTT_MAYBE_ATOMIC(Type) Type
- #endif
- #ifndef ENTT_ID_TYPE
- # include <cstdint>
- # define ENTT_ID_TYPE std::uint32_t
- #else
- # include <cstdint> // provides coverage for types in the std namespace
- #endif
- #ifndef ENTT_SPARSE_PAGE
- # define ENTT_SPARSE_PAGE 4096
- #endif
- #ifndef ENTT_PACKED_PAGE
- # define ENTT_PACKED_PAGE 1024
- #endif
- #ifdef ENTT_DISABLE_ASSERT
- # undef ENTT_ASSERT
- # define ENTT_ASSERT(condition, msg) (void(0))
- #elif !defined ENTT_ASSERT
- # include <cassert>
- # define ENTT_ASSERT(condition, msg) assert(((condition) && (msg)))
- #endif
- #ifdef ENTT_DISABLE_ASSERT
- # undef ENTT_ASSERT_CONSTEXPR
- # define ENTT_ASSERT_CONSTEXPR(condition, msg) (void(0))
- #elif !defined ENTT_ASSERT_CONSTEXPR
- # define ENTT_ASSERT_CONSTEXPR(condition, msg) ENTT_ASSERT(condition, msg)
- #endif
- #define ENTT_FAIL(msg) ENTT_ASSERT(false, msg);
- #ifdef ENTT_NO_ETO
- # define ENTT_ETO_TYPE(Type) void
- #else
- # define ENTT_ETO_TYPE(Type) Type
- #endif
- #ifdef ENTT_NO_MIXIN
- # define ENTT_STORAGE(Mixin, ...) __VA_ARGS__
- #else
- # define ENTT_STORAGE(Mixin, ...) Mixin<__VA_ARGS__>
- #endif
- #ifdef ENTT_STANDARD_CPP
- # define ENTT_NONSTD false
- #else
- # define ENTT_NONSTD true
- # if defined __clang__ || defined __GNUC__
- # define ENTT_PRETTY_FUNCTION __PRETTY_FUNCTION__
- # define ENTT_PRETTY_FUNCTION_PREFIX '='
- # define ENTT_PRETTY_FUNCTION_SUFFIX ']'
- # elif defined _MSC_VER
- # define ENTT_PRETTY_FUNCTION __FUNCSIG__
- # define ENTT_PRETTY_FUNCTION_PREFIX '<'
- # define ENTT_PRETTY_FUNCTION_SUFFIX '>'
- # endif
- #endif
- #ifndef ENTT_EXPORT
- # if defined _WIN32 || defined __CYGWIN__ || defined _MSC_VER
- # define ENTT_EXPORT __declspec(dllexport)
- # define ENTT_IMPORT __declspec(dllimport)
- # define ENTT_HIDDEN
- # elif defined __GNUC__ && __GNUC__ >= 4
- # define ENTT_EXPORT __attribute__((visibility("default")))
- # define ENTT_IMPORT __attribute__((visibility("default")))
- # define ENTT_HIDDEN __attribute__((visibility("hidden")))
- # else /* Unsupported compiler */
- # define ENTT_EXPORT
- # define ENTT_IMPORT
- # define ENTT_HIDDEN
- # endif
- #endif
- #ifndef ENTT_API
- # if defined ENTT_API_EXPORT
- # define ENTT_API ENTT_EXPORT
- # elif defined ENTT_API_IMPORT
- # define ENTT_API ENTT_IMPORT
- # else /* No API */
- # define ENTT_API
- # endif
- #endif
- #if defined _MSC_VER
- # pragma detect_mismatch("entt.version", ENTT_VERSION)
- # pragma detect_mismatch("entt.noexcept", ENTT_XSTR(ENTT_TRY))
- # pragma detect_mismatch("entt.id", ENTT_XSTR(ENTT_ID_TYPE))
- # pragma detect_mismatch("entt.nonstd", ENTT_XSTR(ENTT_NONSTD))
- #endif
- // NOLINTEND(cppcoreguidelines-macro-usage)
- #endif
- // #include "../core/bit.hpp"
- #ifndef ENTT_CORE_BIT_HPP
- #define ENTT_CORE_BIT_HPP
- #include <cstddef>
- #include <limits>
- #include <type_traits>
- // #include "../config/config.h"
- #ifndef ENTT_CONFIG_CONFIG_H
- #define ENTT_CONFIG_CONFIG_H
- // #include "version.h"
- #ifndef ENTT_CONFIG_VERSION_H
- #define ENTT_CONFIG_VERSION_H
- // #include "macro.h"
- #ifndef ENTT_CONFIG_MACRO_H
- #define ENTT_CONFIG_MACRO_H
- // NOLINTBEGIN(cppcoreguidelines-macro-usage)
- #define ENTT_STR(arg) #arg
- #define ENTT_XSTR(arg) ENTT_STR(arg)
- // NOLINTEND(cppcoreguidelines-macro-usage)
- #endif
- // NOLINTBEGIN(cppcoreguidelines-macro-*,modernize-macro-*)
- #define ENTT_VERSION_MAJOR 3
- #define ENTT_VERSION_MINOR 16
- #define ENTT_VERSION_PATCH 0
- #define ENTT_VERSION \
- ENTT_XSTR(ENTT_VERSION_MAJOR) \
- "." ENTT_XSTR(ENTT_VERSION_MINOR) "." ENTT_XSTR(ENTT_VERSION_PATCH)
- // NOLINTEND(cppcoreguidelines-macro-*,modernize-macro-*)
- #endif
- // NOLINTBEGIN(cppcoreguidelines-macro-usage)
- #if defined(__cpp_exceptions) && !defined(ENTT_NOEXCEPTION)
- # define ENTT_CONSTEXPR
- # define ENTT_THROW throw
- # define ENTT_TRY try
- # define ENTT_CATCH catch(...)
- #else
- # define ENTT_CONSTEXPR constexpr // use only with throwing functions (waiting for C++20)
- # define ENTT_THROW
- # define ENTT_TRY if(true)
- # define ENTT_CATCH if(false)
- #endif
- #if __has_include(<version>)
- # include <version>
- #
- # if defined(__cpp_consteval)
- # define ENTT_CONSTEVAL consteval
- # endif
- #endif
- #ifndef ENTT_CONSTEVAL
- # define ENTT_CONSTEVAL constexpr
- #endif
- #ifdef ENTT_USE_ATOMIC
- # include <atomic>
- # define ENTT_MAYBE_ATOMIC(Type) std::atomic<Type>
- #else
- # define ENTT_MAYBE_ATOMIC(Type) Type
- #endif
- #ifndef ENTT_ID_TYPE
- # include <cstdint>
- # define ENTT_ID_TYPE std::uint32_t
- #else
- # include <cstdint> // provides coverage for types in the std namespace
- #endif
- #ifndef ENTT_SPARSE_PAGE
- # define ENTT_SPARSE_PAGE 4096
- #endif
- #ifndef ENTT_PACKED_PAGE
- # define ENTT_PACKED_PAGE 1024
- #endif
- #ifdef ENTT_DISABLE_ASSERT
- # undef ENTT_ASSERT
- # define ENTT_ASSERT(condition, msg) (void(0))
- #elif !defined ENTT_ASSERT
- # include <cassert>
- # define ENTT_ASSERT(condition, msg) assert(((condition) && (msg)))
- #endif
- #ifdef ENTT_DISABLE_ASSERT
- # undef ENTT_ASSERT_CONSTEXPR
- # define ENTT_ASSERT_CONSTEXPR(condition, msg) (void(0))
- #elif !defined ENTT_ASSERT_CONSTEXPR
- # define ENTT_ASSERT_CONSTEXPR(condition, msg) ENTT_ASSERT(condition, msg)
- #endif
- #define ENTT_FAIL(msg) ENTT_ASSERT(false, msg);
- #ifdef ENTT_NO_ETO
- # define ENTT_ETO_TYPE(Type) void
- #else
- # define ENTT_ETO_TYPE(Type) Type
- #endif
- #ifdef ENTT_NO_MIXIN
- # define ENTT_STORAGE(Mixin, ...) __VA_ARGS__
- #else
- # define ENTT_STORAGE(Mixin, ...) Mixin<__VA_ARGS__>
- #endif
- #ifdef ENTT_STANDARD_CPP
- # define ENTT_NONSTD false
- #else
- # define ENTT_NONSTD true
- # if defined __clang__ || defined __GNUC__
- # define ENTT_PRETTY_FUNCTION __PRETTY_FUNCTION__
- # define ENTT_PRETTY_FUNCTION_PREFIX '='
- # define ENTT_PRETTY_FUNCTION_SUFFIX ']'
- # elif defined _MSC_VER
- # define ENTT_PRETTY_FUNCTION __FUNCSIG__
- # define ENTT_PRETTY_FUNCTION_PREFIX '<'
- # define ENTT_PRETTY_FUNCTION_SUFFIX '>'
- # endif
- #endif
- #ifndef ENTT_EXPORT
- # if defined _WIN32 || defined __CYGWIN__ || defined _MSC_VER
- # define ENTT_EXPORT __declspec(dllexport)
- # define ENTT_IMPORT __declspec(dllimport)
- # define ENTT_HIDDEN
- # elif defined __GNUC__ && __GNUC__ >= 4
- # define ENTT_EXPORT __attribute__((visibility("default")))
- # define ENTT_IMPORT __attribute__((visibility("default")))
- # define ENTT_HIDDEN __attribute__((visibility("hidden")))
- # else /* Unsupported compiler */
- # define ENTT_EXPORT
- # define ENTT_IMPORT
- # define ENTT_HIDDEN
- # endif
- #endif
- #ifndef ENTT_API
- # if defined ENTT_API_EXPORT
- # define ENTT_API ENTT_EXPORT
- # elif defined ENTT_API_IMPORT
- # define ENTT_API ENTT_IMPORT
- # else /* No API */
- # define ENTT_API
- # endif
- #endif
- #if defined _MSC_VER
- # pragma detect_mismatch("entt.version", ENTT_VERSION)
- # pragma detect_mismatch("entt.noexcept", ENTT_XSTR(ENTT_TRY))
- # pragma detect_mismatch("entt.id", ENTT_XSTR(ENTT_ID_TYPE))
- # pragma detect_mismatch("entt.nonstd", ENTT_XSTR(ENTT_NONSTD))
- #endif
- // NOLINTEND(cppcoreguidelines-macro-usage)
- #endif
- namespace entt {
- /**
- * @brief Returns the number of set bits in a value (waiting for C++20 and
- * `std::popcount`).
- * @tparam Type Unsigned integer type.
- * @param value A value of unsigned integer type.
- * @return The number of set bits in the value.
- */
- template<typename Type>
- [[nodiscard]] constexpr std::enable_if_t<std::is_unsigned_v<Type>, int> popcount(const Type value) noexcept {
- return value ? (int(value & 1) + popcount(static_cast<Type>(value >> 1))) : 0;
- }
- /**
- * @brief Checks whether a value is a power of two or not (waiting for C++20 and
- * `std::has_single_bit`).
- * @tparam Type Unsigned integer type.
- * @param value A value of unsigned integer type.
- * @return True if the value is a power of two, false otherwise.
- */
- template<typename Type>
- [[nodiscard]] constexpr std::enable_if_t<std::is_unsigned_v<Type>, bool> has_single_bit(const Type value) noexcept {
- return value && ((value & (value - 1)) == 0);
- }
- /**
- * @brief Computes the smallest power of two greater than or equal to a value
- * (waiting for C++20 and `std::bit_ceil`).
- * @tparam Type Unsigned integer type.
- * @param value A value of unsigned integer type.
- * @return The smallest power of two greater than or equal to the given value.
- */
- template<typename Type>
- [[nodiscard]] constexpr std::enable_if_t<std::is_unsigned_v<Type>, Type> next_power_of_two(const Type value) noexcept {
- // NOLINTNEXTLINE(bugprone-assert-side-effect)
- ENTT_ASSERT_CONSTEXPR(value < (Type{1u} << (std::numeric_limits<Type>::digits - 1)), "Numeric limits exceeded");
- Type curr = value - (value != 0u);
- for(int next = 1; next < std::numeric_limits<Type>::digits; next = next * 2) {
- curr |= (curr >> next);
- }
- return ++curr;
- }
- /**
- * @brief Fast module utility function (powers of two only).
- * @tparam Type Unsigned integer type.
- * @param value A value of unsigned integer type.
- * @param mod _Modulus_, it must be a power of two.
- * @return The common remainder.
- */
- template<typename Type>
- [[nodiscard]] constexpr std::enable_if_t<std::is_unsigned_v<Type>, Type> fast_mod(const Type value, const std::size_t mod) noexcept {
- ENTT_ASSERT_CONSTEXPR(has_single_bit(mod), "Value must be a power of two");
- return static_cast<Type>(value & (mod - 1u));
- }
- } // namespace entt
- #endif
- // #include "../core/compressed_pair.hpp"
- #ifndef ENTT_CORE_COMPRESSED_PAIR_HPP
- #define ENTT_CORE_COMPRESSED_PAIR_HPP
- #include <cstddef>
- #include <tuple>
- #include <type_traits>
- #include <utility>
- // #include "fwd.hpp"
- #ifndef ENTT_CORE_FWD_HPP
- #define ENTT_CORE_FWD_HPP
- #include <cstddef>
- #include <cstdint>
- // #include "../config/config.h"
- namespace entt {
- /*! @brief Possible modes of an any object. */
- enum class any_policy : std::uint8_t {
- /*! @brief Default mode, no element available. */
- empty,
- /*! @brief Owning mode, dynamically allocated element. */
- dynamic,
- /*! @brief Owning mode, embedded element. */
- embedded,
- /*! @brief Aliasing mode, non-const reference. */
- ref,
- /*! @brief Const aliasing mode, const reference. */
- cref
- };
- // NOLINTNEXTLINE(cppcoreguidelines-avoid-c-arrays, modernize-avoid-c-arrays)
- template<std::size_t Len = sizeof(double[2]), std::size_t = alignof(double[2])>
- class basic_any;
- /*! @brief Alias declaration for type identifiers. */
- using id_type = ENTT_ID_TYPE;
- /*! @brief Alias declaration for the most common use case. */
- using any = basic_any<>;
- template<typename, typename>
- class compressed_pair;
- template<typename>
- class basic_hashed_string;
- /*! @brief Aliases for common character types. */
- using hashed_string = basic_hashed_string<char>;
- /*! @brief Aliases for common character types. */
- using hashed_wstring = basic_hashed_string<wchar_t>;
- // NOLINTNEXTLINE(bugprone-forward-declaration-namespace)
- struct type_info;
- } // namespace entt
- #endif
- // #include "type_traits.hpp"
- #ifndef ENTT_CORE_TYPE_TRAITS_HPP
- #define ENTT_CORE_TYPE_TRAITS_HPP
- #include <cstddef>
- #include <iterator>
- #include <tuple>
- #include <type_traits>
- #include <utility>
- // #include "../config/config.h"
- // #include "fwd.hpp"
- namespace entt {
- /**
- * @brief Utility class to disambiguate overloaded functions.
- * @tparam N Number of choices available.
- */
- template<std::size_t N>
- struct choice_t
- // unfortunately, doxygen cannot parse such a construct
- : /*! @cond TURN_OFF_DOXYGEN */ choice_t<N - 1> /*! @endcond */
- {};
- /*! @copybrief choice_t */
- template<>
- struct choice_t<0> {};
- /**
- * @brief Variable template for the choice trick.
- * @tparam N Number of choices available.
- */
- template<std::size_t N>
- inline constexpr choice_t<N> choice{};
- /**
- * @brief Identity type trait.
- *
- * Useful to establish non-deduced contexts in template argument deduction
- * (waiting for C++20) or to provide types through function arguments.
- *
- * @tparam Type A type.
- */
- template<typename Type>
- struct type_identity {
- /*! @brief Identity type. */
- using type = Type;
- };
- /**
- * @brief Helper type.
- * @tparam Type A type.
- */
- template<typename Type>
- using type_identity_t = typename type_identity<Type>::type;
- /**
- * @brief A type-only `sizeof` wrapper that returns 0 where `sizeof` complains.
- * @tparam Type The type of which to return the size.
- */
- template<typename Type, typename = void>
- struct size_of: std::integral_constant<std::size_t, 0u> {};
- /*! @copydoc size_of */
- template<typename Type>
- struct size_of<Type, std::void_t<decltype(sizeof(Type))>>
- // NOLINTNEXTLINE(bugprone-sizeof-expression)
- : std::integral_constant<std::size_t, sizeof(Type)> {};
- /**
- * @brief Helper variable template.
- * @tparam Type The type of which to return the size.
- */
- template<typename Type>
- inline constexpr std::size_t size_of_v = size_of<Type>::value;
- /**
- * @brief Using declaration to be used to _repeat_ the same type a number of
- * times equal to the size of a given parameter pack.
- * @tparam Type A type to repeat.
- */
- template<typename Type, typename>
- using unpack_as_type = Type;
- /**
- * @brief Helper variable template to be used to _repeat_ the same value a
- * number of times equal to the size of a given parameter pack.
- * @tparam Value A value to repeat.
- */
- template<auto Value, typename>
- inline constexpr auto unpack_as_value = Value;
- /**
- * @brief Wraps a static constant.
- * @tparam Value A static constant.
- */
- template<auto Value>
- using integral_constant = std::integral_constant<decltype(Value), Value>;
- /**
- * @brief Alias template to facilitate the creation of named values.
- * @tparam Value A constant value at least convertible to `id_type`.
- */
- template<id_type Value>
- using tag = integral_constant<Value>;
- /**
- * @brief A class to use to push around lists of types, nothing more.
- * @tparam Type Types provided by the type list.
- */
- template<typename... Type>
- struct type_list {
- /*! @brief Type list type. */
- using type = type_list;
- /*! @brief Compile-time number of elements in the type list. */
- static constexpr auto size = sizeof...(Type);
- };
- /*! @brief Primary template isn't defined on purpose. */
- template<std::size_t, typename>
- struct type_list_element;
- /**
- * @brief Provides compile-time indexed access to the types of a type list.
- * @tparam Index Index of the type to return.
- * @tparam First First type provided by the type list.
- * @tparam Other Other types provided by the type list.
- */
- template<std::size_t Index, typename First, typename... Other>
- struct type_list_element<Index, type_list<First, Other...>>
- : type_list_element<Index - 1u, type_list<Other...>> {};
- /**
- * @brief Provides compile-time indexed access to the types of a type list.
- * @tparam First First type provided by the type list.
- * @tparam Other Other types provided by the type list.
- */
- template<typename First, typename... Other>
- struct type_list_element<0u, type_list<First, Other...>> {
- /*! @brief Searched type. */
- using type = First;
- };
- /**
- * @brief Helper type.
- * @tparam Index Index of the type to return.
- * @tparam List Type list to search into.
- */
- template<std::size_t Index, typename List>
- using type_list_element_t = typename type_list_element<Index, List>::type;
- /*! @brief Primary template isn't defined on purpose. */
- template<typename, typename>
- struct type_list_index;
- /**
- * @brief Provides compile-time type access to the types of a type list.
- * @tparam Type Type to look for and for which to return the index.
- * @tparam First First type provided by the type list.
- * @tparam Other Other types provided by the type list.
- */
- template<typename Type, typename First, typename... Other>
- struct type_list_index<Type, type_list<First, Other...>> {
- /*! @brief Unsigned integer type. */
- using value_type = std::size_t;
- /*! @brief Compile-time position of the given type in the sublist. */
- static constexpr value_type value = 1u + type_list_index<Type, type_list<Other...>>::value;
- };
- /**
- * @brief Provides compile-time type access to the types of a type list.
- * @tparam Type Type to look for and for which to return the index.
- * @tparam Other Other types provided by the type list.
- */
- template<typename Type, typename... Other>
- struct type_list_index<Type, type_list<Type, Other...>> {
- static_assert(type_list_index<Type, type_list<Other...>>::value == sizeof...(Other), "Non-unique type");
- /*! @brief Unsigned integer type. */
- using value_type = std::size_t;
- /*! @brief Compile-time position of the given type in the sublist. */
- static constexpr value_type value = 0u;
- };
- /**
- * @brief Provides compile-time type access to the types of a type list.
- * @tparam Type Type to look for and for which to return the index.
- */
- template<typename Type>
- struct type_list_index<Type, type_list<>> {
- /*! @brief Unsigned integer type. */
- using value_type = std::size_t;
- /*! @brief Compile-time position of the given type in the sublist. */
- static constexpr value_type value = 0u;
- };
- /**
- * @brief Helper variable template.
- * @tparam List Type list.
- * @tparam Type Type to look for and for which to return the index.
- */
- template<typename Type, typename List>
- inline constexpr std::size_t type_list_index_v = type_list_index<Type, List>::value;
- /**
- * @brief Concatenates multiple type lists.
- * @tparam Type Types provided by the first type list.
- * @tparam Other Types provided by the second type list.
- * @return A type list composed by the types of both the type lists.
- */
- template<typename... Type, typename... Other>
- constexpr type_list<Type..., Other...> operator+(type_list<Type...>, type_list<Other...>) {
- return {};
- }
- /*! @brief Primary template isn't defined on purpose. */
- template<typename...>
- struct type_list_cat;
- /*! @brief Concatenates multiple type lists. */
- template<>
- struct type_list_cat<> {
- /*! @brief A type list composed by the types of all the type lists. */
- using type = type_list<>;
- };
- /**
- * @brief Concatenates multiple type lists.
- * @tparam Type Types provided by the first type list.
- * @tparam Other Types provided by the second type list.
- * @tparam List Other type lists, if any.
- */
- template<typename... Type, typename... Other, typename... List>
- struct type_list_cat<type_list<Type...>, type_list<Other...>, List...> {
- /*! @brief A type list composed by the types of all the type lists. */
- using type = typename type_list_cat<type_list<Type..., Other...>, List...>::type;
- };
- /**
- * @brief Concatenates multiple type lists.
- * @tparam Type Types provided by the type list.
- */
- template<typename... Type>
- struct type_list_cat<type_list<Type...>> {
- /*! @brief A type list composed by the types of all the type lists. */
- using type = type_list<Type...>;
- };
- /**
- * @brief Helper type.
- * @tparam List Type lists to concatenate.
- */
- template<typename... List>
- using type_list_cat_t = typename type_list_cat<List...>::type;
- /*! @cond TURN_OFF_DOXYGEN */
- namespace internal {
- template<typename...>
- struct type_list_unique;
- template<typename First, typename... Other, typename... Type>
- struct type_list_unique<type_list<First, Other...>, Type...>
- : std::conditional_t<(std::is_same_v<First, Type> || ...), type_list_unique<type_list<Other...>, Type...>, type_list_unique<type_list<Other...>, Type..., First>> {};
- template<typename... Type>
- struct type_list_unique<type_list<>, Type...> {
- using type = type_list<Type...>;
- };
- } // namespace internal
- /*! @endcond */
- /**
- * @brief Removes duplicates types from a type list.
- * @tparam List Type list.
- */
- template<typename List>
- struct type_list_unique {
- /*! @brief A type list without duplicate types. */
- using type = typename internal::type_list_unique<List>::type;
- };
- /**
- * @brief Helper type.
- * @tparam List Type list.
- */
- template<typename List>
- using type_list_unique_t = typename type_list_unique<List>::type;
- /**
- * @brief Provides the member constant `value` to true if a type list contains a
- * given type, false otherwise.
- * @tparam List Type list.
- * @tparam Type Type to look for.
- */
- template<typename List, typename Type>
- struct type_list_contains;
- /**
- * @copybrief type_list_contains
- * @tparam Type Types provided by the type list.
- * @tparam Other Type to look for.
- */
- template<typename... Type, typename Other>
- struct type_list_contains<type_list<Type...>, Other>
- : std::bool_constant<(std::is_same_v<Type, Other> || ...)> {};
- /**
- * @brief Helper variable template.
- * @tparam List Type list.
- * @tparam Type Type to look for.
- */
- template<typename List, typename Type>
- inline constexpr bool type_list_contains_v = type_list_contains<List, Type>::value;
- /*! @brief Primary template isn't defined on purpose. */
- template<typename...>
- struct type_list_diff;
- /**
- * @brief Computes the difference between two type lists.
- * @tparam Type Types provided by the first type list.
- * @tparam Other Types provided by the second type list.
- */
- template<typename... Type, typename... Other>
- struct type_list_diff<type_list<Type...>, type_list<Other...>> {
- /*! @brief A type list that is the difference between the two type lists. */
- using type = type_list_cat_t<std::conditional_t<type_list_contains_v<type_list<Other...>, Type>, type_list<>, type_list<Type>>...>;
- };
- /**
- * @brief Helper type.
- * @tparam List Type lists between which to compute the difference.
- */
- template<typename... List>
- using type_list_diff_t = typename type_list_diff<List...>::type;
- /*! @brief Primary template isn't defined on purpose. */
- template<typename, template<typename...> class>
- struct type_list_transform;
- /**
- * @brief Applies a given _function_ to a type list and generate a new list.
- * @tparam Type Types provided by the type list.
- * @tparam Op Unary operation as template class with a type member named `type`.
- */
- template<typename... Type, template<typename...> class Op>
- struct type_list_transform<type_list<Type...>, Op> {
- /*! @brief Resulting type list after applying the transform function. */
- // NOLINTNEXTLINE(modernize-type-traits)
- using type = type_list<typename Op<Type>::type...>;
- };
- /**
- * @brief Helper type.
- * @tparam List Type list.
- * @tparam Op Unary operation as template class with a type member named `type`.
- */
- template<typename List, template<typename...> class Op>
- using type_list_transform_t = typename type_list_transform<List, Op>::type;
- /**
- * @brief A class to use to push around lists of constant values, nothing more.
- * @tparam Value Values provided by the value list.
- */
- template<auto... Value>
- struct value_list {
- /*! @brief Value list type. */
- using type = value_list;
- /*! @brief Compile-time number of elements in the value list. */
- static constexpr auto size = sizeof...(Value);
- };
- /*! @brief Primary template isn't defined on purpose. */
- template<std::size_t, typename>
- struct value_list_element;
- /**
- * @brief Provides compile-time indexed access to the values of a value list.
- * @tparam Index Index of the value to return.
- * @tparam Value First value provided by the value list.
- * @tparam Other Other values provided by the value list.
- */
- template<std::size_t Index, auto Value, auto... Other>
- struct value_list_element<Index, value_list<Value, Other...>>
- : value_list_element<Index - 1u, value_list<Other...>> {};
- /**
- * @brief Provides compile-time indexed access to the types of a type list.
- * @tparam Value First value provided by the value list.
- * @tparam Other Other values provided by the value list.
- */
- template<auto Value, auto... Other>
- struct value_list_element<0u, value_list<Value, Other...>> {
- /*! @brief Searched type. */
- using type = decltype(Value);
- /*! @brief Searched value. */
- static constexpr auto value = Value;
- };
- /**
- * @brief Helper type.
- * @tparam Index Index of the type to return.
- * @tparam List Value list to search into.
- */
- template<std::size_t Index, typename List>
- using value_list_element_t = typename value_list_element<Index, List>::type;
- /**
- * @brief Helper type.
- * @tparam Index Index of the value to return.
- * @tparam List Value list to search into.
- */
- template<std::size_t Index, typename List>
- inline constexpr auto value_list_element_v = value_list_element<Index, List>::value;
- /*! @brief Primary template isn't defined on purpose. */
- template<auto, typename>
- struct value_list_index;
- /**
- * @brief Provides compile-time type access to the values of a value list.
- * @tparam Value Value to look for and for which to return the index.
- * @tparam First First value provided by the value list.
- * @tparam Other Other values provided by the value list.
- */
- template<auto Value, auto First, auto... Other>
- struct value_list_index<Value, value_list<First, Other...>> {
- /*! @brief Unsigned integer type. */
- using value_type = std::size_t;
- /*! @brief Compile-time position of the given value in the sublist. */
- static constexpr value_type value = 1u + value_list_index<Value, value_list<Other...>>::value;
- };
- /**
- * @brief Provides compile-time type access to the values of a value list.
- * @tparam Value Value to look for and for which to return the index.
- * @tparam Other Other values provided by the value list.
- */
- template<auto Value, auto... Other>
- struct value_list_index<Value, value_list<Value, Other...>> {
- static_assert(value_list_index<Value, value_list<Other...>>::value == sizeof...(Other), "Non-unique type");
- /*! @brief Unsigned integer type. */
- using value_type = std::size_t;
- /*! @brief Compile-time position of the given value in the sublist. */
- static constexpr value_type value = 0u;
- };
- /**
- * @brief Provides compile-time type access to the values of a value list.
- * @tparam Value Value to look for and for which to return the index.
- */
- template<auto Value>
- struct value_list_index<Value, value_list<>> {
- /*! @brief Unsigned integer type. */
- using value_type = std::size_t;
- /*! @brief Compile-time position of the given type in the sublist. */
- static constexpr value_type value = 0u;
- };
- /**
- * @brief Helper variable template.
- * @tparam List Value list.
- * @tparam Value Value to look for and for which to return the index.
- */
- template<auto Value, typename List>
- inline constexpr std::size_t value_list_index_v = value_list_index<Value, List>::value;
- /**
- * @brief Concatenates multiple value lists.
- * @tparam Value Values provided by the first value list.
- * @tparam Other Values provided by the second value list.
- * @return A value list composed by the values of both the value lists.
- */
- template<auto... Value, auto... Other>
- constexpr value_list<Value..., Other...> operator+(value_list<Value...>, value_list<Other...>) {
- return {};
- }
- /*! @brief Primary template isn't defined on purpose. */
- template<typename...>
- struct value_list_cat;
- /*! @brief Concatenates multiple value lists. */
- template<>
- struct value_list_cat<> {
- /*! @brief A value list composed by the values of all the value lists. */
- using type = value_list<>;
- };
- /**
- * @brief Concatenates multiple value lists.
- * @tparam Value Values provided by the first value list.
- * @tparam Other Values provided by the second value list.
- * @tparam List Other value lists, if any.
- */
- template<auto... Value, auto... Other, typename... List>
- struct value_list_cat<value_list<Value...>, value_list<Other...>, List...> {
- /*! @brief A value list composed by the values of all the value lists. */
- using type = typename value_list_cat<value_list<Value..., Other...>, List...>::type;
- };
- /**
- * @brief Concatenates multiple value lists.
- * @tparam Value Values provided by the value list.
- */
- template<auto... Value>
- struct value_list_cat<value_list<Value...>> {
- /*! @brief A value list composed by the values of all the value lists. */
- using type = value_list<Value...>;
- };
- /**
- * @brief Helper type.
- * @tparam List Value lists to concatenate.
- */
- template<typename... List>
- using value_list_cat_t = typename value_list_cat<List...>::type;
- /*! @brief Primary template isn't defined on purpose. */
- template<typename>
- struct value_list_unique;
- /**
- * @brief Removes duplicates values from a value list.
- * @tparam Value One of the values provided by the given value list.
- * @tparam Other The other values provided by the given value list.
- */
- template<auto Value, auto... Other>
- struct value_list_unique<value_list<Value, Other...>> {
- /*! @brief A value list without duplicate types. */
- using type = std::conditional_t<
- ((Value == Other) || ...),
- typename value_list_unique<value_list<Other...>>::type,
- value_list_cat_t<value_list<Value>, typename value_list_unique<value_list<Other...>>::type>>;
- };
- /*! @brief Removes duplicates values from a value list. */
- template<>
- struct value_list_unique<value_list<>> {
- /*! @brief A value list without duplicate types. */
- using type = value_list<>;
- };
- /**
- * @brief Helper type.
- * @tparam Type A value list.
- */
- template<typename Type>
- using value_list_unique_t = typename value_list_unique<Type>::type;
- /**
- * @brief Provides the member constant `value` to true if a value list contains
- * a given value, false otherwise.
- * @tparam List Value list.
- * @tparam Value Value to look for.
- */
- template<typename List, auto Value>
- struct value_list_contains;
- /**
- * @copybrief value_list_contains
- * @tparam Value Values provided by the value list.
- * @tparam Other Value to look for.
- */
- template<auto... Value, auto Other>
- struct value_list_contains<value_list<Value...>, Other>
- : std::bool_constant<((Value == Other) || ...)> {};
- /**
- * @brief Helper variable template.
- * @tparam List Value list.
- * @tparam Value Value to look for.
- */
- template<typename List, auto Value>
- inline constexpr bool value_list_contains_v = value_list_contains<List, Value>::value;
- /*! @brief Primary template isn't defined on purpose. */
- template<typename...>
- struct value_list_diff;
- /**
- * @brief Computes the difference between two value lists.
- * @tparam Value Values provided by the first value list.
- * @tparam Other Values provided by the second value list.
- */
- template<auto... Value, auto... Other>
- struct value_list_diff<value_list<Value...>, value_list<Other...>> {
- /*! @brief A value list that is the difference between the two value lists. */
- using type = value_list_cat_t<std::conditional_t<value_list_contains_v<value_list<Other...>, Value>, value_list<>, value_list<Value>>...>;
- };
- /**
- * @brief Helper type.
- * @tparam List Value lists between which to compute the difference.
- */
- template<typename... List>
- using value_list_diff_t = typename value_list_diff<List...>::type;
- /*! @brief Same as std::is_invocable, but with tuples. */
- template<typename, typename>
- struct is_applicable: std::false_type {};
- /**
- * @copybrief is_applicable
- * @tparam Func A valid function type.
- * @tparam Tuple Tuple-like type.
- * @tparam Args The list of arguments to use to probe the function type.
- */
- template<typename Func, template<typename...> class Tuple, typename... Args>
- struct is_applicable<Func, Tuple<Args...>>: std::is_invocable<Func, Args...> {};
- /**
- * @copybrief is_applicable
- * @tparam Func A valid function type.
- * @tparam Tuple Tuple-like type.
- * @tparam Args The list of arguments to use to probe the function type.
- */
- template<typename Func, template<typename...> class Tuple, typename... Args>
- struct is_applicable<Func, const Tuple<Args...>>: std::is_invocable<Func, Args...> {};
- /**
- * @brief Helper variable template.
- * @tparam Func A valid function type.
- * @tparam Args The list of arguments to use to probe the function type.
- */
- template<typename Func, typename Args>
- inline constexpr bool is_applicable_v = is_applicable<Func, Args>::value;
- /*! @brief Same as std::is_invocable_r, but with tuples for arguments. */
- template<typename, typename, typename>
- struct is_applicable_r: std::false_type {};
- /**
- * @copybrief is_applicable_r
- * @tparam Ret The type to which the return type of the function should be
- * convertible.
- * @tparam Func A valid function type.
- * @tparam Args The list of arguments to use to probe the function type.
- */
- template<typename Ret, typename Func, typename... Args>
- struct is_applicable_r<Ret, Func, std::tuple<Args...>>: std::is_invocable_r<Ret, Func, Args...> {};
- /**
- * @brief Helper variable template.
- * @tparam Ret The type to which the return type of the function should be
- * convertible.
- * @tparam Func A valid function type.
- * @tparam Args The list of arguments to use to probe the function type.
- */
- template<typename Ret, typename Func, typename Args>
- inline constexpr bool is_applicable_r_v = is_applicable_r<Ret, Func, Args>::value;
- /**
- * @brief Provides the member constant `value` to true if a given type is
- * complete, false otherwise.
- * @tparam Type The type to test.
- */
- template<typename Type, typename = void>
- struct is_complete: std::false_type {};
- /*! @copydoc is_complete */
- template<typename Type>
- struct is_complete<Type, std::void_t<decltype(sizeof(Type))>>: std::true_type {};
- /**
- * @brief Helper variable template.
- * @tparam Type The type to test.
- */
- template<typename Type>
- inline constexpr bool is_complete_v = is_complete<Type>::value;
- /**
- * @brief Provides the member constant `value` to true if a given type is an
- * iterator, false otherwise.
- * @tparam Type The type to test.
- */
- template<typename Type, typename = void>
- struct is_iterator: std::false_type {};
- /*! @cond TURN_OFF_DOXYGEN */
- namespace internal {
- template<typename, typename = void>
- struct has_iterator_category: std::false_type {};
- template<typename Type>
- struct has_iterator_category<Type, std::void_t<typename std::iterator_traits<Type>::iterator_category>>: std::true_type {};
- } // namespace internal
- /*! @endcond */
- /*! @copydoc is_iterator */
- template<typename Type>
- struct is_iterator<Type, std::enable_if_t<!std::is_void_v<std::remove_const_t<std::remove_pointer_t<Type>>>>>
- : internal::has_iterator_category<Type> {};
- /**
- * @brief Helper variable template.
- * @tparam Type The type to test.
- */
- template<typename Type>
- inline constexpr bool is_iterator_v = is_iterator<Type>::value;
- /**
- * @brief Provides the member constant `value` to true if a given type is both
- * an empty and non-final class, false otherwise.
- * @tparam Type The type to test
- */
- template<typename Type>
- struct is_ebco_eligible
- : std::bool_constant<std::is_empty_v<Type> && !std::is_final_v<Type>> {};
- /**
- * @brief Helper variable template.
- * @tparam Type The type to test.
- */
- template<typename Type>
- inline constexpr bool is_ebco_eligible_v = is_ebco_eligible<Type>::value;
- /**
- * @brief Provides the member constant `value` to true if `Type::is_transparent`
- * is valid and denotes a type, false otherwise.
- * @tparam Type The type to test.
- */
- template<typename Type, typename = void>
- struct is_transparent: std::false_type {};
- /*! @copydoc is_transparent */
- template<typename Type>
- struct is_transparent<Type, std::void_t<typename Type::is_transparent>>: std::true_type {};
- /**
- * @brief Helper variable template.
- * @tparam Type The type to test.
- */
- template<typename Type>
- inline constexpr bool is_transparent_v = is_transparent<Type>::value;
- /*! @cond TURN_OFF_DOXYGEN */
- namespace internal {
- template<typename, typename = void>
- struct has_tuple_size_value: std::false_type {};
- template<typename Type>
- struct has_tuple_size_value<Type, std::void_t<decltype(std::tuple_size<const Type>::value)>>: std::true_type {};
- template<typename, typename = void>
- struct has_value_type: std::false_type {};
- template<typename Type>
- struct has_value_type<Type, std::void_t<typename Type::value_type>>: std::true_type {};
- template<typename>
- [[nodiscard]] constexpr bool dispatch_is_equality_comparable();
- template<typename Type, std::size_t... Index>
- [[nodiscard]] constexpr bool unpack_maybe_equality_comparable(std::index_sequence<Index...>) {
- return (dispatch_is_equality_comparable<std::tuple_element_t<Index, Type>>() && ...);
- }
- template<typename>
- [[nodiscard]] constexpr bool maybe_equality_comparable(char) {
- return false;
- }
- template<typename Type>
- [[nodiscard]] constexpr auto maybe_equality_comparable(int) -> decltype(std::declval<Type>() == std::declval<Type>()) {
- return true;
- }
- template<typename Type>
- [[nodiscard]] constexpr bool dispatch_is_equality_comparable() {
- // NOLINTBEGIN(modernize-use-transparent-functors)
- if constexpr(std::is_array_v<Type>) {
- return false;
- } else if constexpr(is_complete_v<std::tuple_size<std::remove_const_t<Type>>>) {
- if constexpr(has_tuple_size_value<Type>::value) {
- return maybe_equality_comparable<Type>(0) && unpack_maybe_equality_comparable<Type>(std::make_index_sequence<std::tuple_size<Type>::value>{});
- } else {
- return maybe_equality_comparable<Type>(0);
- }
- } else if constexpr(has_value_type<Type>::value) {
- if constexpr(is_iterator_v<Type> || std::is_same_v<typename Type::value_type, Type> || dispatch_is_equality_comparable<typename Type::value_type>()) {
- return maybe_equality_comparable<Type>(0);
- } else {
- return false;
- }
- } else {
- return maybe_equality_comparable<Type>(0);
- }
- // NOLINTEND(modernize-use-transparent-functors)
- }
- } // namespace internal
- /*! @endcond */
- /**
- * @brief Provides the member constant `value` to true if a given type is
- * equality comparable, false otherwise.
- * @tparam Type The type to test.
- */
- template<typename Type>
- struct is_equality_comparable: std::bool_constant<internal::dispatch_is_equality_comparable<Type>()> {};
- /*! @copydoc is_equality_comparable */
- template<typename Type>
- struct is_equality_comparable<const Type>: is_equality_comparable<Type> {};
- /**
- * @brief Helper variable template.
- * @tparam Type The type to test.
- */
- template<typename Type>
- inline constexpr bool is_equality_comparable_v = is_equality_comparable<Type>::value;
- /**
- * @brief Transcribes the constness of a type to another type.
- * @tparam To The type to which to transcribe the constness.
- * @tparam From The type from which to transcribe the constness.
- */
- template<typename To, typename From>
- struct constness_as {
- /*! @brief The type resulting from the transcription of the constness. */
- using type = std::remove_const_t<To>;
- };
- /*! @copydoc constness_as */
- template<typename To, typename From>
- struct constness_as<To, const From> {
- /*! @brief The type resulting from the transcription of the constness. */
- using type = const To;
- };
- /**
- * @brief Alias template to facilitate the transcription of the constness.
- * @tparam To The type to which to transcribe the constness.
- * @tparam From The type from which to transcribe the constness.
- */
- template<typename To, typename From>
- using constness_as_t = typename constness_as<To, From>::type;
- /**
- * @brief Extracts the class of a non-static member object or function.
- * @tparam Member A pointer to a non-static member object or function.
- */
- template<typename Member>
- class member_class {
- static_assert(std::is_member_pointer_v<Member>, "Invalid pointer type to non-static member object or function");
- template<typename Class, typename Ret, typename... Args>
- static Class *clazz(Ret (Class::*)(Args...));
- template<typename Class, typename Ret, typename... Args>
- static Class *clazz(Ret (Class::*)(Args...) const);
- template<typename Class, typename Type>
- static Class *clazz(Type Class::*);
- public:
- /*! @brief The class of the given non-static member object or function. */
- using type = std::remove_pointer_t<decltype(clazz(std::declval<Member>()))>;
- };
- /**
- * @brief Helper type.
- * @tparam Member A pointer to a non-static member object or function.
- */
- template<typename Member>
- using member_class_t = typename member_class<Member>::type;
- /**
- * @brief Extracts the n-th argument of a _callable_ type.
- * @tparam Index The index of the argument to extract.
- * @tparam Candidate A valid _callable_ type.
- */
- template<std::size_t Index, typename Candidate>
- class nth_argument {
- template<typename Ret, typename... Args>
- static constexpr type_list<Args...> pick_up(Ret (*)(Args...));
- template<typename Ret, typename Class, typename... Args>
- static constexpr type_list<Args...> pick_up(Ret (Class ::*)(Args...));
- template<typename Ret, typename Class, typename... Args>
- static constexpr type_list<Args...> pick_up(Ret (Class ::*)(Args...) const);
- template<typename Type, typename Class>
- static constexpr type_list<Type> pick_up(Type Class ::*);
- template<typename Type>
- static constexpr decltype(pick_up(&Type::operator())) pick_up(Type &&);
- public:
- /*! @brief N-th argument of the _callable_ type. */
- using type = type_list_element_t<Index, decltype(pick_up(std::declval<Candidate>()))>;
- };
- /**
- * @brief Helper type.
- * @tparam Index The index of the argument to extract.
- * @tparam Candidate A valid function, member function or data member type.
- */
- template<std::size_t Index, typename Candidate>
- using nth_argument_t = typename nth_argument<Index, Candidate>::type;
- } // namespace entt
- template<typename... Type>
- struct std::tuple_size<entt::type_list<Type...>>: std::integral_constant<std::size_t, entt::type_list<Type...>::size> {};
- template<std::size_t Index, typename... Type>
- struct std::tuple_element<Index, entt::type_list<Type...>>: entt::type_list_element<Index, entt::type_list<Type...>> {};
- template<auto... Value>
- struct std::tuple_size<entt::value_list<Value...>>: std::integral_constant<std::size_t, entt::value_list<Value...>::size> {};
- template<std::size_t Index, auto... Value>
- struct std::tuple_element<Index, entt::value_list<Value...>>: entt::value_list_element<Index, entt::value_list<Value...>> {};
- #endif
- namespace entt {
- /*! @cond TURN_OFF_DOXYGEN */
- namespace internal {
- template<typename Type, std::size_t, typename = void>
- struct compressed_pair_element {
- using reference = Type &;
- using const_reference = const Type &;
- template<typename Dummy = Type, typename = std::enable_if_t<std::is_default_constructible_v<Dummy>>>
- // NOLINTNEXTLINE(modernize-use-equals-default)
- constexpr compressed_pair_element() noexcept(std::is_nothrow_default_constructible_v<Type>) {}
- template<typename Arg, typename = std::enable_if_t<!std::is_same_v<std::remove_const_t<std::remove_reference_t<Arg>>, compressed_pair_element>>>
- constexpr compressed_pair_element(Arg &&arg) noexcept(std::is_nothrow_constructible_v<Type, Arg>)
- : value{std::forward<Arg>(arg)} {}
- template<typename... Args, std::size_t... Index>
- constexpr compressed_pair_element(std::tuple<Args...> args, std::index_sequence<Index...>) noexcept(std::is_nothrow_constructible_v<Type, Args...>)
- : value{std::forward<Args>(std::get<Index>(args))...} {}
- [[nodiscard]] constexpr reference get() noexcept {
- return value;
- }
- [[nodiscard]] constexpr const_reference get() const noexcept {
- return value;
- }
- private:
- Type value{};
- };
- template<typename Type, std::size_t Tag>
- struct compressed_pair_element<Type, Tag, std::enable_if_t<is_ebco_eligible_v<Type>>>: Type {
- using reference = Type &;
- using const_reference = const Type &;
- using base_type = Type;
- template<typename Dummy = Type, typename = std::enable_if_t<std::is_default_constructible_v<Dummy>>>
- constexpr compressed_pair_element() noexcept(std::is_nothrow_default_constructible_v<base_type>)
- : base_type{} {}
- template<typename Arg, typename = std::enable_if_t<!std::is_same_v<std::remove_const_t<std::remove_reference_t<Arg>>, compressed_pair_element>>>
- constexpr compressed_pair_element(Arg &&arg) noexcept(std::is_nothrow_constructible_v<base_type, Arg>)
- : base_type{std::forward<Arg>(arg)} {}
- template<typename... Args, std::size_t... Index>
- constexpr compressed_pair_element(std::tuple<Args...> args, std::index_sequence<Index...>) noexcept(std::is_nothrow_constructible_v<base_type, Args...>)
- : base_type{std::forward<Args>(std::get<Index>(args))...} {}
- [[nodiscard]] constexpr reference get() noexcept {
- return *this;
- }
- [[nodiscard]] constexpr const_reference get() const noexcept {
- return *this;
- }
- };
- } // namespace internal
- /*! @endcond */
- /**
- * @brief A compressed pair.
- *
- * A pair that exploits the _Empty Base Class Optimization_ (or _EBCO_) to
- * reduce its final size to a minimum.
- *
- * @tparam First The type of the first element that the pair stores.
- * @tparam Second The type of the second element that the pair stores.
- */
- template<typename First, typename Second>
- class compressed_pair final
- : internal::compressed_pair_element<First, 0u>,
- internal::compressed_pair_element<Second, 1u> {
- using first_base = internal::compressed_pair_element<First, 0u>;
- using second_base = internal::compressed_pair_element<Second, 1u>;
- public:
- /*! @brief The type of the first element that the pair stores. */
- using first_type = First;
- /*! @brief The type of the second element that the pair stores. */
- using second_type = Second;
- /**
- * @brief Default constructor, conditionally enabled.
- *
- * This constructor is only available when the types that the pair stores
- * are both at least default constructible.
- *
- * @tparam Dummy Dummy template parameter used for internal purposes.
- */
- template<bool Dummy = true, typename = std::enable_if_t<Dummy && std::is_default_constructible_v<first_type> && std::is_default_constructible_v<second_type>>>
- constexpr compressed_pair() noexcept(std::is_nothrow_default_constructible_v<first_base> && std::is_nothrow_default_constructible_v<second_base>)
- : first_base{},
- second_base{} {}
- /**
- * @brief Copy constructor.
- * @param other The instance to copy from.
- */
- constexpr compressed_pair(const compressed_pair &other) = default;
- /**
- * @brief Move constructor.
- * @param other The instance to move from.
- */
- constexpr compressed_pair(compressed_pair &&other) noexcept = default;
- /**
- * @brief Constructs a pair from its values.
- * @tparam Arg Type of value to use to initialize the first element.
- * @tparam Other Type of value to use to initialize the second element.
- * @param arg Value to use to initialize the first element.
- * @param other Value to use to initialize the second element.
- */
- template<typename Arg, typename Other>
- constexpr compressed_pair(Arg &&arg, Other &&other) noexcept(std::is_nothrow_constructible_v<first_base, Arg> && std::is_nothrow_constructible_v<second_base, Other>)
- : first_base{std::forward<Arg>(arg)},
- second_base{std::forward<Other>(other)} {}
- /**
- * @brief Constructs a pair by forwarding the arguments to its parts.
- * @tparam Args Types of arguments to use to initialize the first element.
- * @tparam Other Types of arguments to use to initialize the second element.
- * @param args Arguments to use to initialize the first element.
- * @param other Arguments to use to initialize the second element.
- */
- template<typename... Args, typename... Other>
- constexpr compressed_pair(std::piecewise_construct_t, std::tuple<Args...> args, std::tuple<Other...> other) noexcept(std::is_nothrow_constructible_v<first_base, Args...> && std::is_nothrow_constructible_v<second_base, Other...>)
- : first_base{std::move(args), std::index_sequence_for<Args...>{}},
- second_base{std::move(other), std::index_sequence_for<Other...>{}} {}
- /*! @brief Default destructor. */
- ~compressed_pair() = default;
- /**
- * @brief Copy assignment operator.
- * @param other The instance to copy from.
- * @return This compressed pair object.
- */
- constexpr compressed_pair &operator=(const compressed_pair &other) = default;
- /**
- * @brief Move assignment operator.
- * @param other The instance to move from.
- * @return This compressed pair object.
- */
- constexpr compressed_pair &operator=(compressed_pair &&other) noexcept = default;
- /**
- * @brief Returns the first element that a pair stores.
- * @return The first element that a pair stores.
- */
- [[nodiscard]] constexpr first_type &first() noexcept {
- return static_cast<first_base &>(*this).get();
- }
- /*! @copydoc first */
- [[nodiscard]] constexpr const first_type &first() const noexcept {
- return static_cast<const first_base &>(*this).get();
- }
- /**
- * @brief Returns the second element that a pair stores.
- * @return The second element that a pair stores.
- */
- [[nodiscard]] constexpr second_type &second() noexcept {
- return static_cast<second_base &>(*this).get();
- }
- /*! @copydoc second */
- [[nodiscard]] constexpr const second_type &second() const noexcept {
- return static_cast<const second_base &>(*this).get();
- }
- /**
- * @brief Swaps two compressed pair objects.
- * @param other The compressed pair to swap with.
- */
- constexpr void swap(compressed_pair &other) noexcept {
- using std::swap;
- swap(first(), other.first());
- swap(second(), other.second());
- }
- /**
- * @brief Extracts an element from the compressed pair.
- * @tparam Index An integer value that is either 0 or 1.
- * @return Returns a reference to the first element if `Index` is 0 and a
- * reference to the second element if `Index` is 1.
- */
- template<std::size_t Index>
- [[nodiscard]] constexpr decltype(auto) get() noexcept {
- if constexpr(Index == 0u) {
- return first();
- } else {
- static_assert(Index == 1u, "Index out of bounds");
- return second();
- }
- }
- /*! @copydoc get */
- template<std::size_t Index>
- [[nodiscard]] constexpr decltype(auto) get() const noexcept {
- if constexpr(Index == 0u) {
- return first();
- } else {
- static_assert(Index == 1u, "Index out of bounds");
- return second();
- }
- }
- };
- /**
- * @brief Deduction guide.
- * @tparam Type Type of value to use to initialize the first element.
- * @tparam Other Type of value to use to initialize the second element.
- */
- template<typename Type, typename Other>
- compressed_pair(Type &&, Other &&) -> compressed_pair<std::decay_t<Type>, std::decay_t<Other>>;
- /**
- * @brief Swaps two compressed pair objects.
- * @tparam First The type of the first element that the pairs store.
- * @tparam Second The type of the second element that the pairs store.
- * @param lhs A valid compressed pair object.
- * @param rhs A valid compressed pair object.
- */
- template<typename First, typename Second>
- constexpr void swap(compressed_pair<First, Second> &lhs, compressed_pair<First, Second> &rhs) noexcept {
- lhs.swap(rhs);
- }
- } // namespace entt
- namespace std {
- /**
- * @brief `std::tuple_size` specialization for `compressed_pair`s.
- * @tparam First The type of the first element that the pair stores.
- * @tparam Second The type of the second element that the pair stores.
- */
- template<typename First, typename Second>
- struct tuple_size<entt::compressed_pair<First, Second>>: integral_constant<size_t, 2u> {};
- /**
- * @brief `std::tuple_element` specialization for `compressed_pair`s.
- * @tparam Index The index of the type to return.
- * @tparam First The type of the first element that the pair stores.
- * @tparam Second The type of the second element that the pair stores.
- */
- template<size_t Index, typename First, typename Second>
- struct tuple_element<Index, entt::compressed_pair<First, Second>>: conditional<Index == 0u, First, Second> {
- static_assert(Index < 2u, "Index out of bounds");
- };
- } // namespace std
- #endif
- // #include "../core/iterator.hpp"
- #ifndef ENTT_CORE_ITERATOR_HPP
- #define ENTT_CORE_ITERATOR_HPP
- #include <iterator>
- #include <memory>
- #include <type_traits>
- #include <utility>
- namespace entt {
- /**
- * @brief Helper type to use as pointer with input iterators.
- * @tparam Type of wrapped value.
- */
- template<typename Type>
- struct input_iterator_pointer final {
- /*! @brief Value type. */
- using value_type = Type;
- /*! @brief Pointer type. */
- using pointer = Type *;
- /*! @brief Reference type. */
- using reference = Type &;
- /**
- * @brief Constructs a proxy object by move.
- * @param val Value to use to initialize the proxy object.
- */
- constexpr input_iterator_pointer(value_type &&val) noexcept(std::is_nothrow_move_constructible_v<value_type>)
- : value{std::move(val)} {}
- /**
- * @brief Access operator for accessing wrapped values.
- * @return A pointer to the wrapped value.
- */
- [[nodiscard]] constexpr pointer operator->() noexcept {
- return std::addressof(value);
- }
- /**
- * @brief Dereference operator for accessing wrapped values.
- * @return A reference to the wrapped value.
- */
- [[nodiscard]] constexpr reference operator*() noexcept {
- return value;
- }
- private:
- Type value;
- };
- /**
- * @brief Plain iota iterator (waiting for C++20).
- * @tparam Type Value type.
- */
- template<typename Type>
- class iota_iterator final {
- static_assert(std::is_integral_v<Type>, "Not an integral type");
- public:
- /*! @brief Value type, likely an integral one. */
- using value_type = Type;
- /*! @brief Invalid pointer type. */
- using pointer = void;
- /*! @brief Non-reference type, same as value type. */
- using reference = value_type;
- /*! @brief Difference type. */
- using difference_type = std::ptrdiff_t;
- /*! @brief Iterator category. */
- using iterator_category = std::input_iterator_tag;
- /*! @brief Default constructor. */
- constexpr iota_iterator() noexcept
- : current{} {}
- /**
- * @brief Constructs an iota iterator from a given value.
- * @param init The initial value assigned to the iota iterator.
- */
- constexpr iota_iterator(const value_type init) noexcept
- : current{init} {}
- /**
- * @brief Pre-increment operator.
- * @return This iota iterator.
- */
- constexpr iota_iterator &operator++() noexcept {
- return ++current, *this;
- }
- /**
- * @brief Post-increment operator.
- * @return This iota iterator.
- */
- constexpr iota_iterator operator++(int) noexcept {
- const iota_iterator orig = *this;
- return ++(*this), orig;
- }
- /**
- * @brief Dereference operator.
- * @return The underlying value.
- */
- [[nodiscard]] constexpr reference operator*() const noexcept {
- return current;
- }
- private:
- value_type current;
- };
- /**
- * @brief Comparison operator.
- * @tparam Type Value type of the iota iterator.
- * @param lhs A properly initialized iota iterator.
- * @param rhs A properly initialized iota iterator.
- * @return True if the two iterators are identical, false otherwise.
- */
- template<typename Type>
- [[nodiscard]] constexpr bool operator==(const iota_iterator<Type> &lhs, const iota_iterator<Type> &rhs) noexcept {
- return *lhs == *rhs;
- }
- /**
- * @brief Comparison operator.
- * @tparam Type Value type of the iota iterator.
- * @param lhs A properly initialized iota iterator.
- * @param rhs A properly initialized iota iterator.
- * @return True if the two iterators differ, false otherwise.
- */
- template<typename Type>
- [[nodiscard]] constexpr bool operator!=(const iota_iterator<Type> &lhs, const iota_iterator<Type> &rhs) noexcept {
- return !(lhs == rhs);
- }
- /**
- * @brief Utility class to create an iterable object from a pair of iterators.
- * @tparam It Type of iterator.
- * @tparam Sentinel Type of sentinel.
- */
- template<typename It, typename Sentinel = It>
- struct iterable_adaptor final {
- /*! @brief Value type. */
- using value_type = typename std::iterator_traits<It>::value_type;
- /*! @brief Iterator type. */
- using iterator = It;
- /*! @brief Sentinel type. */
- using sentinel = Sentinel;
- /*! @brief Default constructor. */
- constexpr iterable_adaptor() noexcept(std::is_nothrow_default_constructible_v<iterator> && std::is_nothrow_default_constructible_v<sentinel>)
- : first{},
- last{} {}
- /**
- * @brief Creates an iterable object from a pair of iterators.
- * @param from Begin iterator.
- * @param to End iterator.
- */
- constexpr iterable_adaptor(iterator from, sentinel to) noexcept(std::is_nothrow_move_constructible_v<iterator> && std::is_nothrow_move_constructible_v<sentinel>)
- : first{std::move(from)},
- last{std::move(to)} {}
- /**
- * @brief Returns an iterator to the beginning.
- * @return An iterator to the first element of the range.
- */
- [[nodiscard]] constexpr iterator begin() const noexcept {
- return first;
- }
- /**
- * @brief Returns an iterator to the end.
- * @return An iterator to the element following the last element of the
- * range.
- */
- [[nodiscard]] constexpr sentinel end() const noexcept {
- return last;
- }
- /*! @copydoc begin */
- [[nodiscard]] constexpr iterator cbegin() const noexcept {
- return begin();
- }
- /*! @copydoc end */
- [[nodiscard]] constexpr sentinel cend() const noexcept {
- return end();
- }
- private:
- It first;
- Sentinel last;
- };
- } // namespace entt
- #endif
- // #include "../core/memory.hpp"
- #ifndef ENTT_CORE_MEMORY_HPP
- #define ENTT_CORE_MEMORY_HPP
- #include <cstddef>
- #include <memory>
- #include <tuple>
- #include <type_traits>
- #include <utility>
- // #include "../config/config.h"
- namespace entt {
- /**
- * @brief Unwraps fancy pointers, does nothing otherwise (waiting for C++20).
- * @tparam Type Pointer type.
- * @param ptr Fancy or raw pointer.
- * @return A raw pointer that represents the address of the original pointer.
- */
- template<typename Type>
- [[nodiscard]] constexpr auto to_address(Type &&ptr) noexcept {
- if constexpr(std::is_pointer_v<std::decay_t<Type>>) {
- return ptr;
- } else {
- return to_address(std::forward<Type>(ptr).operator->());
- }
- }
- /**
- * @brief Utility function to design allocation-aware containers.
- * @tparam Allocator Type of allocator.
- * @param lhs A valid allocator.
- * @param rhs Another valid allocator.
- */
- template<typename Allocator>
- constexpr void propagate_on_container_copy_assignment([[maybe_unused]] Allocator &lhs, [[maybe_unused]] Allocator &rhs) noexcept {
- if constexpr(std::allocator_traits<Allocator>::propagate_on_container_copy_assignment::value) {
- lhs = rhs;
- }
- }
- /**
- * @brief Utility function to design allocation-aware containers.
- * @tparam Allocator Type of allocator.
- * @param lhs A valid allocator.
- * @param rhs Another valid allocator.
- */
- template<typename Allocator>
- constexpr void propagate_on_container_move_assignment([[maybe_unused]] Allocator &lhs, [[maybe_unused]] Allocator &rhs) noexcept {
- if constexpr(std::allocator_traits<Allocator>::propagate_on_container_move_assignment::value) {
- lhs = std::move(rhs);
- }
- }
- /**
- * @brief Utility function to design allocation-aware containers.
- * @tparam Allocator Type of allocator.
- * @param lhs A valid allocator.
- * @param rhs Another valid allocator.
- */
- template<typename Allocator>
- constexpr void propagate_on_container_swap([[maybe_unused]] Allocator &lhs, [[maybe_unused]] Allocator &rhs) noexcept {
- if constexpr(std::allocator_traits<Allocator>::propagate_on_container_swap::value) {
- using std::swap;
- swap(lhs, rhs);
- } else {
- ENTT_ASSERT_CONSTEXPR(lhs == rhs, "Cannot swap the containers");
- }
- }
- /**
- * @brief Deleter for allocator-aware unique pointers (waiting for C++20).
- * @tparam Allocator Type of allocator used to manage memory and elements.
- */
- template<typename Allocator>
- struct allocation_deleter: private Allocator {
- /*! @brief Allocator type. */
- using allocator_type = Allocator;
- /*! @brief Pointer type. */
- using pointer = typename std::allocator_traits<Allocator>::pointer;
- /**
- * @brief Inherited constructors.
- * @param alloc The allocator to use.
- */
- constexpr allocation_deleter(const allocator_type &alloc) noexcept(std::is_nothrow_copy_constructible_v<allocator_type>)
- : Allocator{alloc} {}
- /**
- * @brief Destroys the pointed object and deallocates its memory.
- * @param ptr A valid pointer to an object of the given type.
- */
- constexpr void operator()(pointer ptr) noexcept(std::is_nothrow_destructible_v<typename allocator_type::value_type>) {
- using alloc_traits = std::allocator_traits<Allocator>;
- alloc_traits::destroy(*this, to_address(ptr));
- alloc_traits::deallocate(*this, ptr, 1u);
- }
- };
- /**
- * @brief Allows `std::unique_ptr` to use allocators (waiting for C++20).
- * @tparam Type Type of object to allocate for and to construct.
- * @tparam Allocator Type of allocator used to manage memory and elements.
- * @tparam Args Types of arguments to use to construct the object.
- * @param allocator The allocator to use.
- * @param args Parameters to use to construct the object.
- * @return A properly initialized unique pointer with a custom deleter.
- */
- template<typename Type, typename Allocator, typename... Args>
- ENTT_CONSTEXPR auto allocate_unique(Allocator &allocator, Args &&...args) {
- static_assert(!std::is_array_v<Type>, "Array types are not supported");
- using alloc_traits = typename std::allocator_traits<Allocator>::template rebind_traits<Type>;
- using allocator_type = typename alloc_traits::allocator_type;
- allocator_type alloc{allocator};
- auto ptr = alloc_traits::allocate(alloc, 1u);
- ENTT_TRY {
- alloc_traits::construct(alloc, to_address(ptr), std::forward<Args>(args)...);
- }
- ENTT_CATCH {
- alloc_traits::deallocate(alloc, ptr, 1u);
- ENTT_THROW;
- }
- return std::unique_ptr<Type, allocation_deleter<allocator_type>>{ptr, alloc};
- }
- /*! @cond TURN_OFF_DOXYGEN */
- namespace internal {
- template<typename Type>
- struct uses_allocator_construction {
- template<typename Allocator, typename... Params>
- static constexpr auto args([[maybe_unused]] const Allocator &allocator, Params &&...params) noexcept {
- if constexpr(!std::uses_allocator_v<Type, Allocator> && std::is_constructible_v<Type, Params...>) {
- return std::forward_as_tuple(std::forward<Params>(params)...);
- } else {
- static_assert(std::uses_allocator_v<Type, Allocator>, "Ill-formed request");
- if constexpr(std::is_constructible_v<Type, std::allocator_arg_t, const Allocator &, Params...>) {
- return std::tuple<std::allocator_arg_t, const Allocator &, Params &&...>{std::allocator_arg, allocator, std::forward<Params>(params)...};
- } else {
- static_assert(std::is_constructible_v<Type, Params..., const Allocator &>, "Ill-formed request");
- return std::forward_as_tuple(std::forward<Params>(params)..., allocator);
- }
- }
- }
- };
- template<typename Type, typename Other>
- struct uses_allocator_construction<std::pair<Type, Other>> {
- using type = std::pair<Type, Other>;
- template<typename Allocator, typename First, typename Second>
- static constexpr auto args(const Allocator &allocator, std::piecewise_construct_t, First &&first, Second &&second) noexcept {
- return std::make_tuple(
- std::piecewise_construct,
- std::apply([&allocator](auto &&...curr) { return uses_allocator_construction<Type>::args(allocator, std::forward<decltype(curr)>(curr)...); }, std::forward<First>(first)),
- std::apply([&allocator](auto &&...curr) { return uses_allocator_construction<Other>::args(allocator, std::forward<decltype(curr)>(curr)...); }, std::forward<Second>(second)));
- }
- template<typename Allocator>
- static constexpr auto args(const Allocator &allocator) noexcept {
- return uses_allocator_construction<type>::args(allocator, std::piecewise_construct, std::tuple<>{}, std::tuple<>{});
- }
- template<typename Allocator, typename First, typename Second>
- static constexpr auto args(const Allocator &allocator, First &&first, Second &&second) noexcept {
- return uses_allocator_construction<type>::args(allocator, std::piecewise_construct, std::forward_as_tuple(std::forward<First>(first)), std::forward_as_tuple(std::forward<Second>(second)));
- }
- template<typename Allocator, typename First, typename Second>
- static constexpr auto args(const Allocator &allocator, const std::pair<First, Second> &value) noexcept {
- return uses_allocator_construction<type>::args(allocator, std::piecewise_construct, std::forward_as_tuple(value.first), std::forward_as_tuple(value.second));
- }
- template<typename Allocator, typename First, typename Second>
- static constexpr auto args(const Allocator &allocator, std::pair<First, Second> &&value) noexcept {
- return uses_allocator_construction<type>::args(allocator, std::piecewise_construct, std::forward_as_tuple(std::move(value.first)), std::forward_as_tuple(std::move(value.second)));
- }
- };
- } // namespace internal
- /*! @endcond */
- /**
- * @brief Uses-allocator construction utility (waiting for C++20).
- *
- * Primarily intended for internal use. Prepares the argument list needed to
- * create an object of a given type by means of uses-allocator construction.
- *
- * @tparam Type Type to return arguments for.
- * @tparam Allocator Type of allocator used to manage memory and elements.
- * @tparam Args Types of arguments to use to construct the object.
- * @param allocator The allocator to use.
- * @param args Parameters to use to construct the object.
- * @return The arguments needed to create an object of the given type.
- */
- template<typename Type, typename Allocator, typename... Args>
- constexpr auto uses_allocator_construction_args(const Allocator &allocator, Args &&...args) noexcept {
- return internal::uses_allocator_construction<Type>::args(allocator, std::forward<Args>(args)...);
- }
- /**
- * @brief Uses-allocator construction utility (waiting for C++20).
- *
- * Primarily intended for internal use. Creates an object of a given type by
- * means of uses-allocator construction.
- *
- * @tparam Type Type of object to create.
- * @tparam Allocator Type of allocator used to manage memory and elements.
- * @tparam Args Types of arguments to use to construct the object.
- * @param allocator The allocator to use.
- * @param args Parameters to use to construct the object.
- * @return A newly created object of the given type.
- */
- template<typename Type, typename Allocator, typename... Args>
- constexpr Type make_obj_using_allocator(const Allocator &allocator, Args &&...args) {
- return std::make_from_tuple<Type>(internal::uses_allocator_construction<Type>::args(allocator, std::forward<Args>(args)...));
- }
- /**
- * @brief Uses-allocator construction utility (waiting for C++20).
- *
- * Primarily intended for internal use. Creates an object of a given type by
- * means of uses-allocator construction at an uninitialized memory location.
- *
- * @tparam Type Type of object to create.
- * @tparam Allocator Type of allocator used to manage memory and elements.
- * @tparam Args Types of arguments to use to construct the object.
- * @param value Memory location in which to place the object.
- * @param allocator The allocator to use.
- * @param args Parameters to use to construct the object.
- * @return A pointer to the newly created object of the given type.
- */
- template<typename Type, typename Allocator, typename... Args>
- constexpr Type *uninitialized_construct_using_allocator(Type *value, const Allocator &allocator, Args &&...args) {
- return std::apply([value](auto &&...curr) { return ::new(value) Type(std::forward<decltype(curr)>(curr)...); }, internal::uses_allocator_construction<Type>::args(allocator, std::forward<Args>(args)...));
- }
- } // namespace entt
- #endif
- // #include "../core/type_traits.hpp"
- #ifndef ENTT_CORE_TYPE_TRAITS_HPP
- #define ENTT_CORE_TYPE_TRAITS_HPP
- #include <cstddef>
- #include <iterator>
- #include <tuple>
- #include <type_traits>
- #include <utility>
- // #include "../config/config.h"
- // #include "fwd.hpp"
- namespace entt {
- /**
- * @brief Utility class to disambiguate overloaded functions.
- * @tparam N Number of choices available.
- */
- template<std::size_t N>
- struct choice_t
- // unfortunately, doxygen cannot parse such a construct
- : /*! @cond TURN_OFF_DOXYGEN */ choice_t<N - 1> /*! @endcond */
- {};
- /*! @copybrief choice_t */
- template<>
- struct choice_t<0> {};
- /**
- * @brief Variable template for the choice trick.
- * @tparam N Number of choices available.
- */
- template<std::size_t N>
- inline constexpr choice_t<N> choice{};
- /**
- * @brief Identity type trait.
- *
- * Useful to establish non-deduced contexts in template argument deduction
- * (waiting for C++20) or to provide types through function arguments.
- *
- * @tparam Type A type.
- */
- template<typename Type>
- struct type_identity {
- /*! @brief Identity type. */
- using type = Type;
- };
- /**
- * @brief Helper type.
- * @tparam Type A type.
- */
- template<typename Type>
- using type_identity_t = typename type_identity<Type>::type;
- /**
- * @brief A type-only `sizeof` wrapper that returns 0 where `sizeof` complains.
- * @tparam Type The type of which to return the size.
- */
- template<typename Type, typename = void>
- struct size_of: std::integral_constant<std::size_t, 0u> {};
- /*! @copydoc size_of */
- template<typename Type>
- struct size_of<Type, std::void_t<decltype(sizeof(Type))>>
- // NOLINTNEXTLINE(bugprone-sizeof-expression)
- : std::integral_constant<std::size_t, sizeof(Type)> {};
- /**
- * @brief Helper variable template.
- * @tparam Type The type of which to return the size.
- */
- template<typename Type>
- inline constexpr std::size_t size_of_v = size_of<Type>::value;
- /**
- * @brief Using declaration to be used to _repeat_ the same type a number of
- * times equal to the size of a given parameter pack.
- * @tparam Type A type to repeat.
- */
- template<typename Type, typename>
- using unpack_as_type = Type;
- /**
- * @brief Helper variable template to be used to _repeat_ the same value a
- * number of times equal to the size of a given parameter pack.
- * @tparam Value A value to repeat.
- */
- template<auto Value, typename>
- inline constexpr auto unpack_as_value = Value;
- /**
- * @brief Wraps a static constant.
- * @tparam Value A static constant.
- */
- template<auto Value>
- using integral_constant = std::integral_constant<decltype(Value), Value>;
- /**
- * @brief Alias template to facilitate the creation of named values.
- * @tparam Value A constant value at least convertible to `id_type`.
- */
- template<id_type Value>
- using tag = integral_constant<Value>;
- /**
- * @brief A class to use to push around lists of types, nothing more.
- * @tparam Type Types provided by the type list.
- */
- template<typename... Type>
- struct type_list {
- /*! @brief Type list type. */
- using type = type_list;
- /*! @brief Compile-time number of elements in the type list. */
- static constexpr auto size = sizeof...(Type);
- };
- /*! @brief Primary template isn't defined on purpose. */
- template<std::size_t, typename>
- struct type_list_element;
- /**
- * @brief Provides compile-time indexed access to the types of a type list.
- * @tparam Index Index of the type to return.
- * @tparam First First type provided by the type list.
- * @tparam Other Other types provided by the type list.
- */
- template<std::size_t Index, typename First, typename... Other>
- struct type_list_element<Index, type_list<First, Other...>>
- : type_list_element<Index - 1u, type_list<Other...>> {};
- /**
- * @brief Provides compile-time indexed access to the types of a type list.
- * @tparam First First type provided by the type list.
- * @tparam Other Other types provided by the type list.
- */
- template<typename First, typename... Other>
- struct type_list_element<0u, type_list<First, Other...>> {
- /*! @brief Searched type. */
- using type = First;
- };
- /**
- * @brief Helper type.
- * @tparam Index Index of the type to return.
- * @tparam List Type list to search into.
- */
- template<std::size_t Index, typename List>
- using type_list_element_t = typename type_list_element<Index, List>::type;
- /*! @brief Primary template isn't defined on purpose. */
- template<typename, typename>
- struct type_list_index;
- /**
- * @brief Provides compile-time type access to the types of a type list.
- * @tparam Type Type to look for and for which to return the index.
- * @tparam First First type provided by the type list.
- * @tparam Other Other types provided by the type list.
- */
- template<typename Type, typename First, typename... Other>
- struct type_list_index<Type, type_list<First, Other...>> {
- /*! @brief Unsigned integer type. */
- using value_type = std::size_t;
- /*! @brief Compile-time position of the given type in the sublist. */
- static constexpr value_type value = 1u + type_list_index<Type, type_list<Other...>>::value;
- };
- /**
- * @brief Provides compile-time type access to the types of a type list.
- * @tparam Type Type to look for and for which to return the index.
- * @tparam Other Other types provided by the type list.
- */
- template<typename Type, typename... Other>
- struct type_list_index<Type, type_list<Type, Other...>> {
- static_assert(type_list_index<Type, type_list<Other...>>::value == sizeof...(Other), "Non-unique type");
- /*! @brief Unsigned integer type. */
- using value_type = std::size_t;
- /*! @brief Compile-time position of the given type in the sublist. */
- static constexpr value_type value = 0u;
- };
- /**
- * @brief Provides compile-time type access to the types of a type list.
- * @tparam Type Type to look for and for which to return the index.
- */
- template<typename Type>
- struct type_list_index<Type, type_list<>> {
- /*! @brief Unsigned integer type. */
- using value_type = std::size_t;
- /*! @brief Compile-time position of the given type in the sublist. */
- static constexpr value_type value = 0u;
- };
- /**
- * @brief Helper variable template.
- * @tparam List Type list.
- * @tparam Type Type to look for and for which to return the index.
- */
- template<typename Type, typename List>
- inline constexpr std::size_t type_list_index_v = type_list_index<Type, List>::value;
- /**
- * @brief Concatenates multiple type lists.
- * @tparam Type Types provided by the first type list.
- * @tparam Other Types provided by the second type list.
- * @return A type list composed by the types of both the type lists.
- */
- template<typename... Type, typename... Other>
- constexpr type_list<Type..., Other...> operator+(type_list<Type...>, type_list<Other...>) {
- return {};
- }
- /*! @brief Primary template isn't defined on purpose. */
- template<typename...>
- struct type_list_cat;
- /*! @brief Concatenates multiple type lists. */
- template<>
- struct type_list_cat<> {
- /*! @brief A type list composed by the types of all the type lists. */
- using type = type_list<>;
- };
- /**
- * @brief Concatenates multiple type lists.
- * @tparam Type Types provided by the first type list.
- * @tparam Other Types provided by the second type list.
- * @tparam List Other type lists, if any.
- */
- template<typename... Type, typename... Other, typename... List>
- struct type_list_cat<type_list<Type...>, type_list<Other...>, List...> {
- /*! @brief A type list composed by the types of all the type lists. */
- using type = typename type_list_cat<type_list<Type..., Other...>, List...>::type;
- };
- /**
- * @brief Concatenates multiple type lists.
- * @tparam Type Types provided by the type list.
- */
- template<typename... Type>
- struct type_list_cat<type_list<Type...>> {
- /*! @brief A type list composed by the types of all the type lists. */
- using type = type_list<Type...>;
- };
- /**
- * @brief Helper type.
- * @tparam List Type lists to concatenate.
- */
- template<typename... List>
- using type_list_cat_t = typename type_list_cat<List...>::type;
- /*! @cond TURN_OFF_DOXYGEN */
- namespace internal {
- template<typename...>
- struct type_list_unique;
- template<typename First, typename... Other, typename... Type>
- struct type_list_unique<type_list<First, Other...>, Type...>
- : std::conditional_t<(std::is_same_v<First, Type> || ...), type_list_unique<type_list<Other...>, Type...>, type_list_unique<type_list<Other...>, Type..., First>> {};
- template<typename... Type>
- struct type_list_unique<type_list<>, Type...> {
- using type = type_list<Type...>;
- };
- } // namespace internal
- /*! @endcond */
- /**
- * @brief Removes duplicates types from a type list.
- * @tparam List Type list.
- */
- template<typename List>
- struct type_list_unique {
- /*! @brief A type list without duplicate types. */
- using type = typename internal::type_list_unique<List>::type;
- };
- /**
- * @brief Helper type.
- * @tparam List Type list.
- */
- template<typename List>
- using type_list_unique_t = typename type_list_unique<List>::type;
- /**
- * @brief Provides the member constant `value` to true if a type list contains a
- * given type, false otherwise.
- * @tparam List Type list.
- * @tparam Type Type to look for.
- */
- template<typename List, typename Type>
- struct type_list_contains;
- /**
- * @copybrief type_list_contains
- * @tparam Type Types provided by the type list.
- * @tparam Other Type to look for.
- */
- template<typename... Type, typename Other>
- struct type_list_contains<type_list<Type...>, Other>
- : std::bool_constant<(std::is_same_v<Type, Other> || ...)> {};
- /**
- * @brief Helper variable template.
- * @tparam List Type list.
- * @tparam Type Type to look for.
- */
- template<typename List, typename Type>
- inline constexpr bool type_list_contains_v = type_list_contains<List, Type>::value;
- /*! @brief Primary template isn't defined on purpose. */
- template<typename...>
- struct type_list_diff;
- /**
- * @brief Computes the difference between two type lists.
- * @tparam Type Types provided by the first type list.
- * @tparam Other Types provided by the second type list.
- */
- template<typename... Type, typename... Other>
- struct type_list_diff<type_list<Type...>, type_list<Other...>> {
- /*! @brief A type list that is the difference between the two type lists. */
- using type = type_list_cat_t<std::conditional_t<type_list_contains_v<type_list<Other...>, Type>, type_list<>, type_list<Type>>...>;
- };
- /**
- * @brief Helper type.
- * @tparam List Type lists between which to compute the difference.
- */
- template<typename... List>
- using type_list_diff_t = typename type_list_diff<List...>::type;
- /*! @brief Primary template isn't defined on purpose. */
- template<typename, template<typename...> class>
- struct type_list_transform;
- /**
- * @brief Applies a given _function_ to a type list and generate a new list.
- * @tparam Type Types provided by the type list.
- * @tparam Op Unary operation as template class with a type member named `type`.
- */
- template<typename... Type, template<typename...> class Op>
- struct type_list_transform<type_list<Type...>, Op> {
- /*! @brief Resulting type list after applying the transform function. */
- // NOLINTNEXTLINE(modernize-type-traits)
- using type = type_list<typename Op<Type>::type...>;
- };
- /**
- * @brief Helper type.
- * @tparam List Type list.
- * @tparam Op Unary operation as template class with a type member named `type`.
- */
- template<typename List, template<typename...> class Op>
- using type_list_transform_t = typename type_list_transform<List, Op>::type;
- /**
- * @brief A class to use to push around lists of constant values, nothing more.
- * @tparam Value Values provided by the value list.
- */
- template<auto... Value>
- struct value_list {
- /*! @brief Value list type. */
- using type = value_list;
- /*! @brief Compile-time number of elements in the value list. */
- static constexpr auto size = sizeof...(Value);
- };
- /*! @brief Primary template isn't defined on purpose. */
- template<std::size_t, typename>
- struct value_list_element;
- /**
- * @brief Provides compile-time indexed access to the values of a value list.
- * @tparam Index Index of the value to return.
- * @tparam Value First value provided by the value list.
- * @tparam Other Other values provided by the value list.
- */
- template<std::size_t Index, auto Value, auto... Other>
- struct value_list_element<Index, value_list<Value, Other...>>
- : value_list_element<Index - 1u, value_list<Other...>> {};
- /**
- * @brief Provides compile-time indexed access to the types of a type list.
- * @tparam Value First value provided by the value list.
- * @tparam Other Other values provided by the value list.
- */
- template<auto Value, auto... Other>
- struct value_list_element<0u, value_list<Value, Other...>> {
- /*! @brief Searched type. */
- using type = decltype(Value);
- /*! @brief Searched value. */
- static constexpr auto value = Value;
- };
- /**
- * @brief Helper type.
- * @tparam Index Index of the type to return.
- * @tparam List Value list to search into.
- */
- template<std::size_t Index, typename List>
- using value_list_element_t = typename value_list_element<Index, List>::type;
- /**
- * @brief Helper type.
- * @tparam Index Index of the value to return.
- * @tparam List Value list to search into.
- */
- template<std::size_t Index, typename List>
- inline constexpr auto value_list_element_v = value_list_element<Index, List>::value;
- /*! @brief Primary template isn't defined on purpose. */
- template<auto, typename>
- struct value_list_index;
- /**
- * @brief Provides compile-time type access to the values of a value list.
- * @tparam Value Value to look for and for which to return the index.
- * @tparam First First value provided by the value list.
- * @tparam Other Other values provided by the value list.
- */
- template<auto Value, auto First, auto... Other>
- struct value_list_index<Value, value_list<First, Other...>> {
- /*! @brief Unsigned integer type. */
- using value_type = std::size_t;
- /*! @brief Compile-time position of the given value in the sublist. */
- static constexpr value_type value = 1u + value_list_index<Value, value_list<Other...>>::value;
- };
- /**
- * @brief Provides compile-time type access to the values of a value list.
- * @tparam Value Value to look for and for which to return the index.
- * @tparam Other Other values provided by the value list.
- */
- template<auto Value, auto... Other>
- struct value_list_index<Value, value_list<Value, Other...>> {
- static_assert(value_list_index<Value, value_list<Other...>>::value == sizeof...(Other), "Non-unique type");
- /*! @brief Unsigned integer type. */
- using value_type = std::size_t;
- /*! @brief Compile-time position of the given value in the sublist. */
- static constexpr value_type value = 0u;
- };
- /**
- * @brief Provides compile-time type access to the values of a value list.
- * @tparam Value Value to look for and for which to return the index.
- */
- template<auto Value>
- struct value_list_index<Value, value_list<>> {
- /*! @brief Unsigned integer type. */
- using value_type = std::size_t;
- /*! @brief Compile-time position of the given type in the sublist. */
- static constexpr value_type value = 0u;
- };
- /**
- * @brief Helper variable template.
- * @tparam List Value list.
- * @tparam Value Value to look for and for which to return the index.
- */
- template<auto Value, typename List>
- inline constexpr std::size_t value_list_index_v = value_list_index<Value, List>::value;
- /**
- * @brief Concatenates multiple value lists.
- * @tparam Value Values provided by the first value list.
- * @tparam Other Values provided by the second value list.
- * @return A value list composed by the values of both the value lists.
- */
- template<auto... Value, auto... Other>
- constexpr value_list<Value..., Other...> operator+(value_list<Value...>, value_list<Other...>) {
- return {};
- }
- /*! @brief Primary template isn't defined on purpose. */
- template<typename...>
- struct value_list_cat;
- /*! @brief Concatenates multiple value lists. */
- template<>
- struct value_list_cat<> {
- /*! @brief A value list composed by the values of all the value lists. */
- using type = value_list<>;
- };
- /**
- * @brief Concatenates multiple value lists.
- * @tparam Value Values provided by the first value list.
- * @tparam Other Values provided by the second value list.
- * @tparam List Other value lists, if any.
- */
- template<auto... Value, auto... Other, typename... List>
- struct value_list_cat<value_list<Value...>, value_list<Other...>, List...> {
- /*! @brief A value list composed by the values of all the value lists. */
- using type = typename value_list_cat<value_list<Value..., Other...>, List...>::type;
- };
- /**
- * @brief Concatenates multiple value lists.
- * @tparam Value Values provided by the value list.
- */
- template<auto... Value>
- struct value_list_cat<value_list<Value...>> {
- /*! @brief A value list composed by the values of all the value lists. */
- using type = value_list<Value...>;
- };
- /**
- * @brief Helper type.
- * @tparam List Value lists to concatenate.
- */
- template<typename... List>
- using value_list_cat_t = typename value_list_cat<List...>::type;
- /*! @brief Primary template isn't defined on purpose. */
- template<typename>
- struct value_list_unique;
- /**
- * @brief Removes duplicates values from a value list.
- * @tparam Value One of the values provided by the given value list.
- * @tparam Other The other values provided by the given value list.
- */
- template<auto Value, auto... Other>
- struct value_list_unique<value_list<Value, Other...>> {
- /*! @brief A value list without duplicate types. */
- using type = std::conditional_t<
- ((Value == Other) || ...),
- typename value_list_unique<value_list<Other...>>::type,
- value_list_cat_t<value_list<Value>, typename value_list_unique<value_list<Other...>>::type>>;
- };
- /*! @brief Removes duplicates values from a value list. */
- template<>
- struct value_list_unique<value_list<>> {
- /*! @brief A value list without duplicate types. */
- using type = value_list<>;
- };
- /**
- * @brief Helper type.
- * @tparam Type A value list.
- */
- template<typename Type>
- using value_list_unique_t = typename value_list_unique<Type>::type;
- /**
- * @brief Provides the member constant `value` to true if a value list contains
- * a given value, false otherwise.
- * @tparam List Value list.
- * @tparam Value Value to look for.
- */
- template<typename List, auto Value>
- struct value_list_contains;
- /**
- * @copybrief value_list_contains
- * @tparam Value Values provided by the value list.
- * @tparam Other Value to look for.
- */
- template<auto... Value, auto Other>
- struct value_list_contains<value_list<Value...>, Other>
- : std::bool_constant<((Value == Other) || ...)> {};
- /**
- * @brief Helper variable template.
- * @tparam List Value list.
- * @tparam Value Value to look for.
- */
- template<typename List, auto Value>
- inline constexpr bool value_list_contains_v = value_list_contains<List, Value>::value;
- /*! @brief Primary template isn't defined on purpose. */
- template<typename...>
- struct value_list_diff;
- /**
- * @brief Computes the difference between two value lists.
- * @tparam Value Values provided by the first value list.
- * @tparam Other Values provided by the second value list.
- */
- template<auto... Value, auto... Other>
- struct value_list_diff<value_list<Value...>, value_list<Other...>> {
- /*! @brief A value list that is the difference between the two value lists. */
- using type = value_list_cat_t<std::conditional_t<value_list_contains_v<value_list<Other...>, Value>, value_list<>, value_list<Value>>...>;
- };
- /**
- * @brief Helper type.
- * @tparam List Value lists between which to compute the difference.
- */
- template<typename... List>
- using value_list_diff_t = typename value_list_diff<List...>::type;
- /*! @brief Same as std::is_invocable, but with tuples. */
- template<typename, typename>
- struct is_applicable: std::false_type {};
- /**
- * @copybrief is_applicable
- * @tparam Func A valid function type.
- * @tparam Tuple Tuple-like type.
- * @tparam Args The list of arguments to use to probe the function type.
- */
- template<typename Func, template<typename...> class Tuple, typename... Args>
- struct is_applicable<Func, Tuple<Args...>>: std::is_invocable<Func, Args...> {};
- /**
- * @copybrief is_applicable
- * @tparam Func A valid function type.
- * @tparam Tuple Tuple-like type.
- * @tparam Args The list of arguments to use to probe the function type.
- */
- template<typename Func, template<typename...> class Tuple, typename... Args>
- struct is_applicable<Func, const Tuple<Args...>>: std::is_invocable<Func, Args...> {};
- /**
- * @brief Helper variable template.
- * @tparam Func A valid function type.
- * @tparam Args The list of arguments to use to probe the function type.
- */
- template<typename Func, typename Args>
- inline constexpr bool is_applicable_v = is_applicable<Func, Args>::value;
- /*! @brief Same as std::is_invocable_r, but with tuples for arguments. */
- template<typename, typename, typename>
- struct is_applicable_r: std::false_type {};
- /**
- * @copybrief is_applicable_r
- * @tparam Ret The type to which the return type of the function should be
- * convertible.
- * @tparam Func A valid function type.
- * @tparam Args The list of arguments to use to probe the function type.
- */
- template<typename Ret, typename Func, typename... Args>
- struct is_applicable_r<Ret, Func, std::tuple<Args...>>: std::is_invocable_r<Ret, Func, Args...> {};
- /**
- * @brief Helper variable template.
- * @tparam Ret The type to which the return type of the function should be
- * convertible.
- * @tparam Func A valid function type.
- * @tparam Args The list of arguments to use to probe the function type.
- */
- template<typename Ret, typename Func, typename Args>
- inline constexpr bool is_applicable_r_v = is_applicable_r<Ret, Func, Args>::value;
- /**
- * @brief Provides the member constant `value` to true if a given type is
- * complete, false otherwise.
- * @tparam Type The type to test.
- */
- template<typename Type, typename = void>
- struct is_complete: std::false_type {};
- /*! @copydoc is_complete */
- template<typename Type>
- struct is_complete<Type, std::void_t<decltype(sizeof(Type))>>: std::true_type {};
- /**
- * @brief Helper variable template.
- * @tparam Type The type to test.
- */
- template<typename Type>
- inline constexpr bool is_complete_v = is_complete<Type>::value;
- /**
- * @brief Provides the member constant `value` to true if a given type is an
- * iterator, false otherwise.
- * @tparam Type The type to test.
- */
- template<typename Type, typename = void>
- struct is_iterator: std::false_type {};
- /*! @cond TURN_OFF_DOXYGEN */
- namespace internal {
- template<typename, typename = void>
- struct has_iterator_category: std::false_type {};
- template<typename Type>
- struct has_iterator_category<Type, std::void_t<typename std::iterator_traits<Type>::iterator_category>>: std::true_type {};
- } // namespace internal
- /*! @endcond */
- /*! @copydoc is_iterator */
- template<typename Type>
- struct is_iterator<Type, std::enable_if_t<!std::is_void_v<std::remove_const_t<std::remove_pointer_t<Type>>>>>
- : internal::has_iterator_category<Type> {};
- /**
- * @brief Helper variable template.
- * @tparam Type The type to test.
- */
- template<typename Type>
- inline constexpr bool is_iterator_v = is_iterator<Type>::value;
- /**
- * @brief Provides the member constant `value` to true if a given type is both
- * an empty and non-final class, false otherwise.
- * @tparam Type The type to test
- */
- template<typename Type>
- struct is_ebco_eligible
- : std::bool_constant<std::is_empty_v<Type> && !std::is_final_v<Type>> {};
- /**
- * @brief Helper variable template.
- * @tparam Type The type to test.
- */
- template<typename Type>
- inline constexpr bool is_ebco_eligible_v = is_ebco_eligible<Type>::value;
- /**
- * @brief Provides the member constant `value` to true if `Type::is_transparent`
- * is valid and denotes a type, false otherwise.
- * @tparam Type The type to test.
- */
- template<typename Type, typename = void>
- struct is_transparent: std::false_type {};
- /*! @copydoc is_transparent */
- template<typename Type>
- struct is_transparent<Type, std::void_t<typename Type::is_transparent>>: std::true_type {};
- /**
- * @brief Helper variable template.
- * @tparam Type The type to test.
- */
- template<typename Type>
- inline constexpr bool is_transparent_v = is_transparent<Type>::value;
- /*! @cond TURN_OFF_DOXYGEN */
- namespace internal {
- template<typename, typename = void>
- struct has_tuple_size_value: std::false_type {};
- template<typename Type>
- struct has_tuple_size_value<Type, std::void_t<decltype(std::tuple_size<const Type>::value)>>: std::true_type {};
- template<typename, typename = void>
- struct has_value_type: std::false_type {};
- template<typename Type>
- struct has_value_type<Type, std::void_t<typename Type::value_type>>: std::true_type {};
- template<typename>
- [[nodiscard]] constexpr bool dispatch_is_equality_comparable();
- template<typename Type, std::size_t... Index>
- [[nodiscard]] constexpr bool unpack_maybe_equality_comparable(std::index_sequence<Index...>) {
- return (dispatch_is_equality_comparable<std::tuple_element_t<Index, Type>>() && ...);
- }
- template<typename>
- [[nodiscard]] constexpr bool maybe_equality_comparable(char) {
- return false;
- }
- template<typename Type>
- [[nodiscard]] constexpr auto maybe_equality_comparable(int) -> decltype(std::declval<Type>() == std::declval<Type>()) {
- return true;
- }
- template<typename Type>
- [[nodiscard]] constexpr bool dispatch_is_equality_comparable() {
- // NOLINTBEGIN(modernize-use-transparent-functors)
- if constexpr(std::is_array_v<Type>) {
- return false;
- } else if constexpr(is_complete_v<std::tuple_size<std::remove_const_t<Type>>>) {
- if constexpr(has_tuple_size_value<Type>::value) {
- return maybe_equality_comparable<Type>(0) && unpack_maybe_equality_comparable<Type>(std::make_index_sequence<std::tuple_size<Type>::value>{});
- } else {
- return maybe_equality_comparable<Type>(0);
- }
- } else if constexpr(has_value_type<Type>::value) {
- if constexpr(is_iterator_v<Type> || std::is_same_v<typename Type::value_type, Type> || dispatch_is_equality_comparable<typename Type::value_type>()) {
- return maybe_equality_comparable<Type>(0);
- } else {
- return false;
- }
- } else {
- return maybe_equality_comparable<Type>(0);
- }
- // NOLINTEND(modernize-use-transparent-functors)
- }
- } // namespace internal
- /*! @endcond */
- /**
- * @brief Provides the member constant `value` to true if a given type is
- * equality comparable, false otherwise.
- * @tparam Type The type to test.
- */
- template<typename Type>
- struct is_equality_comparable: std::bool_constant<internal::dispatch_is_equality_comparable<Type>()> {};
- /*! @copydoc is_equality_comparable */
- template<typename Type>
- struct is_equality_comparable<const Type>: is_equality_comparable<Type> {};
- /**
- * @brief Helper variable template.
- * @tparam Type The type to test.
- */
- template<typename Type>
- inline constexpr bool is_equality_comparable_v = is_equality_comparable<Type>::value;
- /**
- * @brief Transcribes the constness of a type to another type.
- * @tparam To The type to which to transcribe the constness.
- * @tparam From The type from which to transcribe the constness.
- */
- template<typename To, typename From>
- struct constness_as {
- /*! @brief The type resulting from the transcription of the constness. */
- using type = std::remove_const_t<To>;
- };
- /*! @copydoc constness_as */
- template<typename To, typename From>
- struct constness_as<To, const From> {
- /*! @brief The type resulting from the transcription of the constness. */
- using type = const To;
- };
- /**
- * @brief Alias template to facilitate the transcription of the constness.
- * @tparam To The type to which to transcribe the constness.
- * @tparam From The type from which to transcribe the constness.
- */
- template<typename To, typename From>
- using constness_as_t = typename constness_as<To, From>::type;
- /**
- * @brief Extracts the class of a non-static member object or function.
- * @tparam Member A pointer to a non-static member object or function.
- */
- template<typename Member>
- class member_class {
- static_assert(std::is_member_pointer_v<Member>, "Invalid pointer type to non-static member object or function");
- template<typename Class, typename Ret, typename... Args>
- static Class *clazz(Ret (Class::*)(Args...));
- template<typename Class, typename Ret, typename... Args>
- static Class *clazz(Ret (Class::*)(Args...) const);
- template<typename Class, typename Type>
- static Class *clazz(Type Class::*);
- public:
- /*! @brief The class of the given non-static member object or function. */
- using type = std::remove_pointer_t<decltype(clazz(std::declval<Member>()))>;
- };
- /**
- * @brief Helper type.
- * @tparam Member A pointer to a non-static member object or function.
- */
- template<typename Member>
- using member_class_t = typename member_class<Member>::type;
- /**
- * @brief Extracts the n-th argument of a _callable_ type.
- * @tparam Index The index of the argument to extract.
- * @tparam Candidate A valid _callable_ type.
- */
- template<std::size_t Index, typename Candidate>
- class nth_argument {
- template<typename Ret, typename... Args>
- static constexpr type_list<Args...> pick_up(Ret (*)(Args...));
- template<typename Ret, typename Class, typename... Args>
- static constexpr type_list<Args...> pick_up(Ret (Class ::*)(Args...));
- template<typename Ret, typename Class, typename... Args>
- static constexpr type_list<Args...> pick_up(Ret (Class ::*)(Args...) const);
- template<typename Type, typename Class>
- static constexpr type_list<Type> pick_up(Type Class ::*);
- template<typename Type>
- static constexpr decltype(pick_up(&Type::operator())) pick_up(Type &&);
- public:
- /*! @brief N-th argument of the _callable_ type. */
- using type = type_list_element_t<Index, decltype(pick_up(std::declval<Candidate>()))>;
- };
- /**
- * @brief Helper type.
- * @tparam Index The index of the argument to extract.
- * @tparam Candidate A valid function, member function or data member type.
- */
- template<std::size_t Index, typename Candidate>
- using nth_argument_t = typename nth_argument<Index, Candidate>::type;
- } // namespace entt
- template<typename... Type>
- struct std::tuple_size<entt::type_list<Type...>>: std::integral_constant<std::size_t, entt::type_list<Type...>::size> {};
- template<std::size_t Index, typename... Type>
- struct std::tuple_element<Index, entt::type_list<Type...>>: entt::type_list_element<Index, entt::type_list<Type...>> {};
- template<auto... Value>
- struct std::tuple_size<entt::value_list<Value...>>: std::integral_constant<std::size_t, entt::value_list<Value...>::size> {};
- template<std::size_t Index, auto... Value>
- struct std::tuple_element<Index, entt::value_list<Value...>>: entt::value_list_element<Index, entt::value_list<Value...>> {};
- #endif
- // #include "fwd.hpp"
- #ifndef ENTT_CONTAINER_FWD_HPP
- #define ENTT_CONTAINER_FWD_HPP
- #include <functional>
- #include <memory>
- #include <utility>
- #include <vector>
- namespace entt {
- template<
- typename Key,
- typename Type,
- typename = std::hash<Key>,
- typename = std::equal_to<>,
- typename = std::allocator<std::pair<const Key, Type>>>
- class dense_map;
- template<
- typename Type,
- typename = std::hash<Type>,
- typename = std::equal_to<>,
- typename = std::allocator<Type>>
- class dense_set;
- template<typename...>
- class basic_table;
- /**
- * @brief Alias declaration for the most common use case.
- * @tparam Type Element types.
- */
- template<typename... Type>
- using table = basic_table<std::vector<Type>...>;
- } // namespace entt
- #endif
- namespace entt {
- /*! @cond TURN_OFF_DOXYGEN */
- namespace internal {
- static constexpr std::size_t dense_map_placeholder_position = (std::numeric_limits<std::size_t>::max)();
- template<typename Key, typename Type>
- struct dense_map_node final {
- using value_type = std::pair<Key, Type>;
- template<typename... Args>
- dense_map_node(const std::size_t pos, Args &&...args)
- : next{pos},
- element{std::forward<Args>(args)...} {}
- template<typename Allocator, typename... Args>
- dense_map_node(std::allocator_arg_t, const Allocator &allocator, const std::size_t pos, Args &&...args)
- : next{pos},
- element{entt::make_obj_using_allocator<value_type>(allocator, std::forward<Args>(args)...)} {}
- template<typename Allocator>
- dense_map_node(std::allocator_arg_t, const Allocator &allocator, const dense_map_node &other)
- : next{other.next},
- element{entt::make_obj_using_allocator<value_type>(allocator, other.element)} {}
- template<typename Allocator>
- dense_map_node(std::allocator_arg_t, const Allocator &allocator, dense_map_node &&other)
- : next{other.next},
- element{entt::make_obj_using_allocator<value_type>(allocator, std::move(other.element))} {}
- std::size_t next;
- value_type element;
- };
- template<typename It>
- class dense_map_iterator final {
- template<typename>
- friend class dense_map_iterator;
- using first_type = decltype(std::as_const(std::declval<It>()->element.first));
- using second_type = decltype((std::declval<It>()->element.second));
- public:
- using value_type = std::pair<first_type, second_type>;
- using pointer = input_iterator_pointer<value_type>;
- using reference = value_type;
- using difference_type = std::ptrdiff_t;
- using iterator_category = std::input_iterator_tag;
- using iterator_concept = std::random_access_iterator_tag;
- constexpr dense_map_iterator() noexcept
- : it{} {}
- constexpr dense_map_iterator(const It iter) noexcept
- : it{iter} {}
- template<typename Other, typename = std::enable_if_t<!std::is_same_v<It, Other> && std::is_constructible_v<It, Other>>>
- constexpr dense_map_iterator(const dense_map_iterator<Other> &other) noexcept
- : it{other.it} {}
- constexpr dense_map_iterator &operator++() noexcept {
- return ++it, *this;
- }
- constexpr dense_map_iterator operator++(int) noexcept {
- const dense_map_iterator orig = *this;
- return ++(*this), orig;
- }
- constexpr dense_map_iterator &operator--() noexcept {
- return --it, *this;
- }
- constexpr dense_map_iterator operator--(int) noexcept {
- const dense_map_iterator orig = *this;
- return operator--(), orig;
- }
- constexpr dense_map_iterator &operator+=(const difference_type value) noexcept {
- it += value;
- return *this;
- }
- constexpr dense_map_iterator operator+(const difference_type value) const noexcept {
- dense_map_iterator copy = *this;
- return (copy += value);
- }
- constexpr dense_map_iterator &operator-=(const difference_type value) noexcept {
- return (*this += -value);
- }
- constexpr dense_map_iterator operator-(const difference_type value) const noexcept {
- return (*this + -value);
- }
- [[nodiscard]] constexpr reference operator[](const difference_type value) const noexcept {
- return {it[value].element.first, it[value].element.second};
- }
- [[nodiscard]] constexpr pointer operator->() const noexcept {
- return operator*();
- }
- [[nodiscard]] constexpr reference operator*() const noexcept {
- return operator[](0);
- }
- template<typename Lhs, typename Rhs>
- friend constexpr std::ptrdiff_t operator-(const dense_map_iterator<Lhs> &, const dense_map_iterator<Rhs> &) noexcept;
- template<typename Lhs, typename Rhs>
- friend constexpr bool operator==(const dense_map_iterator<Lhs> &, const dense_map_iterator<Rhs> &) noexcept;
- template<typename Lhs, typename Rhs>
- friend constexpr bool operator<(const dense_map_iterator<Lhs> &, const dense_map_iterator<Rhs> &) noexcept;
- private:
- It it;
- };
- template<typename Lhs, typename Rhs>
- [[nodiscard]] constexpr std::ptrdiff_t operator-(const dense_map_iterator<Lhs> &lhs, const dense_map_iterator<Rhs> &rhs) noexcept {
- return lhs.it - rhs.it;
- }
- template<typename Lhs, typename Rhs>
- [[nodiscard]] constexpr bool operator==(const dense_map_iterator<Lhs> &lhs, const dense_map_iterator<Rhs> &rhs) noexcept {
- return lhs.it == rhs.it;
- }
- template<typename Lhs, typename Rhs>
- [[nodiscard]] constexpr bool operator!=(const dense_map_iterator<Lhs> &lhs, const dense_map_iterator<Rhs> &rhs) noexcept {
- return !(lhs == rhs);
- }
- template<typename Lhs, typename Rhs>
- [[nodiscard]] constexpr bool operator<(const dense_map_iterator<Lhs> &lhs, const dense_map_iterator<Rhs> &rhs) noexcept {
- return lhs.it < rhs.it;
- }
- template<typename Lhs, typename Rhs>
- [[nodiscard]] constexpr bool operator>(const dense_map_iterator<Lhs> &lhs, const dense_map_iterator<Rhs> &rhs) noexcept {
- return rhs < lhs;
- }
- template<typename Lhs, typename Rhs>
- [[nodiscard]] constexpr bool operator<=(const dense_map_iterator<Lhs> &lhs, const dense_map_iterator<Rhs> &rhs) noexcept {
- return !(lhs > rhs);
- }
- template<typename Lhs, typename Rhs>
- [[nodiscard]] constexpr bool operator>=(const dense_map_iterator<Lhs> &lhs, const dense_map_iterator<Rhs> &rhs) noexcept {
- return !(lhs < rhs);
- }
- template<typename It>
- class dense_map_local_iterator final {
- template<typename>
- friend class dense_map_local_iterator;
- using first_type = decltype(std::as_const(std::declval<It>()->element.first));
- using second_type = decltype((std::declval<It>()->element.second));
- public:
- using value_type = std::pair<first_type, second_type>;
- using pointer = input_iterator_pointer<value_type>;
- using reference = value_type;
- using difference_type = std::ptrdiff_t;
- using iterator_category = std::input_iterator_tag;
- using iterator_concept = std::forward_iterator_tag;
- constexpr dense_map_local_iterator() noexcept = default;
- constexpr dense_map_local_iterator(It iter, const std::size_t pos) noexcept
- : it{iter},
- offset{pos} {}
- template<typename Other, typename = std::enable_if_t<!std::is_same_v<It, Other> && std::is_constructible_v<It, Other>>>
- constexpr dense_map_local_iterator(const dense_map_local_iterator<Other> &other) noexcept
- : it{other.it},
- offset{other.offset} {}
- constexpr dense_map_local_iterator &operator++() noexcept {
- return (offset = it[static_cast<typename It::difference_type>(offset)].next), *this;
- }
- constexpr dense_map_local_iterator operator++(int) noexcept {
- const dense_map_local_iterator orig = *this;
- return ++(*this), orig;
- }
- [[nodiscard]] constexpr pointer operator->() const noexcept {
- return operator*();
- }
- [[nodiscard]] constexpr reference operator*() const noexcept {
- const auto idx = static_cast<typename It::difference_type>(offset);
- return {it[idx].element.first, it[idx].element.second};
- }
- [[nodiscard]] constexpr std::size_t index() const noexcept {
- return offset;
- }
- private:
- It it{};
- std::size_t offset{dense_map_placeholder_position};
- };
- template<typename Lhs, typename Rhs>
- [[nodiscard]] constexpr bool operator==(const dense_map_local_iterator<Lhs> &lhs, const dense_map_local_iterator<Rhs> &rhs) noexcept {
- return lhs.index() == rhs.index();
- }
- template<typename Lhs, typename Rhs>
- [[nodiscard]] constexpr bool operator!=(const dense_map_local_iterator<Lhs> &lhs, const dense_map_local_iterator<Rhs> &rhs) noexcept {
- return !(lhs == rhs);
- }
- } // namespace internal
- /*! @endcond */
- /**
- * @brief Associative container for key-value pairs with unique keys.
- *
- * Internally, elements are organized into buckets. Which bucket an element is
- * placed into depends entirely on the hash of its key. Keys with the same hash
- * code appear in the same bucket.
- *
- * @tparam Key Key type of the associative container.
- * @tparam Type Mapped type of the associative container.
- * @tparam Hash Type of function to use to hash the keys.
- * @tparam KeyEqual Type of function to use to compare the keys for equality.
- * @tparam Allocator Type of allocator used to manage memory and elements.
- */
- template<typename Key, typename Type, typename Hash, typename KeyEqual, typename Allocator>
- class dense_map {
- static constexpr float default_threshold = 0.875f;
- static constexpr std::size_t minimum_capacity = 8u;
- static constexpr std::size_t placeholder_position = internal::dense_map_placeholder_position;
- using node_type = internal::dense_map_node<Key, Type>;
- using alloc_traits = std::allocator_traits<Allocator>;
- static_assert(std::is_same_v<typename alloc_traits::value_type, std::pair<const Key, Type>>, "Invalid value type");
- using sparse_container_type = std::vector<std::size_t, typename alloc_traits::template rebind_alloc<std::size_t>>;
- using packed_container_type = std::vector<node_type, typename alloc_traits::template rebind_alloc<node_type>>;
- template<typename Other>
- [[nodiscard]] std::size_t key_to_bucket(const Other &key) const noexcept {
- // NOLINTNEXTLINE(cppcoreguidelines-pro-bounds-array-to-pointer-decay)
- return fast_mod(static_cast<size_type>(sparse.second()(key)), bucket_count());
- }
- template<typename Other>
- [[nodiscard]] auto constrained_find(const Other &key, const std::size_t bucket) {
- for(auto offset = sparse.first()[bucket]; offset != placeholder_position; offset = packed.first()[offset].next) {
- if(packed.second()(packed.first()[offset].element.first, key)) {
- return begin() + static_cast<typename iterator::difference_type>(offset);
- }
- }
- return end();
- }
- template<typename Other>
- [[nodiscard]] auto constrained_find(const Other &key, const std::size_t bucket) const {
- for(auto offset = sparse.first()[bucket]; offset != placeholder_position; offset = packed.first()[offset].next) {
- if(packed.second()(packed.first()[offset].element.first, key)) {
- return cbegin() + static_cast<typename const_iterator::difference_type>(offset);
- }
- }
- return cend();
- }
- template<typename Other, typename... Args>
- [[nodiscard]] auto insert_or_do_nothing(Other &&key, Args &&...args) {
- const auto index = key_to_bucket(key);
- if(auto it = constrained_find(key, index); it != end()) {
- return std::make_pair(it, false);
- }
- packed.first().emplace_back(sparse.first()[index], std::piecewise_construct, std::forward_as_tuple(std::forward<Other>(key)), std::forward_as_tuple(std::forward<Args>(args)...));
- sparse.first()[index] = packed.first().size() - 1u;
- rehash_if_required();
- return std::make_pair(--end(), true);
- }
- template<typename Other, typename Arg>
- [[nodiscard]] auto insert_or_overwrite(Other &&key, Arg &&value) {
- const auto index = key_to_bucket(key);
- if(auto it = constrained_find(key, index); it != end()) {
- it->second = std::forward<Arg>(value);
- return std::make_pair(it, false);
- }
- packed.first().emplace_back(sparse.first()[index], std::forward<Other>(key), std::forward<Arg>(value));
- sparse.first()[index] = packed.first().size() - 1u;
- rehash_if_required();
- return std::make_pair(--end(), true);
- }
- void move_and_pop(const std::size_t pos) {
- if(const auto last = size() - 1u; pos != last) {
- size_type *curr = &sparse.first()[key_to_bucket(packed.first().back().element.first)];
- packed.first()[pos] = std::move(packed.first().back());
- for(; *curr != last; curr = &packed.first()[*curr].next) {}
- *curr = pos;
- }
- packed.first().pop_back();
- }
- void rehash_if_required() {
- if(const auto bc = bucket_count(); size() > static_cast<size_type>(static_cast<float>(bc) * max_load_factor())) {
- rehash(bc * 2u);
- }
- }
- public:
- /*! @brief Allocator type. */
- using allocator_type = Allocator;
- /*! @brief Key type of the container. */
- using key_type = Key;
- /*! @brief Mapped type of the container. */
- using mapped_type = Type;
- /*! @brief Key-value type of the container. */
- using value_type = std::pair<const Key, Type>;
- /*! @brief Unsigned integer type. */
- using size_type = std::size_t;
- /*! @brief Signed integer type. */
- using difference_type = std::ptrdiff_t;
- /*! @brief Type of function to use to hash the keys. */
- using hasher = Hash;
- /*! @brief Type of function to use to compare the keys for equality. */
- using key_equal = KeyEqual;
- /*! @brief Input iterator type. */
- using iterator = internal::dense_map_iterator<typename packed_container_type::iterator>;
- /*! @brief Constant input iterator type. */
- using const_iterator = internal::dense_map_iterator<typename packed_container_type::const_iterator>;
- /*! @brief Input iterator type. */
- using local_iterator = internal::dense_map_local_iterator<typename packed_container_type::iterator>;
- /*! @brief Constant input iterator type. */
- using const_local_iterator = internal::dense_map_local_iterator<typename packed_container_type::const_iterator>;
- /*! @brief Default constructor. */
- dense_map()
- : dense_map{minimum_capacity} {}
- /**
- * @brief Constructs an empty container with a given allocator.
- * @param allocator The allocator to use.
- */
- explicit dense_map(const allocator_type &allocator)
- : dense_map{minimum_capacity, hasher{}, key_equal{}, allocator} {}
- /**
- * @brief Constructs an empty container with a given allocator and user
- * supplied minimal number of buckets.
- * @param cnt Minimal number of buckets.
- * @param allocator The allocator to use.
- */
- dense_map(const size_type cnt, const allocator_type &allocator)
- : dense_map{cnt, hasher{}, key_equal{}, allocator} {}
- /**
- * @brief Constructs an empty container with a given allocator, hash
- * function and user supplied minimal number of buckets.
- * @param cnt Minimal number of buckets.
- * @param hash Hash function to use.
- * @param allocator The allocator to use.
- */
- dense_map(const size_type cnt, const hasher &hash, const allocator_type &allocator)
- : dense_map{cnt, hash, key_equal{}, allocator} {}
- /**
- * @brief Constructs an empty container with a given allocator, hash
- * function, compare function and user supplied minimal number of buckets.
- * @param cnt Minimal number of buckets.
- * @param hash Hash function to use.
- * @param equal Compare function to use.
- * @param allocator The allocator to use.
- */
- explicit dense_map(const size_type cnt, const hasher &hash = hasher{}, const key_equal &equal = key_equal{}, const allocator_type &allocator = allocator_type{})
- : sparse{allocator, hash},
- packed{allocator, equal} {
- rehash(cnt);
- }
- /*! @brief Default copy constructor. */
- dense_map(const dense_map &) = default;
- /**
- * @brief Allocator-extended copy constructor.
- * @param other The instance to copy from.
- * @param allocator The allocator to use.
- */
- dense_map(const dense_map &other, const allocator_type &allocator)
- : sparse{std::piecewise_construct, std::forward_as_tuple(other.sparse.first(), allocator), std::forward_as_tuple(other.sparse.second())},
- packed{std::piecewise_construct, std::forward_as_tuple(other.packed.first(), allocator), std::forward_as_tuple(other.packed.second())},
- threshold{other.threshold} {}
- /*! @brief Default move constructor. */
- dense_map(dense_map &&) noexcept = default;
- /**
- * @brief Allocator-extended move constructor.
- * @param other The instance to move from.
- * @param allocator The allocator to use.
- */
- dense_map(dense_map &&other, const allocator_type &allocator)
- : sparse{std::piecewise_construct, std::forward_as_tuple(std::move(other.sparse.first()), allocator), std::forward_as_tuple(std::move(other.sparse.second()))},
- packed{std::piecewise_construct, std::forward_as_tuple(std::move(other.packed.first()), allocator), std::forward_as_tuple(std::move(other.packed.second()))},
- threshold{other.threshold} {}
- /*! @brief Default destructor. */
- ~dense_map() = default;
- /**
- * @brief Default copy assignment operator.
- * @return This container.
- */
- dense_map &operator=(const dense_map &) = default;
- /**
- * @brief Default move assignment operator.
- * @return This container.
- */
- dense_map &operator=(dense_map &&) noexcept = default;
- /**
- * @brief Exchanges the contents with those of a given container.
- * @param other Container to exchange the content with.
- */
- void swap(dense_map &other) noexcept {
- using std::swap;
- swap(sparse, other.sparse);
- swap(packed, other.packed);
- swap(threshold, other.threshold);
- }
- /**
- * @brief Returns the associated allocator.
- * @return The associated allocator.
- */
- [[nodiscard]] constexpr allocator_type get_allocator() const noexcept {
- return sparse.first().get_allocator();
- }
- /**
- * @brief Returns an iterator to the beginning.
- *
- * If the array is empty, the returned iterator will be equal to `end()`.
- *
- * @return An iterator to the first instance of the internal array.
- */
- [[nodiscard]] const_iterator cbegin() const noexcept {
- return packed.first().begin();
- }
- /*! @copydoc cbegin */
- [[nodiscard]] const_iterator begin() const noexcept {
- return cbegin();
- }
- /*! @copydoc begin */
- [[nodiscard]] iterator begin() noexcept {
- return packed.first().begin();
- }
- /**
- * @brief Returns an iterator to the end.
- * @return An iterator to the element following the last instance of the
- * internal array.
- */
- [[nodiscard]] const_iterator cend() const noexcept {
- return packed.first().end();
- }
- /*! @copydoc cend */
- [[nodiscard]] const_iterator end() const noexcept {
- return cend();
- }
- /*! @copydoc end */
- [[nodiscard]] iterator end() noexcept {
- return packed.first().end();
- }
- /**
- * @brief Checks whether a container is empty.
- * @return True if the container is empty, false otherwise.
- */
- [[nodiscard]] bool empty() const noexcept {
- return packed.first().empty();
- }
- /**
- * @brief Returns the number of elements in a container.
- * @return Number of elements in a container.
- */
- [[nodiscard]] size_type size() const noexcept {
- return packed.first().size();
- }
- /**
- * @brief Returns the maximum possible number of elements.
- * @return Maximum possible number of elements.
- */
- [[nodiscard]] size_type max_size() const noexcept {
- return packed.first().max_size();
- }
- /*! @brief Clears the container. */
- void clear() noexcept {
- sparse.first().clear();
- packed.first().clear();
- rehash(0u);
- }
- /**
- * @brief Inserts an element into the container, if the key does not exist.
- * @param value A key-value pair eventually convertible to the value type.
- * @return A pair consisting of an iterator to the inserted element (or to
- * the element that prevented the insertion) and a bool denoting whether the
- * insertion took place.
- */
- std::pair<iterator, bool> insert(const value_type &value) {
- return insert_or_do_nothing(value.first, value.second);
- }
- /*! @copydoc insert */
- std::pair<iterator, bool> insert(value_type &&value) {
- return insert_or_do_nothing(std::move(value.first), std::move(value.second));
- }
- /**
- * @copydoc insert
- * @tparam Arg Type of the key-value pair to insert into the container.
- */
- template<typename Arg>
- std::enable_if_t<std::is_constructible_v<value_type, Arg &&>, std::pair<iterator, bool>>
- insert(Arg &&value) {
- return insert_or_do_nothing(std::forward<Arg>(value).first, std::forward<Arg>(value).second);
- }
- /**
- * @brief Inserts elements into the container, if their keys do not exist.
- * @tparam It Type of input iterator.
- * @param first An iterator to the first element of the range of elements.
- * @param last An iterator past the last element of the range of elements.
- */
- template<typename It>
- void insert(It first, It last) {
- for(; first != last; ++first) {
- insert(*first);
- }
- }
- /**
- * @brief Inserts an element into the container or assigns to the current
- * element if the key already exists.
- * @tparam Arg Type of the value to insert or assign.
- * @param key A key used both to look up and to insert if not found.
- * @param value A value to insert or assign.
- * @return A pair consisting of an iterator to the element and a bool
- * denoting whether the insertion took place.
- */
- template<typename Arg>
- std::pair<iterator, bool> insert_or_assign(const key_type &key, Arg &&value) {
- return insert_or_overwrite(key, std::forward<Arg>(value));
- }
- /*! @copydoc insert_or_assign */
- template<typename Arg>
- std::pair<iterator, bool> insert_or_assign(key_type &&key, Arg &&value) {
- return insert_or_overwrite(std::move(key), std::forward<Arg>(value));
- }
- /**
- * @brief Constructs an element in-place, if the key does not exist.
- *
- * The element is also constructed when the container already has the key,
- * in which case the newly constructed object is destroyed immediately.
- *
- * @tparam Args Types of arguments to forward to the constructor of the
- * element.
- * @param args Arguments to forward to the constructor of the element.
- * @return A pair consisting of an iterator to the inserted element (or to
- * the element that prevented the insertion) and a bool denoting whether the
- * insertion took place.
- */
- template<typename... Args>
- std::pair<iterator, bool> emplace([[maybe_unused]] Args &&...args) {
- if constexpr(sizeof...(Args) == 0u) {
- return insert_or_do_nothing(key_type{});
- } else if constexpr(sizeof...(Args) == 1u) {
- return insert_or_do_nothing(std::forward<Args>(args).first..., std::forward<Args>(args).second...);
- } else if constexpr(sizeof...(Args) == 2u) {
- return insert_or_do_nothing(std::forward<Args>(args)...);
- } else {
- auto &node = packed.first().emplace_back(packed.first().size(), std::forward<Args>(args)...);
- const auto index = key_to_bucket(node.element.first);
- if(auto it = constrained_find(node.element.first, index); it != end()) {
- packed.first().pop_back();
- return std::make_pair(it, false);
- }
- std::swap(node.next, sparse.first()[index]);
- rehash_if_required();
- return std::make_pair(--end(), true);
- }
- }
- /**
- * @brief Inserts in-place if the key does not exist, does nothing if the
- * key exists.
- * @tparam Args Types of arguments to forward to the constructor of the
- * element.
- * @param key A key used both to look up and to insert if not found.
- * @param args Arguments to forward to the constructor of the element.
- * @return A pair consisting of an iterator to the inserted element (or to
- * the element that prevented the insertion) and a bool denoting whether the
- * insertion took place.
- */
- template<typename... Args>
- std::pair<iterator, bool> try_emplace(const key_type &key, Args &&...args) {
- return insert_or_do_nothing(key, std::forward<Args>(args)...);
- }
- /*! @copydoc try_emplace */
- template<typename... Args>
- std::pair<iterator, bool> try_emplace(key_type &&key, Args &&...args) {
- return insert_or_do_nothing(std::move(key), std::forward<Args>(args)...);
- }
- /**
- * @brief Removes an element from a given position.
- * @param pos An iterator to the element to remove.
- * @return An iterator following the removed element.
- */
- iterator erase(const_iterator pos) {
- const auto diff = pos - cbegin();
- erase(pos->first);
- return begin() + diff;
- }
- /**
- * @brief Removes the given elements from a container.
- * @param first An iterator to the first element of the range of elements.
- * @param last An iterator past the last element of the range of elements.
- * @return An iterator following the last removed element.
- */
- iterator erase(const_iterator first, const_iterator last) {
- const auto dist = first - cbegin();
- for(auto from = last - cbegin(); from != dist; --from) {
- erase(packed.first()[static_cast<size_type>(from) - 1u].element.first);
- }
- return (begin() + dist);
- }
- /**
- * @brief Removes the element associated with a given key.
- * @param key A key value of an element to remove.
- * @return Number of elements removed (either 0 or 1).
- */
- size_type erase(const key_type &key) {
- for(size_type *curr = &sparse.first()[key_to_bucket(key)]; *curr != placeholder_position; curr = &packed.first()[*curr].next) {
- if(packed.second()(packed.first()[*curr].element.first, key)) {
- const auto index = *curr;
- *curr = packed.first()[*curr].next;
- move_and_pop(index);
- return 1u;
- }
- }
- return 0u;
- }
- /**
- * @brief Accesses a given element with bounds checking.
- * @param key A key of an element to find.
- * @return A reference to the mapped value of the requested element.
- */
- [[nodiscard]] mapped_type &at(const key_type &key) {
- auto it = find(key);
- ENTT_ASSERT(it != end(), "Invalid key");
- return it->second;
- }
- /*! @copydoc at */
- [[nodiscard]] const mapped_type &at(const key_type &key) const {
- auto it = find(key);
- ENTT_ASSERT(it != cend(), "Invalid key");
- return it->second;
- }
- /**
- * @brief Accesses a given element with bounds checking.
- * @tparam Other Type of the key of an element to find.
- * @param key A key of an element to find.
- * @return A reference to the mapped value of the requested element.
- */
- template<typename Other>
- [[nodiscard]] std::enable_if_t<is_transparent_v<hasher> && is_transparent_v<key_equal>, std::conditional_t<false, Other, mapped_type const &>>
- at(const Other &key) const {
- auto it = find(key);
- ENTT_ASSERT(it != cend(), "Invalid key");
- return it->second;
- }
- /*! @copydoc at */
- template<typename Other>
- [[nodiscard]] std::enable_if_t<is_transparent_v<hasher> && is_transparent_v<key_equal>, std::conditional_t<false, Other, mapped_type &>>
- at(const Other &key) {
- auto it = find(key);
- ENTT_ASSERT(it != end(), "Invalid key");
- return it->second;
- }
- /**
- * @brief Accesses or inserts a given element.
- * @param key A key of an element to find or insert.
- * @return A reference to the mapped value of the requested element.
- */
- [[nodiscard]] mapped_type &operator[](const key_type &key) {
- return insert_or_do_nothing(key).first->second;
- }
- /**
- * @brief Accesses or inserts a given element.
- * @param key A key of an element to find or insert.
- * @return A reference to the mapped value of the requested element.
- */
- [[nodiscard]] mapped_type &operator[](key_type &&key) {
- return insert_or_do_nothing(std::move(key)).first->second;
- }
- /**
- * @brief Returns the number of elements matching a key (either 1 or 0).
- * @param key Key value of an element to search for.
- * @return Number of elements matching the key (either 1 or 0).
- */
- [[nodiscard]] size_type count(const key_type &key) const {
- return find(key) != end();
- }
- /**
- * @brief Returns the number of elements matching a key (either 1 or 0).
- * @tparam Other Type of the key value of an element to search for.
- * @param key Key value of an element to search for.
- * @return Number of elements matching the key (either 1 or 0).
- */
- template<typename Other>
- [[nodiscard]] std::enable_if_t<is_transparent_v<hasher> && is_transparent_v<key_equal>, std::conditional_t<false, Other, size_type>>
- count(const Other &key) const {
- return find(key) != end();
- }
- /**
- * @brief Finds an element with a given key.
- * @param key Key value of an element to search for.
- * @return An iterator to an element with the given key. If no such element
- * is found, a past-the-end iterator is returned.
- */
- [[nodiscard]] iterator find(const key_type &key) {
- return constrained_find(key, key_to_bucket(key));
- }
- /*! @copydoc find */
- [[nodiscard]] const_iterator find(const key_type &key) const {
- return constrained_find(key, key_to_bucket(key));
- }
- /**
- * @brief Finds an element with a key that compares _equivalent_ to a given
- * key.
- * @tparam Other Type of the key value of an element to search for.
- * @param key Key value of an element to search for.
- * @return An iterator to an element with the given key. If no such element
- * is found, a past-the-end iterator is returned.
- */
- template<typename Other>
- [[nodiscard]] std::enable_if_t<is_transparent_v<hasher> && is_transparent_v<key_equal>, std::conditional_t<false, Other, iterator>>
- find(const Other &key) {
- return constrained_find(key, key_to_bucket(key));
- }
- /*! @copydoc find */
- template<typename Other>
- [[nodiscard]] std::enable_if_t<is_transparent_v<hasher> && is_transparent_v<key_equal>, std::conditional_t<false, Other, const_iterator>>
- find(const Other &key) const {
- return constrained_find(key, key_to_bucket(key));
- }
- /**
- * @brief Returns a range containing all elements with a given key.
- * @param key Key value of an element to search for.
- * @return A pair of iterators pointing to the first element and past the
- * last element of the range.
- */
- [[nodiscard]] std::pair<iterator, iterator> equal_range(const key_type &key) {
- const auto it = find(key);
- return {it, it + !(it == end())};
- }
- /*! @copydoc equal_range */
- [[nodiscard]] std::pair<const_iterator, const_iterator> equal_range(const key_type &key) const {
- const auto it = find(key);
- return {it, it + !(it == cend())};
- }
- /**
- * @brief Returns a range containing all elements that compare _equivalent_
- * to a given key.
- * @tparam Other Type of an element to search for.
- * @param key Key value of an element to search for.
- * @return A pair of iterators pointing to the first element and past the
- * last element of the range.
- */
- template<typename Other>
- [[nodiscard]] std::enable_if_t<is_transparent_v<hasher> && is_transparent_v<key_equal>, std::conditional_t<false, Other, std::pair<iterator, iterator>>>
- equal_range(const Other &key) {
- const auto it = find(key);
- return {it, it + !(it == end())};
- }
- /*! @copydoc equal_range */
- template<typename Other>
- [[nodiscard]] std::enable_if_t<is_transparent_v<hasher> && is_transparent_v<key_equal>, std::conditional_t<false, Other, std::pair<const_iterator, const_iterator>>>
- equal_range(const Other &key) const {
- const auto it = find(key);
- return {it, it + !(it == cend())};
- }
- /**
- * @brief Checks if the container contains an element with a given key.
- * @param key Key value of an element to search for.
- * @return True if there is such an element, false otherwise.
- */
- [[nodiscard]] bool contains(const key_type &key) const {
- return (find(key) != cend());
- }
- /**
- * @brief Checks if the container contains an element with a key that
- * compares _equivalent_ to a given value.
- * @tparam Other Type of the key value of an element to search for.
- * @param key Key value of an element to search for.
- * @return True if there is such an element, false otherwise.
- */
- template<typename Other>
- [[nodiscard]] std::enable_if_t<is_transparent_v<hasher> && is_transparent_v<key_equal>, std::conditional_t<false, Other, bool>>
- contains(const Other &key) const {
- return (find(key) != cend());
- }
- /**
- * @brief Returns an iterator to the beginning of a given bucket.
- * @param index An index of a bucket to access.
- * @return An iterator to the beginning of the given bucket.
- */
- [[nodiscard]] const_local_iterator cbegin(const size_type index) const {
- return {packed.first().begin(), sparse.first()[index]};
- }
- /**
- * @brief Returns an iterator to the beginning of a given bucket.
- * @param index An index of a bucket to access.
- * @return An iterator to the beginning of the given bucket.
- */
- [[nodiscard]] const_local_iterator begin(const size_type index) const {
- return cbegin(index);
- }
- /**
- * @brief Returns an iterator to the beginning of a given bucket.
- * @param index An index of a bucket to access.
- * @return An iterator to the beginning of the given bucket.
- */
- [[nodiscard]] local_iterator begin(const size_type index) {
- return {packed.first().begin(), sparse.first()[index]};
- }
- /**
- * @brief Returns an iterator to the end of a given bucket.
- * @param index An index of a bucket to access.
- * @return An iterator to the end of the given bucket.
- */
- [[nodiscard]] const_local_iterator cend([[maybe_unused]] const size_type index) const {
- return {};
- }
- /**
- * @brief Returns an iterator to the end of a given bucket.
- * @param index An index of a bucket to access.
- * @return An iterator to the end of the given bucket.
- */
- [[nodiscard]] const_local_iterator end(const size_type index) const {
- return cend(index);
- }
- /**
- * @brief Returns an iterator to the end of a given bucket.
- * @param index An index of a bucket to access.
- * @return An iterator to the end of the given bucket.
- */
- [[nodiscard]] local_iterator end([[maybe_unused]] const size_type index) {
- return {};
- }
- /**
- * @brief Returns the number of buckets.
- * @return The number of buckets.
- */
- [[nodiscard]] size_type bucket_count() const {
- return sparse.first().size();
- }
- /**
- * @brief Returns the maximum number of buckets.
- * @return The maximum number of buckets.
- */
- [[nodiscard]] size_type max_bucket_count() const {
- return sparse.first().max_size();
- }
- /**
- * @brief Returns the number of elements in a given bucket.
- * @param index The index of the bucket to examine.
- * @return The number of elements in the given bucket.
- */
- [[nodiscard]] size_type bucket_size(const size_type index) const {
- return static_cast<size_type>(std::distance(begin(index), end(index)));
- }
- /**
- * @brief Returns the bucket for a given key.
- * @param key The value of the key to examine.
- * @return The bucket for the given key.
- */
- [[nodiscard]] size_type bucket(const key_type &key) const {
- return key_to_bucket(key);
- }
- /**
- * @brief Returns the average number of elements per bucket.
- * @return The average number of elements per bucket.
- */
- [[nodiscard]] float load_factor() const {
- return static_cast<float>(size()) / static_cast<float>(bucket_count());
- }
- /**
- * @brief Returns the maximum average number of elements per bucket.
- * @return The maximum average number of elements per bucket.
- */
- [[nodiscard]] float max_load_factor() const {
- return threshold;
- }
- /**
- * @brief Sets the desired maximum average number of elements per bucket.
- * @param value A desired maximum average number of elements per bucket.
- */
- void max_load_factor(const float value) {
- ENTT_ASSERT(value > 0.f, "Invalid load factor");
- threshold = value;
- rehash(0u);
- }
- /**
- * @brief Reserves at least the specified number of buckets and regenerates
- * the hash table.
- * @param cnt New number of buckets.
- */
- void rehash(const size_type cnt) {
- auto value = cnt > minimum_capacity ? cnt : minimum_capacity;
- const auto cap = static_cast<size_type>(static_cast<float>(size()) / max_load_factor());
- value = value > cap ? value : cap;
- if(const auto sz = next_power_of_two(value); sz != bucket_count()) {
- sparse.first().resize(sz);
- for(auto &&elem: sparse.first()) {
- elem = placeholder_position;
- }
- for(size_type pos{}, last = size(); pos < last; ++pos) {
- const auto index = key_to_bucket(packed.first()[pos].element.first);
- packed.first()[pos].next = std::exchange(sparse.first()[index], pos);
- }
- }
- }
- /**
- * @brief Reserves space for at least the specified number of elements and
- * regenerates the hash table.
- * @param cnt New number of elements.
- */
- void reserve(const size_type cnt) {
- packed.first().reserve(cnt);
- rehash(static_cast<size_type>(std::ceil(static_cast<float>(cnt) / max_load_factor())));
- }
- /**
- * @brief Returns the function used to hash the keys.
- * @return The function used to hash the keys.
- */
- [[nodiscard]] hasher hash_function() const {
- return sparse.second();
- }
- /**
- * @brief Returns the function used to compare keys for equality.
- * @return The function used to compare keys for equality.
- */
- [[nodiscard]] key_equal key_eq() const {
- return packed.second();
- }
- private:
- compressed_pair<sparse_container_type, hasher> sparse;
- compressed_pair<packed_container_type, key_equal> packed;
- float threshold{default_threshold};
- };
- } // namespace entt
- /*! @cond TURN_OFF_DOXYGEN */
- namespace std {
- template<typename Key, typename Value, typename Allocator>
- struct uses_allocator<entt::internal::dense_map_node<Key, Value>, Allocator>
- : std::true_type {};
- } // namespace std
- /*! @endcond */
- #endif
- // #include "../container/dense_set.hpp"
- #ifndef ENTT_CONTAINER_DENSE_SET_HPP
- #define ENTT_CONTAINER_DENSE_SET_HPP
- #include <cmath>
- #include <cstddef>
- #include <functional>
- #include <iterator>
- #include <limits>
- #include <memory>
- #include <tuple>
- #include <type_traits>
- #include <utility>
- #include <vector>
- // #include "../config/config.h"
- // #include "../core/bit.hpp"
- // #include "../core/compressed_pair.hpp"
- // #include "../core/type_traits.hpp"
- // #include "fwd.hpp"
- namespace entt {
- /*! @cond TURN_OFF_DOXYGEN */
- namespace internal {
- static constexpr std::size_t dense_set_placeholder_position = (std::numeric_limits<std::size_t>::max)();
- template<typename It>
- class dense_set_iterator final {
- template<typename>
- friend class dense_set_iterator;
- public:
- using value_type = typename It::value_type::second_type;
- using pointer = const value_type *;
- using reference = const value_type &;
- using difference_type = std::ptrdiff_t;
- using iterator_category = std::random_access_iterator_tag;
- constexpr dense_set_iterator() noexcept
- : it{} {}
- constexpr dense_set_iterator(const It iter) noexcept
- : it{iter} {}
- template<typename Other, typename = std::enable_if_t<!std::is_same_v<It, Other> && std::is_constructible_v<It, Other>>>
- constexpr dense_set_iterator(const dense_set_iterator<Other> &other) noexcept
- : it{other.it} {}
- constexpr dense_set_iterator &operator++() noexcept {
- return ++it, *this;
- }
- constexpr dense_set_iterator operator++(int) noexcept {
- const dense_set_iterator orig = *this;
- return ++(*this), orig;
- }
- constexpr dense_set_iterator &operator--() noexcept {
- return --it, *this;
- }
- constexpr dense_set_iterator operator--(int) noexcept {
- const dense_set_iterator orig = *this;
- return operator--(), orig;
- }
- constexpr dense_set_iterator &operator+=(const difference_type value) noexcept {
- it += value;
- return *this;
- }
- constexpr dense_set_iterator operator+(const difference_type value) const noexcept {
- dense_set_iterator copy = *this;
- return (copy += value);
- }
- constexpr dense_set_iterator &operator-=(const difference_type value) noexcept {
- return (*this += -value);
- }
- constexpr dense_set_iterator operator-(const difference_type value) const noexcept {
- return (*this + -value);
- }
- [[nodiscard]] constexpr reference operator[](const difference_type value) const noexcept {
- return it[value].second;
- }
- [[nodiscard]] constexpr pointer operator->() const noexcept {
- return std::addressof(operator[](0));
- }
- [[nodiscard]] constexpr reference operator*() const noexcept {
- return operator[](0);
- }
- template<typename Lhs, typename Rhs>
- friend constexpr std::ptrdiff_t operator-(const dense_set_iterator<Lhs> &, const dense_set_iterator<Rhs> &) noexcept;
- template<typename Lhs, typename Rhs>
- friend constexpr bool operator==(const dense_set_iterator<Lhs> &, const dense_set_iterator<Rhs> &) noexcept;
- template<typename Lhs, typename Rhs>
- friend constexpr bool operator<(const dense_set_iterator<Lhs> &, const dense_set_iterator<Rhs> &) noexcept;
- private:
- It it;
- };
- template<typename Lhs, typename Rhs>
- [[nodiscard]] constexpr std::ptrdiff_t operator-(const dense_set_iterator<Lhs> &lhs, const dense_set_iterator<Rhs> &rhs) noexcept {
- return lhs.it - rhs.it;
- }
- template<typename Lhs, typename Rhs>
- [[nodiscard]] constexpr bool operator==(const dense_set_iterator<Lhs> &lhs, const dense_set_iterator<Rhs> &rhs) noexcept {
- return lhs.it == rhs.it;
- }
- template<typename Lhs, typename Rhs>
- [[nodiscard]] constexpr bool operator!=(const dense_set_iterator<Lhs> &lhs, const dense_set_iterator<Rhs> &rhs) noexcept {
- return !(lhs == rhs);
- }
- template<typename Lhs, typename Rhs>
- [[nodiscard]] constexpr bool operator<(const dense_set_iterator<Lhs> &lhs, const dense_set_iterator<Rhs> &rhs) noexcept {
- return lhs.it < rhs.it;
- }
- template<typename Lhs, typename Rhs>
- [[nodiscard]] constexpr bool operator>(const dense_set_iterator<Lhs> &lhs, const dense_set_iterator<Rhs> &rhs) noexcept {
- return rhs < lhs;
- }
- template<typename Lhs, typename Rhs>
- [[nodiscard]] constexpr bool operator<=(const dense_set_iterator<Lhs> &lhs, const dense_set_iterator<Rhs> &rhs) noexcept {
- return !(lhs > rhs);
- }
- template<typename Lhs, typename Rhs>
- [[nodiscard]] constexpr bool operator>=(const dense_set_iterator<Lhs> &lhs, const dense_set_iterator<Rhs> &rhs) noexcept {
- return !(lhs < rhs);
- }
- template<typename It>
- class dense_set_local_iterator final {
- template<typename>
- friend class dense_set_local_iterator;
- public:
- using value_type = typename It::value_type::second_type;
- using pointer = const value_type *;
- using reference = const value_type &;
- using difference_type = std::ptrdiff_t;
- using iterator_category = std::forward_iterator_tag;
- constexpr dense_set_local_iterator() noexcept = default;
- constexpr dense_set_local_iterator(It iter, const std::size_t pos) noexcept
- : it{iter},
- offset{pos} {}
- template<typename Other, typename = std::enable_if_t<!std::is_same_v<It, Other> && std::is_constructible_v<It, Other>>>
- constexpr dense_set_local_iterator(const dense_set_local_iterator<Other> &other) noexcept
- : it{other.it},
- offset{other.offset} {}
- constexpr dense_set_local_iterator &operator++() noexcept {
- return offset = it[static_cast<typename It::difference_type>(offset)].first, *this;
- }
- constexpr dense_set_local_iterator operator++(int) noexcept {
- const dense_set_local_iterator orig = *this;
- return ++(*this), orig;
- }
- [[nodiscard]] constexpr pointer operator->() const noexcept {
- return std::addressof(it[static_cast<typename It::difference_type>(offset)].second);
- }
- [[nodiscard]] constexpr reference operator*() const noexcept {
- return *operator->();
- }
- [[nodiscard]] constexpr std::size_t index() const noexcept {
- return offset;
- }
- private:
- It it{};
- std::size_t offset{dense_set_placeholder_position};
- };
- template<typename Lhs, typename Rhs>
- [[nodiscard]] constexpr bool operator==(const dense_set_local_iterator<Lhs> &lhs, const dense_set_local_iterator<Rhs> &rhs) noexcept {
- return lhs.index() == rhs.index();
- }
- template<typename Lhs, typename Rhs>
- [[nodiscard]] constexpr bool operator!=(const dense_set_local_iterator<Lhs> &lhs, const dense_set_local_iterator<Rhs> &rhs) noexcept {
- return !(lhs == rhs);
- }
- } // namespace internal
- /*! @endcond */
- /**
- * @brief Associative container for unique objects of a given type.
- *
- * Internally, elements are organized into buckets. Which bucket an element is
- * placed into depends entirely on its hash. Elements with the same hash code
- * appear in the same bucket.
- *
- * @tparam Type Value type of the associative container.
- * @tparam Hash Type of function to use to hash the values.
- * @tparam KeyEqual Type of function to use to compare the values for equality.
- * @tparam Allocator Type of allocator used to manage memory and elements.
- */
- template<typename Type, typename Hash, typename KeyEqual, typename Allocator>
- class dense_set {
- static constexpr float default_threshold = 0.875f;
- static constexpr std::size_t minimum_capacity = 8u;
- static constexpr std::size_t placeholder_position = internal::dense_set_placeholder_position;
- using node_type = std::pair<std::size_t, Type>;
- using alloc_traits = std::allocator_traits<Allocator>;
- static_assert(std::is_same_v<typename alloc_traits::value_type, Type>, "Invalid value type");
- using sparse_container_type = std::vector<std::size_t, typename alloc_traits::template rebind_alloc<std::size_t>>;
- using packed_container_type = std::vector<node_type, typename alloc_traits::template rebind_alloc<node_type>>;
- template<typename Other>
- [[nodiscard]] std::size_t value_to_bucket(const Other &value) const noexcept {
- return fast_mod(static_cast<size_type>(sparse.second()(value)), bucket_count());
- }
- template<typename Other>
- [[nodiscard]] auto constrained_find(const Other &value, const std::size_t bucket) {
- for(auto offset = sparse.first()[bucket]; offset != placeholder_position; offset = packed.first()[offset].first) {
- if(packed.second()(packed.first()[offset].second, value)) {
- return begin() + static_cast<typename iterator::difference_type>(offset);
- }
- }
- return end();
- }
- template<typename Other>
- [[nodiscard]] auto constrained_find(const Other &value, const std::size_t bucket) const {
- for(auto offset = sparse.first()[bucket]; offset != placeholder_position; offset = packed.first()[offset].first) {
- if(packed.second()(packed.first()[offset].second, value)) {
- return cbegin() + static_cast<typename const_iterator::difference_type>(offset);
- }
- }
- return cend();
- }
- template<typename Other>
- [[nodiscard]] auto insert_or_do_nothing(Other &&value) {
- const auto index = value_to_bucket(value);
- if(auto it = constrained_find(value, index); it != end()) {
- return std::make_pair(it, false);
- }
- packed.first().emplace_back(sparse.first()[index], std::forward<Other>(value));
- sparse.first()[index] = packed.first().size() - 1u;
- rehash_if_required();
- return std::make_pair(--end(), true);
- }
- void move_and_pop(const std::size_t pos) {
- if(const auto last = size() - 1u; pos != last) {
- size_type *curr = &sparse.first()[value_to_bucket(packed.first().back().second)];
- packed.first()[pos] = std::move(packed.first().back());
- for(; *curr != last; curr = &packed.first()[*curr].first) {}
- *curr = pos;
- }
- packed.first().pop_back();
- }
- void rehash_if_required() {
- if(const auto bc = bucket_count(); size() > static_cast<size_type>(static_cast<float>(bc) * max_load_factor())) {
- rehash(bc * 2u);
- }
- }
- public:
- /*! @brief Allocator type. */
- using allocator_type = Allocator;
- /*! @brief Key type of the container. */
- using key_type = Type;
- /*! @brief Value type of the container. */
- using value_type = Type;
- /*! @brief Unsigned integer type. */
- using size_type = std::size_t;
- /*! @brief Signed integer type. */
- using difference_type = std::ptrdiff_t;
- /*! @brief Type of function to use to hash the elements. */
- using hasher = Hash;
- /*! @brief Type of function to use to compare the elements for equality. */
- using key_equal = KeyEqual;
- /*! @brief Random access iterator type. */
- using iterator = internal::dense_set_iterator<typename packed_container_type::iterator>;
- /*! @brief Constant random access iterator type. */
- using const_iterator = internal::dense_set_iterator<typename packed_container_type::const_iterator>;
- /*! @brief Reverse iterator type. */
- using reverse_iterator = std::reverse_iterator<iterator>;
- /*! @brief Constant reverse iterator type. */
- using const_reverse_iterator = std::reverse_iterator<const_iterator>;
- /*! @brief Forward iterator type. */
- using local_iterator = internal::dense_set_local_iterator<typename packed_container_type::iterator>;
- /*! @brief Constant forward iterator type. */
- using const_local_iterator = internal::dense_set_local_iterator<typename packed_container_type::const_iterator>;
- /*! @brief Default constructor. */
- dense_set()
- : dense_set{minimum_capacity} {}
- /**
- * @brief Constructs an empty container with a given allocator.
- * @param allocator The allocator to use.
- */
- explicit dense_set(const allocator_type &allocator)
- : dense_set{minimum_capacity, hasher{}, key_equal{}, allocator} {}
- /**
- * @brief Constructs an empty container with a given allocator and user
- * supplied minimal number of buckets.
- * @param cnt Minimal number of buckets.
- * @param allocator The allocator to use.
- */
- dense_set(const size_type cnt, const allocator_type &allocator)
- : dense_set{cnt, hasher{}, key_equal{}, allocator} {}
- /**
- * @brief Constructs an empty container with a given allocator, hash
- * function and user supplied minimal number of buckets.
- * @param cnt Minimal number of buckets.
- * @param hash Hash function to use.
- * @param allocator The allocator to use.
- */
- dense_set(const size_type cnt, const hasher &hash, const allocator_type &allocator)
- : dense_set{cnt, hash, key_equal{}, allocator} {}
- /**
- * @brief Constructs an empty container with a given allocator, hash
- * function, compare function and user supplied minimal number of buckets.
- * @param cnt Minimal number of buckets.
- * @param hash Hash function to use.
- * @param equal Compare function to use.
- * @param allocator The allocator to use.
- */
- explicit dense_set(const size_type cnt, const hasher &hash = hasher{}, const key_equal &equal = key_equal{}, const allocator_type &allocator = allocator_type{})
- : sparse{allocator, hash},
- packed{allocator, equal} {
- rehash(cnt);
- }
- /*! @brief Default copy constructor. */
- dense_set(const dense_set &) = default;
- /**
- * @brief Allocator-extended copy constructor.
- * @param other The instance to copy from.
- * @param allocator The allocator to use.
- */
- dense_set(const dense_set &other, const allocator_type &allocator)
- : sparse{std::piecewise_construct, std::forward_as_tuple(other.sparse.first(), allocator), std::forward_as_tuple(other.sparse.second())},
- packed{std::piecewise_construct, std::forward_as_tuple(other.packed.first(), allocator), std::forward_as_tuple(other.packed.second())},
- threshold{other.threshold} {}
- /*! @brief Default move constructor. */
- dense_set(dense_set &&) noexcept = default;
- /**
- * @brief Allocator-extended move constructor.
- * @param other The instance to move from.
- * @param allocator The allocator to use.
- */
- dense_set(dense_set &&other, const allocator_type &allocator)
- : sparse{std::piecewise_construct, std::forward_as_tuple(std::move(other.sparse.first()), allocator), std::forward_as_tuple(std::move(other.sparse.second()))},
- packed{std::piecewise_construct, std::forward_as_tuple(std::move(other.packed.first()), allocator), std::forward_as_tuple(std::move(other.packed.second()))},
- threshold{other.threshold} {}
- /*! @brief Default destructor. */
- ~dense_set() = default;
- /**
- * @brief Default copy assignment operator.
- * @return This container.
- */
- dense_set &operator=(const dense_set &) = default;
- /**
- * @brief Default move assignment operator.
- * @return This container.
- */
- dense_set &operator=(dense_set &&) noexcept = default;
- /**
- * @brief Exchanges the contents with those of a given container.
- * @param other Container to exchange the content with.
- */
- void swap(dense_set &other) noexcept {
- using std::swap;
- swap(sparse, other.sparse);
- swap(packed, other.packed);
- swap(threshold, other.threshold);
- }
- /**
- * @brief Returns the associated allocator.
- * @return The associated allocator.
- */
- [[nodiscard]] constexpr allocator_type get_allocator() const noexcept {
- return sparse.first().get_allocator();
- }
- /**
- * @brief Returns an iterator to the beginning.
- *
- * If the array is empty, the returned iterator will be equal to `end()`.
- *
- * @return An iterator to the first instance of the internal array.
- */
- [[nodiscard]] const_iterator cbegin() const noexcept {
- return packed.first().begin();
- }
- /*! @copydoc cbegin */
- [[nodiscard]] const_iterator begin() const noexcept {
- return cbegin();
- }
- /*! @copydoc begin */
- [[nodiscard]] iterator begin() noexcept {
- return packed.first().begin();
- }
- /**
- * @brief Returns an iterator to the end.
- * @return An iterator to the element following the last instance of the
- * internal array.
- */
- [[nodiscard]] const_iterator cend() const noexcept {
- return packed.first().end();
- }
- /*! @copydoc cend */
- [[nodiscard]] const_iterator end() const noexcept {
- return cend();
- }
- /*! @copydoc end */
- [[nodiscard]] iterator end() noexcept {
- return packed.first().end();
- }
- /**
- * @brief Returns a reverse iterator to the beginning.
- *
- * If the array is empty, the returned iterator will be equal to `rend()`.
- *
- * @return An iterator to the first instance of the reversed internal array.
- */
- [[nodiscard]] const_reverse_iterator crbegin() const noexcept {
- return std::make_reverse_iterator(cend());
- }
- /*! @copydoc crbegin */
- [[nodiscard]] const_reverse_iterator rbegin() const noexcept {
- return crbegin();
- }
- /*! @copydoc rbegin */
- [[nodiscard]] reverse_iterator rbegin() noexcept {
- return std::make_reverse_iterator(end());
- }
- /**
- * @brief Returns a reverse iterator to the end.
- * @return An iterator to the element following the last instance of the
- * reversed internal array.
- */
- [[nodiscard]] const_reverse_iterator crend() const noexcept {
- return std::make_reverse_iterator(cbegin());
- }
- /*! @copydoc crend */
- [[nodiscard]] const_reverse_iterator rend() const noexcept {
- return crend();
- }
- /*! @copydoc rend */
- [[nodiscard]] reverse_iterator rend() noexcept {
- return std::make_reverse_iterator(begin());
- }
- /**
- * @brief Checks whether a container is empty.
- * @return True if the container is empty, false otherwise.
- */
- [[nodiscard]] bool empty() const noexcept {
- return packed.first().empty();
- }
- /**
- * @brief Returns the number of elements in a container.
- * @return Number of elements in a container.
- */
- [[nodiscard]] size_type size() const noexcept {
- return packed.first().size();
- }
- /**
- * @brief Returns the maximum possible number of elements.
- * @return Maximum possible number of elements.
- */
- [[nodiscard]] size_type max_size() const noexcept {
- return packed.first().max_size();
- }
- /*! @brief Clears the container. */
- void clear() noexcept {
- sparse.first().clear();
- packed.first().clear();
- rehash(0u);
- }
- /**
- * @brief Inserts an element into the container, if it does not exist.
- * @param value An element to insert into the container.
- * @return A pair consisting of an iterator to the inserted element (or to
- * the element that prevented the insertion) and a bool denoting whether the
- * insertion took place.
- */
- std::pair<iterator, bool> insert(const value_type &value) {
- return insert_or_do_nothing(value);
- }
- /*! @copydoc insert */
- std::pair<iterator, bool> insert(value_type &&value) {
- return insert_or_do_nothing(std::move(value));
- }
- /**
- * @brief Inserts elements into the container, if they do not exist.
- * @tparam It Type of input iterator.
- * @param first An iterator to the first element of the range of elements.
- * @param last An iterator past the last element of the range of elements.
- */
- template<typename It>
- void insert(It first, It last) {
- for(; first != last; ++first) {
- insert(*first);
- }
- }
- /**
- * @brief Constructs an element in-place, if it does not exist.
- *
- * The element is also constructed when the container already has the key,
- * in which case the newly constructed object is destroyed immediately.
- *
- * @tparam Args Types of arguments to forward to the constructor of the
- * element.
- * @param args Arguments to forward to the constructor of the element.
- * @return A pair consisting of an iterator to the inserted element (or to
- * the element that prevented the insertion) and a bool denoting whether the
- * insertion took place.
- */
- template<typename... Args>
- std::pair<iterator, bool> emplace(Args &&...args) {
- if constexpr(((sizeof...(Args) == 1u) && ... && std::is_same_v<std::decay_t<Args>, value_type>)) {
- return insert_or_do_nothing(std::forward<Args>(args)...);
- } else {
- auto &node = packed.first().emplace_back(std::piecewise_construct, std::make_tuple(packed.first().size()), std::forward_as_tuple(std::forward<Args>(args)...));
- const auto index = value_to_bucket(node.second);
- if(auto it = constrained_find(node.second, index); it != end()) {
- packed.first().pop_back();
- return std::make_pair(it, false);
- }
- std::swap(node.first, sparse.first()[index]);
- rehash_if_required();
- return std::make_pair(--end(), true);
- }
- }
- /**
- * @brief Removes an element from a given position.
- * @param pos An iterator to the element to remove.
- * @return An iterator following the removed element.
- */
- iterator erase(const_iterator pos) {
- const auto diff = pos - cbegin();
- erase(*pos);
- return begin() + diff;
- }
- /**
- * @brief Removes the given elements from a container.
- * @param first An iterator to the first element of the range of elements.
- * @param last An iterator past the last element of the range of elements.
- * @return An iterator following the last removed element.
- */
- iterator erase(const_iterator first, const_iterator last) {
- const auto dist = first - cbegin();
- for(auto from = last - cbegin(); from != dist; --from) {
- erase(packed.first()[static_cast<size_type>(from) - 1u].second);
- }
- return (begin() + dist);
- }
- /**
- * @brief Removes the element associated with a given value.
- * @param value Value of an element to remove.
- * @return Number of elements removed (either 0 or 1).
- */
- size_type erase(const value_type &value) {
- for(size_type *curr = &sparse.first()[value_to_bucket(value)]; *curr != placeholder_position; curr = &packed.first()[*curr].first) {
- if(packed.second()(packed.first()[*curr].second, value)) {
- const auto index = *curr;
- *curr = packed.first()[*curr].first;
- move_and_pop(index);
- return 1u;
- }
- }
- return 0u;
- }
- /**
- * @brief Returns the number of elements matching a value (either 1 or 0).
- * @param key Key value of an element to search for.
- * @return Number of elements matching the key (either 1 or 0).
- */
- [[nodiscard]] size_type count(const value_type &key) const {
- return find(key) != end();
- }
- /**
- * @brief Returns the number of elements matching a key (either 1 or 0).
- * @tparam Other Type of the key value of an element to search for.
- * @param key Key value of an element to search for.
- * @return Number of elements matching the key (either 1 or 0).
- */
- template<typename Other>
- [[nodiscard]] std::enable_if_t<is_transparent_v<hasher> && is_transparent_v<key_equal>, std::conditional_t<false, Other, size_type>>
- count(const Other &key) const {
- return find(key) != end();
- }
- /**
- * @brief Finds an element with a given value.
- * @param value Value of an element to search for.
- * @return An iterator to an element with the given value. If no such
- * element is found, a past-the-end iterator is returned.
- */
- [[nodiscard]] iterator find(const value_type &value) {
- return constrained_find(value, value_to_bucket(value));
- }
- /*! @copydoc find */
- [[nodiscard]] const_iterator find(const value_type &value) const {
- return constrained_find(value, value_to_bucket(value));
- }
- /**
- * @brief Finds an element that compares _equivalent_ to a given value.
- * @tparam Other Type of an element to search for.
- * @param value Value of an element to search for.
- * @return An iterator to an element with the given value. If no such
- * element is found, a past-the-end iterator is returned.
- */
- template<typename Other>
- [[nodiscard]] std::enable_if_t<is_transparent_v<hasher> && is_transparent_v<key_equal>, std::conditional_t<false, Other, iterator>>
- find(const Other &value) {
- return constrained_find(value, value_to_bucket(value));
- }
- /*! @copydoc find */
- template<typename Other>
- [[nodiscard]] std::enable_if_t<is_transparent_v<hasher> && is_transparent_v<key_equal>, std::conditional_t<false, Other, const_iterator>>
- find(const Other &value) const {
- return constrained_find(value, value_to_bucket(value));
- }
- /**
- * @brief Returns a range containing all elements with a given value.
- * @param value Value of an element to search for.
- * @return A pair of iterators pointing to the first element and past the
- * last element of the range.
- */
- [[nodiscard]] std::pair<iterator, iterator> equal_range(const value_type &value) {
- const auto it = find(value);
- return {it, it + !(it == end())};
- }
- /*! @copydoc equal_range */
- [[nodiscard]] std::pair<const_iterator, const_iterator> equal_range(const value_type &value) const {
- const auto it = find(value);
- return {it, it + !(it == cend())};
- }
- /**
- * @brief Returns a range containing all elements that compare _equivalent_
- * to a given value.
- * @tparam Other Type of an element to search for.
- * @param value Value of an element to search for.
- * @return A pair of iterators pointing to the first element and past the
- * last element of the range.
- */
- template<typename Other>
- [[nodiscard]] std::enable_if_t<is_transparent_v<hasher> && is_transparent_v<key_equal>, std::conditional_t<false, Other, std::pair<iterator, iterator>>>
- equal_range(const Other &value) {
- const auto it = find(value);
- return {it, it + !(it == end())};
- }
- /*! @copydoc equal_range */
- template<typename Other>
- [[nodiscard]] std::enable_if_t<is_transparent_v<hasher> && is_transparent_v<key_equal>, std::conditional_t<false, Other, std::pair<const_iterator, const_iterator>>>
- equal_range(const Other &value) const {
- const auto it = find(value);
- return {it, it + !(it == cend())};
- }
- /**
- * @brief Checks if the container contains an element with a given value.
- * @param value Value of an element to search for.
- * @return True if there is such an element, false otherwise.
- */
- [[nodiscard]] bool contains(const value_type &value) const {
- return (find(value) != cend());
- }
- /**
- * @brief Checks if the container contains an element that compares
- * _equivalent_ to a given value.
- * @tparam Other Type of an element to search for.
- * @param value Value of an element to search for.
- * @return True if there is such an element, false otherwise.
- */
- template<typename Other>
- [[nodiscard]] std::enable_if_t<is_transparent_v<hasher> && is_transparent_v<key_equal>, std::conditional_t<false, Other, bool>>
- contains(const Other &value) const {
- return (find(value) != cend());
- }
- /**
- * @brief Returns an iterator to the beginning of a given bucket.
- * @param index An index of a bucket to access.
- * @return An iterator to the beginning of the given bucket.
- */
- [[nodiscard]] const_local_iterator cbegin(const size_type index) const {
- return {packed.first().begin(), sparse.first()[index]};
- }
- /**
- * @brief Returns an iterator to the beginning of a given bucket.
- * @param index An index of a bucket to access.
- * @return An iterator to the beginning of the given bucket.
- */
- [[nodiscard]] const_local_iterator begin(const size_type index) const {
- return cbegin(index);
- }
- /**
- * @brief Returns an iterator to the beginning of a given bucket.
- * @param index An index of a bucket to access.
- * @return An iterator to the beginning of the given bucket.
- */
- [[nodiscard]] local_iterator begin(const size_type index) {
- return {packed.first().begin(), sparse.first()[index]};
- }
- /**
- * @brief Returns an iterator to the end of a given bucket.
- * @param index An index of a bucket to access.
- * @return An iterator to the end of the given bucket.
- */
- [[nodiscard]] const_local_iterator cend([[maybe_unused]] const size_type index) const {
- return {};
- }
- /**
- * @brief Returns an iterator to the end of a given bucket.
- * @param index An index of a bucket to access.
- * @return An iterator to the end of the given bucket.
- */
- [[nodiscard]] const_local_iterator end(const size_type index) const {
- return cend(index);
- }
- /**
- * @brief Returns an iterator to the end of a given bucket.
- * @param index An index of a bucket to access.
- * @return An iterator to the end of the given bucket.
- */
- [[nodiscard]] local_iterator end([[maybe_unused]] const size_type index) {
- return {};
- }
- /**
- * @brief Returns the number of buckets.
- * @return The number of buckets.
- */
- [[nodiscard]] size_type bucket_count() const {
- return sparse.first().size();
- }
- /**
- * @brief Returns the maximum number of buckets.
- * @return The maximum number of buckets.
- */
- [[nodiscard]] size_type max_bucket_count() const {
- return sparse.first().max_size();
- }
- /**
- * @brief Returns the number of elements in a given bucket.
- * @param index The index of the bucket to examine.
- * @return The number of elements in the given bucket.
- */
- [[nodiscard]] size_type bucket_size(const size_type index) const {
- return static_cast<size_type>(std::distance(begin(index), end(index)));
- }
- /**
- * @brief Returns the bucket for a given element.
- * @param value The value of the element to examine.
- * @return The bucket for the given element.
- */
- [[nodiscard]] size_type bucket(const value_type &value) const {
- return value_to_bucket(value);
- }
- /**
- * @brief Returns the average number of elements per bucket.
- * @return The average number of elements per bucket.
- */
- [[nodiscard]] float load_factor() const {
- return static_cast<float>(size()) / static_cast<float>(bucket_count());
- }
- /**
- * @brief Returns the maximum average number of elements per bucket.
- * @return The maximum average number of elements per bucket.
- */
- [[nodiscard]] float max_load_factor() const {
- return threshold;
- }
- /**
- * @brief Sets the desired maximum average number of elements per bucket.
- * @param value A desired maximum average number of elements per bucket.
- */
- void max_load_factor(const float value) {
- ENTT_ASSERT(value > 0.f, "Invalid load factor");
- threshold = value;
- rehash(0u);
- }
- /**
- * @brief Reserves at least the specified number of buckets and regenerates
- * the hash table.
- * @param cnt New number of buckets.
- */
- void rehash(const size_type cnt) {
- auto value = cnt > minimum_capacity ? cnt : minimum_capacity;
- const auto cap = static_cast<size_type>(static_cast<float>(size()) / max_load_factor());
- value = value > cap ? value : cap;
- if(const auto sz = next_power_of_two(value); sz != bucket_count()) {
- sparse.first().resize(sz);
- for(auto &&elem: sparse.first()) {
- elem = placeholder_position;
- }
- for(size_type pos{}, last = size(); pos < last; ++pos) {
- const auto index = value_to_bucket(packed.first()[pos].second);
- packed.first()[pos].first = std::exchange(sparse.first()[index], pos);
- }
- }
- }
- /**
- * @brief Reserves space for at least the specified number of elements and
- * regenerates the hash table.
- * @param cnt New number of elements.
- */
- void reserve(const size_type cnt) {
- packed.first().reserve(cnt);
- rehash(static_cast<size_type>(std::ceil(static_cast<float>(cnt) / max_load_factor())));
- }
- /**
- * @brief Returns the function used to hash the elements.
- * @return The function used to hash the elements.
- */
- [[nodiscard]] hasher hash_function() const {
- return sparse.second();
- }
- /**
- * @brief Returns the function used to compare elements for equality.
- * @return The function used to compare elements for equality.
- */
- [[nodiscard]] key_equal key_eq() const {
- return packed.second();
- }
- private:
- compressed_pair<sparse_container_type, hasher> sparse;
- compressed_pair<packed_container_type, key_equal> packed;
- float threshold{default_threshold};
- };
- } // namespace entt
- #endif
- // #include "../core/compressed_pair.hpp"
- #ifndef ENTT_CORE_COMPRESSED_PAIR_HPP
- #define ENTT_CORE_COMPRESSED_PAIR_HPP
- #include <cstddef>
- #include <tuple>
- #include <type_traits>
- #include <utility>
- // #include "fwd.hpp"
- #ifndef ENTT_CORE_FWD_HPP
- #define ENTT_CORE_FWD_HPP
- #include <cstddef>
- #include <cstdint>
- // #include "../config/config.h"
- namespace entt {
- /*! @brief Possible modes of an any object. */
- enum class any_policy : std::uint8_t {
- /*! @brief Default mode, no element available. */
- empty,
- /*! @brief Owning mode, dynamically allocated element. */
- dynamic,
- /*! @brief Owning mode, embedded element. */
- embedded,
- /*! @brief Aliasing mode, non-const reference. */
- ref,
- /*! @brief Const aliasing mode, const reference. */
- cref
- };
- // NOLINTNEXTLINE(cppcoreguidelines-avoid-c-arrays, modernize-avoid-c-arrays)
- template<std::size_t Len = sizeof(double[2]), std::size_t = alignof(double[2])>
- class basic_any;
- /*! @brief Alias declaration for type identifiers. */
- using id_type = ENTT_ID_TYPE;
- /*! @brief Alias declaration for the most common use case. */
- using any = basic_any<>;
- template<typename, typename>
- class compressed_pair;
- template<typename>
- class basic_hashed_string;
- /*! @brief Aliases for common character types. */
- using hashed_string = basic_hashed_string<char>;
- /*! @brief Aliases for common character types. */
- using hashed_wstring = basic_hashed_string<wchar_t>;
- // NOLINTNEXTLINE(bugprone-forward-declaration-namespace)
- struct type_info;
- } // namespace entt
- #endif
- // #include "type_traits.hpp"
- #ifndef ENTT_CORE_TYPE_TRAITS_HPP
- #define ENTT_CORE_TYPE_TRAITS_HPP
- #include <cstddef>
- #include <iterator>
- #include <tuple>
- #include <type_traits>
- #include <utility>
- // #include "../config/config.h"
- // #include "fwd.hpp"
- namespace entt {
- /**
- * @brief Utility class to disambiguate overloaded functions.
- * @tparam N Number of choices available.
- */
- template<std::size_t N>
- struct choice_t
- // unfortunately, doxygen cannot parse such a construct
- : /*! @cond TURN_OFF_DOXYGEN */ choice_t<N - 1> /*! @endcond */
- {};
- /*! @copybrief choice_t */
- template<>
- struct choice_t<0> {};
- /**
- * @brief Variable template for the choice trick.
- * @tparam N Number of choices available.
- */
- template<std::size_t N>
- inline constexpr choice_t<N> choice{};
- /**
- * @brief Identity type trait.
- *
- * Useful to establish non-deduced contexts in template argument deduction
- * (waiting for C++20) or to provide types through function arguments.
- *
- * @tparam Type A type.
- */
- template<typename Type>
- struct type_identity {
- /*! @brief Identity type. */
- using type = Type;
- };
- /**
- * @brief Helper type.
- * @tparam Type A type.
- */
- template<typename Type>
- using type_identity_t = typename type_identity<Type>::type;
- /**
- * @brief A type-only `sizeof` wrapper that returns 0 where `sizeof` complains.
- * @tparam Type The type of which to return the size.
- */
- template<typename Type, typename = void>
- struct size_of: std::integral_constant<std::size_t, 0u> {};
- /*! @copydoc size_of */
- template<typename Type>
- struct size_of<Type, std::void_t<decltype(sizeof(Type))>>
- // NOLINTNEXTLINE(bugprone-sizeof-expression)
- : std::integral_constant<std::size_t, sizeof(Type)> {};
- /**
- * @brief Helper variable template.
- * @tparam Type The type of which to return the size.
- */
- template<typename Type>
- inline constexpr std::size_t size_of_v = size_of<Type>::value;
- /**
- * @brief Using declaration to be used to _repeat_ the same type a number of
- * times equal to the size of a given parameter pack.
- * @tparam Type A type to repeat.
- */
- template<typename Type, typename>
- using unpack_as_type = Type;
- /**
- * @brief Helper variable template to be used to _repeat_ the same value a
- * number of times equal to the size of a given parameter pack.
- * @tparam Value A value to repeat.
- */
- template<auto Value, typename>
- inline constexpr auto unpack_as_value = Value;
- /**
- * @brief Wraps a static constant.
- * @tparam Value A static constant.
- */
- template<auto Value>
- using integral_constant = std::integral_constant<decltype(Value), Value>;
- /**
- * @brief Alias template to facilitate the creation of named values.
- * @tparam Value A constant value at least convertible to `id_type`.
- */
- template<id_type Value>
- using tag = integral_constant<Value>;
- /**
- * @brief A class to use to push around lists of types, nothing more.
- * @tparam Type Types provided by the type list.
- */
- template<typename... Type>
- struct type_list {
- /*! @brief Type list type. */
- using type = type_list;
- /*! @brief Compile-time number of elements in the type list. */
- static constexpr auto size = sizeof...(Type);
- };
- /*! @brief Primary template isn't defined on purpose. */
- template<std::size_t, typename>
- struct type_list_element;
- /**
- * @brief Provides compile-time indexed access to the types of a type list.
- * @tparam Index Index of the type to return.
- * @tparam First First type provided by the type list.
- * @tparam Other Other types provided by the type list.
- */
- template<std::size_t Index, typename First, typename... Other>
- struct type_list_element<Index, type_list<First, Other...>>
- : type_list_element<Index - 1u, type_list<Other...>> {};
- /**
- * @brief Provides compile-time indexed access to the types of a type list.
- * @tparam First First type provided by the type list.
- * @tparam Other Other types provided by the type list.
- */
- template<typename First, typename... Other>
- struct type_list_element<0u, type_list<First, Other...>> {
- /*! @brief Searched type. */
- using type = First;
- };
- /**
- * @brief Helper type.
- * @tparam Index Index of the type to return.
- * @tparam List Type list to search into.
- */
- template<std::size_t Index, typename List>
- using type_list_element_t = typename type_list_element<Index, List>::type;
- /*! @brief Primary template isn't defined on purpose. */
- template<typename, typename>
- struct type_list_index;
- /**
- * @brief Provides compile-time type access to the types of a type list.
- * @tparam Type Type to look for and for which to return the index.
- * @tparam First First type provided by the type list.
- * @tparam Other Other types provided by the type list.
- */
- template<typename Type, typename First, typename... Other>
- struct type_list_index<Type, type_list<First, Other...>> {
- /*! @brief Unsigned integer type. */
- using value_type = std::size_t;
- /*! @brief Compile-time position of the given type in the sublist. */
- static constexpr value_type value = 1u + type_list_index<Type, type_list<Other...>>::value;
- };
- /**
- * @brief Provides compile-time type access to the types of a type list.
- * @tparam Type Type to look for and for which to return the index.
- * @tparam Other Other types provided by the type list.
- */
- template<typename Type, typename... Other>
- struct type_list_index<Type, type_list<Type, Other...>> {
- static_assert(type_list_index<Type, type_list<Other...>>::value == sizeof...(Other), "Non-unique type");
- /*! @brief Unsigned integer type. */
- using value_type = std::size_t;
- /*! @brief Compile-time position of the given type in the sublist. */
- static constexpr value_type value = 0u;
- };
- /**
- * @brief Provides compile-time type access to the types of a type list.
- * @tparam Type Type to look for and for which to return the index.
- */
- template<typename Type>
- struct type_list_index<Type, type_list<>> {
- /*! @brief Unsigned integer type. */
- using value_type = std::size_t;
- /*! @brief Compile-time position of the given type in the sublist. */
- static constexpr value_type value = 0u;
- };
- /**
- * @brief Helper variable template.
- * @tparam List Type list.
- * @tparam Type Type to look for and for which to return the index.
- */
- template<typename Type, typename List>
- inline constexpr std::size_t type_list_index_v = type_list_index<Type, List>::value;
- /**
- * @brief Concatenates multiple type lists.
- * @tparam Type Types provided by the first type list.
- * @tparam Other Types provided by the second type list.
- * @return A type list composed by the types of both the type lists.
- */
- template<typename... Type, typename... Other>
- constexpr type_list<Type..., Other...> operator+(type_list<Type...>, type_list<Other...>) {
- return {};
- }
- /*! @brief Primary template isn't defined on purpose. */
- template<typename...>
- struct type_list_cat;
- /*! @brief Concatenates multiple type lists. */
- template<>
- struct type_list_cat<> {
- /*! @brief A type list composed by the types of all the type lists. */
- using type = type_list<>;
- };
- /**
- * @brief Concatenates multiple type lists.
- * @tparam Type Types provided by the first type list.
- * @tparam Other Types provided by the second type list.
- * @tparam List Other type lists, if any.
- */
- template<typename... Type, typename... Other, typename... List>
- struct type_list_cat<type_list<Type...>, type_list<Other...>, List...> {
- /*! @brief A type list composed by the types of all the type lists. */
- using type = typename type_list_cat<type_list<Type..., Other...>, List...>::type;
- };
- /**
- * @brief Concatenates multiple type lists.
- * @tparam Type Types provided by the type list.
- */
- template<typename... Type>
- struct type_list_cat<type_list<Type...>> {
- /*! @brief A type list composed by the types of all the type lists. */
- using type = type_list<Type...>;
- };
- /**
- * @brief Helper type.
- * @tparam List Type lists to concatenate.
- */
- template<typename... List>
- using type_list_cat_t = typename type_list_cat<List...>::type;
- /*! @cond TURN_OFF_DOXYGEN */
- namespace internal {
- template<typename...>
- struct type_list_unique;
- template<typename First, typename... Other, typename... Type>
- struct type_list_unique<type_list<First, Other...>, Type...>
- : std::conditional_t<(std::is_same_v<First, Type> || ...), type_list_unique<type_list<Other...>, Type...>, type_list_unique<type_list<Other...>, Type..., First>> {};
- template<typename... Type>
- struct type_list_unique<type_list<>, Type...> {
- using type = type_list<Type...>;
- };
- } // namespace internal
- /*! @endcond */
- /**
- * @brief Removes duplicates types from a type list.
- * @tparam List Type list.
- */
- template<typename List>
- struct type_list_unique {
- /*! @brief A type list without duplicate types. */
- using type = typename internal::type_list_unique<List>::type;
- };
- /**
- * @brief Helper type.
- * @tparam List Type list.
- */
- template<typename List>
- using type_list_unique_t = typename type_list_unique<List>::type;
- /**
- * @brief Provides the member constant `value` to true if a type list contains a
- * given type, false otherwise.
- * @tparam List Type list.
- * @tparam Type Type to look for.
- */
- template<typename List, typename Type>
- struct type_list_contains;
- /**
- * @copybrief type_list_contains
- * @tparam Type Types provided by the type list.
- * @tparam Other Type to look for.
- */
- template<typename... Type, typename Other>
- struct type_list_contains<type_list<Type...>, Other>
- : std::bool_constant<(std::is_same_v<Type, Other> || ...)> {};
- /**
- * @brief Helper variable template.
- * @tparam List Type list.
- * @tparam Type Type to look for.
- */
- template<typename List, typename Type>
- inline constexpr bool type_list_contains_v = type_list_contains<List, Type>::value;
- /*! @brief Primary template isn't defined on purpose. */
- template<typename...>
- struct type_list_diff;
- /**
- * @brief Computes the difference between two type lists.
- * @tparam Type Types provided by the first type list.
- * @tparam Other Types provided by the second type list.
- */
- template<typename... Type, typename... Other>
- struct type_list_diff<type_list<Type...>, type_list<Other...>> {
- /*! @brief A type list that is the difference between the two type lists. */
- using type = type_list_cat_t<std::conditional_t<type_list_contains_v<type_list<Other...>, Type>, type_list<>, type_list<Type>>...>;
- };
- /**
- * @brief Helper type.
- * @tparam List Type lists between which to compute the difference.
- */
- template<typename... List>
- using type_list_diff_t = typename type_list_diff<List...>::type;
- /*! @brief Primary template isn't defined on purpose. */
- template<typename, template<typename...> class>
- struct type_list_transform;
- /**
- * @brief Applies a given _function_ to a type list and generate a new list.
- * @tparam Type Types provided by the type list.
- * @tparam Op Unary operation as template class with a type member named `type`.
- */
- template<typename... Type, template<typename...> class Op>
- struct type_list_transform<type_list<Type...>, Op> {
- /*! @brief Resulting type list after applying the transform function. */
- // NOLINTNEXTLINE(modernize-type-traits)
- using type = type_list<typename Op<Type>::type...>;
- };
- /**
- * @brief Helper type.
- * @tparam List Type list.
- * @tparam Op Unary operation as template class with a type member named `type`.
- */
- template<typename List, template<typename...> class Op>
- using type_list_transform_t = typename type_list_transform<List, Op>::type;
- /**
- * @brief A class to use to push around lists of constant values, nothing more.
- * @tparam Value Values provided by the value list.
- */
- template<auto... Value>
- struct value_list {
- /*! @brief Value list type. */
- using type = value_list;
- /*! @brief Compile-time number of elements in the value list. */
- static constexpr auto size = sizeof...(Value);
- };
- /*! @brief Primary template isn't defined on purpose. */
- template<std::size_t, typename>
- struct value_list_element;
- /**
- * @brief Provides compile-time indexed access to the values of a value list.
- * @tparam Index Index of the value to return.
- * @tparam Value First value provided by the value list.
- * @tparam Other Other values provided by the value list.
- */
- template<std::size_t Index, auto Value, auto... Other>
- struct value_list_element<Index, value_list<Value, Other...>>
- : value_list_element<Index - 1u, value_list<Other...>> {};
- /**
- * @brief Provides compile-time indexed access to the types of a type list.
- * @tparam Value First value provided by the value list.
- * @tparam Other Other values provided by the value list.
- */
- template<auto Value, auto... Other>
- struct value_list_element<0u, value_list<Value, Other...>> {
- /*! @brief Searched type. */
- using type = decltype(Value);
- /*! @brief Searched value. */
- static constexpr auto value = Value;
- };
- /**
- * @brief Helper type.
- * @tparam Index Index of the type to return.
- * @tparam List Value list to search into.
- */
- template<std::size_t Index, typename List>
- using value_list_element_t = typename value_list_element<Index, List>::type;
- /**
- * @brief Helper type.
- * @tparam Index Index of the value to return.
- * @tparam List Value list to search into.
- */
- template<std::size_t Index, typename List>
- inline constexpr auto value_list_element_v = value_list_element<Index, List>::value;
- /*! @brief Primary template isn't defined on purpose. */
- template<auto, typename>
- struct value_list_index;
- /**
- * @brief Provides compile-time type access to the values of a value list.
- * @tparam Value Value to look for and for which to return the index.
- * @tparam First First value provided by the value list.
- * @tparam Other Other values provided by the value list.
- */
- template<auto Value, auto First, auto... Other>
- struct value_list_index<Value, value_list<First, Other...>> {
- /*! @brief Unsigned integer type. */
- using value_type = std::size_t;
- /*! @brief Compile-time position of the given value in the sublist. */
- static constexpr value_type value = 1u + value_list_index<Value, value_list<Other...>>::value;
- };
- /**
- * @brief Provides compile-time type access to the values of a value list.
- * @tparam Value Value to look for and for which to return the index.
- * @tparam Other Other values provided by the value list.
- */
- template<auto Value, auto... Other>
- struct value_list_index<Value, value_list<Value, Other...>> {
- static_assert(value_list_index<Value, value_list<Other...>>::value == sizeof...(Other), "Non-unique type");
- /*! @brief Unsigned integer type. */
- using value_type = std::size_t;
- /*! @brief Compile-time position of the given value in the sublist. */
- static constexpr value_type value = 0u;
- };
- /**
- * @brief Provides compile-time type access to the values of a value list.
- * @tparam Value Value to look for and for which to return the index.
- */
- template<auto Value>
- struct value_list_index<Value, value_list<>> {
- /*! @brief Unsigned integer type. */
- using value_type = std::size_t;
- /*! @brief Compile-time position of the given type in the sublist. */
- static constexpr value_type value = 0u;
- };
- /**
- * @brief Helper variable template.
- * @tparam List Value list.
- * @tparam Value Value to look for and for which to return the index.
- */
- template<auto Value, typename List>
- inline constexpr std::size_t value_list_index_v = value_list_index<Value, List>::value;
- /**
- * @brief Concatenates multiple value lists.
- * @tparam Value Values provided by the first value list.
- * @tparam Other Values provided by the second value list.
- * @return A value list composed by the values of both the value lists.
- */
- template<auto... Value, auto... Other>
- constexpr value_list<Value..., Other...> operator+(value_list<Value...>, value_list<Other...>) {
- return {};
- }
- /*! @brief Primary template isn't defined on purpose. */
- template<typename...>
- struct value_list_cat;
- /*! @brief Concatenates multiple value lists. */
- template<>
- struct value_list_cat<> {
- /*! @brief A value list composed by the values of all the value lists. */
- using type = value_list<>;
- };
- /**
- * @brief Concatenates multiple value lists.
- * @tparam Value Values provided by the first value list.
- * @tparam Other Values provided by the second value list.
- * @tparam List Other value lists, if any.
- */
- template<auto... Value, auto... Other, typename... List>
- struct value_list_cat<value_list<Value...>, value_list<Other...>, List...> {
- /*! @brief A value list composed by the values of all the value lists. */
- using type = typename value_list_cat<value_list<Value..., Other...>, List...>::type;
- };
- /**
- * @brief Concatenates multiple value lists.
- * @tparam Value Values provided by the value list.
- */
- template<auto... Value>
- struct value_list_cat<value_list<Value...>> {
- /*! @brief A value list composed by the values of all the value lists. */
- using type = value_list<Value...>;
- };
- /**
- * @brief Helper type.
- * @tparam List Value lists to concatenate.
- */
- template<typename... List>
- using value_list_cat_t = typename value_list_cat<List...>::type;
- /*! @brief Primary template isn't defined on purpose. */
- template<typename>
- struct value_list_unique;
- /**
- * @brief Removes duplicates values from a value list.
- * @tparam Value One of the values provided by the given value list.
- * @tparam Other The other values provided by the given value list.
- */
- template<auto Value, auto... Other>
- struct value_list_unique<value_list<Value, Other...>> {
- /*! @brief A value list without duplicate types. */
- using type = std::conditional_t<
- ((Value == Other) || ...),
- typename value_list_unique<value_list<Other...>>::type,
- value_list_cat_t<value_list<Value>, typename value_list_unique<value_list<Other...>>::type>>;
- };
- /*! @brief Removes duplicates values from a value list. */
- template<>
- struct value_list_unique<value_list<>> {
- /*! @brief A value list without duplicate types. */
- using type = value_list<>;
- };
- /**
- * @brief Helper type.
- * @tparam Type A value list.
- */
- template<typename Type>
- using value_list_unique_t = typename value_list_unique<Type>::type;
- /**
- * @brief Provides the member constant `value` to true if a value list contains
- * a given value, false otherwise.
- * @tparam List Value list.
- * @tparam Value Value to look for.
- */
- template<typename List, auto Value>
- struct value_list_contains;
- /**
- * @copybrief value_list_contains
- * @tparam Value Values provided by the value list.
- * @tparam Other Value to look for.
- */
- template<auto... Value, auto Other>
- struct value_list_contains<value_list<Value...>, Other>
- : std::bool_constant<((Value == Other) || ...)> {};
- /**
- * @brief Helper variable template.
- * @tparam List Value list.
- * @tparam Value Value to look for.
- */
- template<typename List, auto Value>
- inline constexpr bool value_list_contains_v = value_list_contains<List, Value>::value;
- /*! @brief Primary template isn't defined on purpose. */
- template<typename...>
- struct value_list_diff;
- /**
- * @brief Computes the difference between two value lists.
- * @tparam Value Values provided by the first value list.
- * @tparam Other Values provided by the second value list.
- */
- template<auto... Value, auto... Other>
- struct value_list_diff<value_list<Value...>, value_list<Other...>> {
- /*! @brief A value list that is the difference between the two value lists. */
- using type = value_list_cat_t<std::conditional_t<value_list_contains_v<value_list<Other...>, Value>, value_list<>, value_list<Value>>...>;
- };
- /**
- * @brief Helper type.
- * @tparam List Value lists between which to compute the difference.
- */
- template<typename... List>
- using value_list_diff_t = typename value_list_diff<List...>::type;
- /*! @brief Same as std::is_invocable, but with tuples. */
- template<typename, typename>
- struct is_applicable: std::false_type {};
- /**
- * @copybrief is_applicable
- * @tparam Func A valid function type.
- * @tparam Tuple Tuple-like type.
- * @tparam Args The list of arguments to use to probe the function type.
- */
- template<typename Func, template<typename...> class Tuple, typename... Args>
- struct is_applicable<Func, Tuple<Args...>>: std::is_invocable<Func, Args...> {};
- /**
- * @copybrief is_applicable
- * @tparam Func A valid function type.
- * @tparam Tuple Tuple-like type.
- * @tparam Args The list of arguments to use to probe the function type.
- */
- template<typename Func, template<typename...> class Tuple, typename... Args>
- struct is_applicable<Func, const Tuple<Args...>>: std::is_invocable<Func, Args...> {};
- /**
- * @brief Helper variable template.
- * @tparam Func A valid function type.
- * @tparam Args The list of arguments to use to probe the function type.
- */
- template<typename Func, typename Args>
- inline constexpr bool is_applicable_v = is_applicable<Func, Args>::value;
- /*! @brief Same as std::is_invocable_r, but with tuples for arguments. */
- template<typename, typename, typename>
- struct is_applicable_r: std::false_type {};
- /**
- * @copybrief is_applicable_r
- * @tparam Ret The type to which the return type of the function should be
- * convertible.
- * @tparam Func A valid function type.
- * @tparam Args The list of arguments to use to probe the function type.
- */
- template<typename Ret, typename Func, typename... Args>
- struct is_applicable_r<Ret, Func, std::tuple<Args...>>: std::is_invocable_r<Ret, Func, Args...> {};
- /**
- * @brief Helper variable template.
- * @tparam Ret The type to which the return type of the function should be
- * convertible.
- * @tparam Func A valid function type.
- * @tparam Args The list of arguments to use to probe the function type.
- */
- template<typename Ret, typename Func, typename Args>
- inline constexpr bool is_applicable_r_v = is_applicable_r<Ret, Func, Args>::value;
- /**
- * @brief Provides the member constant `value` to true if a given type is
- * complete, false otherwise.
- * @tparam Type The type to test.
- */
- template<typename Type, typename = void>
- struct is_complete: std::false_type {};
- /*! @copydoc is_complete */
- template<typename Type>
- struct is_complete<Type, std::void_t<decltype(sizeof(Type))>>: std::true_type {};
- /**
- * @brief Helper variable template.
- * @tparam Type The type to test.
- */
- template<typename Type>
- inline constexpr bool is_complete_v = is_complete<Type>::value;
- /**
- * @brief Provides the member constant `value` to true if a given type is an
- * iterator, false otherwise.
- * @tparam Type The type to test.
- */
- template<typename Type, typename = void>
- struct is_iterator: std::false_type {};
- /*! @cond TURN_OFF_DOXYGEN */
- namespace internal {
- template<typename, typename = void>
- struct has_iterator_category: std::false_type {};
- template<typename Type>
- struct has_iterator_category<Type, std::void_t<typename std::iterator_traits<Type>::iterator_category>>: std::true_type {};
- } // namespace internal
- /*! @endcond */
- /*! @copydoc is_iterator */
- template<typename Type>
- struct is_iterator<Type, std::enable_if_t<!std::is_void_v<std::remove_const_t<std::remove_pointer_t<Type>>>>>
- : internal::has_iterator_category<Type> {};
- /**
- * @brief Helper variable template.
- * @tparam Type The type to test.
- */
- template<typename Type>
- inline constexpr bool is_iterator_v = is_iterator<Type>::value;
- /**
- * @brief Provides the member constant `value` to true if a given type is both
- * an empty and non-final class, false otherwise.
- * @tparam Type The type to test
- */
- template<typename Type>
- struct is_ebco_eligible
- : std::bool_constant<std::is_empty_v<Type> && !std::is_final_v<Type>> {};
- /**
- * @brief Helper variable template.
- * @tparam Type The type to test.
- */
- template<typename Type>
- inline constexpr bool is_ebco_eligible_v = is_ebco_eligible<Type>::value;
- /**
- * @brief Provides the member constant `value` to true if `Type::is_transparent`
- * is valid and denotes a type, false otherwise.
- * @tparam Type The type to test.
- */
- template<typename Type, typename = void>
- struct is_transparent: std::false_type {};
- /*! @copydoc is_transparent */
- template<typename Type>
- struct is_transparent<Type, std::void_t<typename Type::is_transparent>>: std::true_type {};
- /**
- * @brief Helper variable template.
- * @tparam Type The type to test.
- */
- template<typename Type>
- inline constexpr bool is_transparent_v = is_transparent<Type>::value;
- /*! @cond TURN_OFF_DOXYGEN */
- namespace internal {
- template<typename, typename = void>
- struct has_tuple_size_value: std::false_type {};
- template<typename Type>
- struct has_tuple_size_value<Type, std::void_t<decltype(std::tuple_size<const Type>::value)>>: std::true_type {};
- template<typename, typename = void>
- struct has_value_type: std::false_type {};
- template<typename Type>
- struct has_value_type<Type, std::void_t<typename Type::value_type>>: std::true_type {};
- template<typename>
- [[nodiscard]] constexpr bool dispatch_is_equality_comparable();
- template<typename Type, std::size_t... Index>
- [[nodiscard]] constexpr bool unpack_maybe_equality_comparable(std::index_sequence<Index...>) {
- return (dispatch_is_equality_comparable<std::tuple_element_t<Index, Type>>() && ...);
- }
- template<typename>
- [[nodiscard]] constexpr bool maybe_equality_comparable(char) {
- return false;
- }
- template<typename Type>
- [[nodiscard]] constexpr auto maybe_equality_comparable(int) -> decltype(std::declval<Type>() == std::declval<Type>()) {
- return true;
- }
- template<typename Type>
- [[nodiscard]] constexpr bool dispatch_is_equality_comparable() {
- // NOLINTBEGIN(modernize-use-transparent-functors)
- if constexpr(std::is_array_v<Type>) {
- return false;
- } else if constexpr(is_complete_v<std::tuple_size<std::remove_const_t<Type>>>) {
- if constexpr(has_tuple_size_value<Type>::value) {
- return maybe_equality_comparable<Type>(0) && unpack_maybe_equality_comparable<Type>(std::make_index_sequence<std::tuple_size<Type>::value>{});
- } else {
- return maybe_equality_comparable<Type>(0);
- }
- } else if constexpr(has_value_type<Type>::value) {
- if constexpr(is_iterator_v<Type> || std::is_same_v<typename Type::value_type, Type> || dispatch_is_equality_comparable<typename Type::value_type>()) {
- return maybe_equality_comparable<Type>(0);
- } else {
- return false;
- }
- } else {
- return maybe_equality_comparable<Type>(0);
- }
- // NOLINTEND(modernize-use-transparent-functors)
- }
- } // namespace internal
- /*! @endcond */
- /**
- * @brief Provides the member constant `value` to true if a given type is
- * equality comparable, false otherwise.
- * @tparam Type The type to test.
- */
- template<typename Type>
- struct is_equality_comparable: std::bool_constant<internal::dispatch_is_equality_comparable<Type>()> {};
- /*! @copydoc is_equality_comparable */
- template<typename Type>
- struct is_equality_comparable<const Type>: is_equality_comparable<Type> {};
- /**
- * @brief Helper variable template.
- * @tparam Type The type to test.
- */
- template<typename Type>
- inline constexpr bool is_equality_comparable_v = is_equality_comparable<Type>::value;
- /**
- * @brief Transcribes the constness of a type to another type.
- * @tparam To The type to which to transcribe the constness.
- * @tparam From The type from which to transcribe the constness.
- */
- template<typename To, typename From>
- struct constness_as {
- /*! @brief The type resulting from the transcription of the constness. */
- using type = std::remove_const_t<To>;
- };
- /*! @copydoc constness_as */
- template<typename To, typename From>
- struct constness_as<To, const From> {
- /*! @brief The type resulting from the transcription of the constness. */
- using type = const To;
- };
- /**
- * @brief Alias template to facilitate the transcription of the constness.
- * @tparam To The type to which to transcribe the constness.
- * @tparam From The type from which to transcribe the constness.
- */
- template<typename To, typename From>
- using constness_as_t = typename constness_as<To, From>::type;
- /**
- * @brief Extracts the class of a non-static member object or function.
- * @tparam Member A pointer to a non-static member object or function.
- */
- template<typename Member>
- class member_class {
- static_assert(std::is_member_pointer_v<Member>, "Invalid pointer type to non-static member object or function");
- template<typename Class, typename Ret, typename... Args>
- static Class *clazz(Ret (Class::*)(Args...));
- template<typename Class, typename Ret, typename... Args>
- static Class *clazz(Ret (Class::*)(Args...) const);
- template<typename Class, typename Type>
- static Class *clazz(Type Class::*);
- public:
- /*! @brief The class of the given non-static member object or function. */
- using type = std::remove_pointer_t<decltype(clazz(std::declval<Member>()))>;
- };
- /**
- * @brief Helper type.
- * @tparam Member A pointer to a non-static member object or function.
- */
- template<typename Member>
- using member_class_t = typename member_class<Member>::type;
- /**
- * @brief Extracts the n-th argument of a _callable_ type.
- * @tparam Index The index of the argument to extract.
- * @tparam Candidate A valid _callable_ type.
- */
- template<std::size_t Index, typename Candidate>
- class nth_argument {
- template<typename Ret, typename... Args>
- static constexpr type_list<Args...> pick_up(Ret (*)(Args...));
- template<typename Ret, typename Class, typename... Args>
- static constexpr type_list<Args...> pick_up(Ret (Class ::*)(Args...));
- template<typename Ret, typename Class, typename... Args>
- static constexpr type_list<Args...> pick_up(Ret (Class ::*)(Args...) const);
- template<typename Type, typename Class>
- static constexpr type_list<Type> pick_up(Type Class ::*);
- template<typename Type>
- static constexpr decltype(pick_up(&Type::operator())) pick_up(Type &&);
- public:
- /*! @brief N-th argument of the _callable_ type. */
- using type = type_list_element_t<Index, decltype(pick_up(std::declval<Candidate>()))>;
- };
- /**
- * @brief Helper type.
- * @tparam Index The index of the argument to extract.
- * @tparam Candidate A valid function, member function or data member type.
- */
- template<std::size_t Index, typename Candidate>
- using nth_argument_t = typename nth_argument<Index, Candidate>::type;
- } // namespace entt
- template<typename... Type>
- struct std::tuple_size<entt::type_list<Type...>>: std::integral_constant<std::size_t, entt::type_list<Type...>::size> {};
- template<std::size_t Index, typename... Type>
- struct std::tuple_element<Index, entt::type_list<Type...>>: entt::type_list_element<Index, entt::type_list<Type...>> {};
- template<auto... Value>
- struct std::tuple_size<entt::value_list<Value...>>: std::integral_constant<std::size_t, entt::value_list<Value...>::size> {};
- template<std::size_t Index, auto... Value>
- struct std::tuple_element<Index, entt::value_list<Value...>>: entt::value_list_element<Index, entt::value_list<Value...>> {};
- #endif
- namespace entt {
- /*! @cond TURN_OFF_DOXYGEN */
- namespace internal {
- template<typename Type, std::size_t, typename = void>
- struct compressed_pair_element {
- using reference = Type &;
- using const_reference = const Type &;
- template<typename Dummy = Type, typename = std::enable_if_t<std::is_default_constructible_v<Dummy>>>
- // NOLINTNEXTLINE(modernize-use-equals-default)
- constexpr compressed_pair_element() noexcept(std::is_nothrow_default_constructible_v<Type>) {}
- template<typename Arg, typename = std::enable_if_t<!std::is_same_v<std::remove_const_t<std::remove_reference_t<Arg>>, compressed_pair_element>>>
- constexpr compressed_pair_element(Arg &&arg) noexcept(std::is_nothrow_constructible_v<Type, Arg>)
- : value{std::forward<Arg>(arg)} {}
- template<typename... Args, std::size_t... Index>
- constexpr compressed_pair_element(std::tuple<Args...> args, std::index_sequence<Index...>) noexcept(std::is_nothrow_constructible_v<Type, Args...>)
- : value{std::forward<Args>(std::get<Index>(args))...} {}
- [[nodiscard]] constexpr reference get() noexcept {
- return value;
- }
- [[nodiscard]] constexpr const_reference get() const noexcept {
- return value;
- }
- private:
- Type value{};
- };
- template<typename Type, std::size_t Tag>
- struct compressed_pair_element<Type, Tag, std::enable_if_t<is_ebco_eligible_v<Type>>>: Type {
- using reference = Type &;
- using const_reference = const Type &;
- using base_type = Type;
- template<typename Dummy = Type, typename = std::enable_if_t<std::is_default_constructible_v<Dummy>>>
- constexpr compressed_pair_element() noexcept(std::is_nothrow_default_constructible_v<base_type>)
- : base_type{} {}
- template<typename Arg, typename = std::enable_if_t<!std::is_same_v<std::remove_const_t<std::remove_reference_t<Arg>>, compressed_pair_element>>>
- constexpr compressed_pair_element(Arg &&arg) noexcept(std::is_nothrow_constructible_v<base_type, Arg>)
- : base_type{std::forward<Arg>(arg)} {}
- template<typename... Args, std::size_t... Index>
- constexpr compressed_pair_element(std::tuple<Args...> args, std::index_sequence<Index...>) noexcept(std::is_nothrow_constructible_v<base_type, Args...>)
- : base_type{std::forward<Args>(std::get<Index>(args))...} {}
- [[nodiscard]] constexpr reference get() noexcept {
- return *this;
- }
- [[nodiscard]] constexpr const_reference get() const noexcept {
- return *this;
- }
- };
- } // namespace internal
- /*! @endcond */
- /**
- * @brief A compressed pair.
- *
- * A pair that exploits the _Empty Base Class Optimization_ (or _EBCO_) to
- * reduce its final size to a minimum.
- *
- * @tparam First The type of the first element that the pair stores.
- * @tparam Second The type of the second element that the pair stores.
- */
- template<typename First, typename Second>
- class compressed_pair final
- : internal::compressed_pair_element<First, 0u>,
- internal::compressed_pair_element<Second, 1u> {
- using first_base = internal::compressed_pair_element<First, 0u>;
- using second_base = internal::compressed_pair_element<Second, 1u>;
- public:
- /*! @brief The type of the first element that the pair stores. */
- using first_type = First;
- /*! @brief The type of the second element that the pair stores. */
- using second_type = Second;
- /**
- * @brief Default constructor, conditionally enabled.
- *
- * This constructor is only available when the types that the pair stores
- * are both at least default constructible.
- *
- * @tparam Dummy Dummy template parameter used for internal purposes.
- */
- template<bool Dummy = true, typename = std::enable_if_t<Dummy && std::is_default_constructible_v<first_type> && std::is_default_constructible_v<second_type>>>
- constexpr compressed_pair() noexcept(std::is_nothrow_default_constructible_v<first_base> && std::is_nothrow_default_constructible_v<second_base>)
- : first_base{},
- second_base{} {}
- /**
- * @brief Copy constructor.
- * @param other The instance to copy from.
- */
- constexpr compressed_pair(const compressed_pair &other) = default;
- /**
- * @brief Move constructor.
- * @param other The instance to move from.
- */
- constexpr compressed_pair(compressed_pair &&other) noexcept = default;
- /**
- * @brief Constructs a pair from its values.
- * @tparam Arg Type of value to use to initialize the first element.
- * @tparam Other Type of value to use to initialize the second element.
- * @param arg Value to use to initialize the first element.
- * @param other Value to use to initialize the second element.
- */
- template<typename Arg, typename Other>
- constexpr compressed_pair(Arg &&arg, Other &&other) noexcept(std::is_nothrow_constructible_v<first_base, Arg> && std::is_nothrow_constructible_v<second_base, Other>)
- : first_base{std::forward<Arg>(arg)},
- second_base{std::forward<Other>(other)} {}
- /**
- * @brief Constructs a pair by forwarding the arguments to its parts.
- * @tparam Args Types of arguments to use to initialize the first element.
- * @tparam Other Types of arguments to use to initialize the second element.
- * @param args Arguments to use to initialize the first element.
- * @param other Arguments to use to initialize the second element.
- */
- template<typename... Args, typename... Other>
- constexpr compressed_pair(std::piecewise_construct_t, std::tuple<Args...> args, std::tuple<Other...> other) noexcept(std::is_nothrow_constructible_v<first_base, Args...> && std::is_nothrow_constructible_v<second_base, Other...>)
- : first_base{std::move(args), std::index_sequence_for<Args...>{}},
- second_base{std::move(other), std::index_sequence_for<Other...>{}} {}
- /*! @brief Default destructor. */
- ~compressed_pair() = default;
- /**
- * @brief Copy assignment operator.
- * @param other The instance to copy from.
- * @return This compressed pair object.
- */
- constexpr compressed_pair &operator=(const compressed_pair &other) = default;
- /**
- * @brief Move assignment operator.
- * @param other The instance to move from.
- * @return This compressed pair object.
- */
- constexpr compressed_pair &operator=(compressed_pair &&other) noexcept = default;
- /**
- * @brief Returns the first element that a pair stores.
- * @return The first element that a pair stores.
- */
- [[nodiscard]] constexpr first_type &first() noexcept {
- return static_cast<first_base &>(*this).get();
- }
- /*! @copydoc first */
- [[nodiscard]] constexpr const first_type &first() const noexcept {
- return static_cast<const first_base &>(*this).get();
- }
- /**
- * @brief Returns the second element that a pair stores.
- * @return The second element that a pair stores.
- */
- [[nodiscard]] constexpr second_type &second() noexcept {
- return static_cast<second_base &>(*this).get();
- }
- /*! @copydoc second */
- [[nodiscard]] constexpr const second_type &second() const noexcept {
- return static_cast<const second_base &>(*this).get();
- }
- /**
- * @brief Swaps two compressed pair objects.
- * @param other The compressed pair to swap with.
- */
- constexpr void swap(compressed_pair &other) noexcept {
- using std::swap;
- swap(first(), other.first());
- swap(second(), other.second());
- }
- /**
- * @brief Extracts an element from the compressed pair.
- * @tparam Index An integer value that is either 0 or 1.
- * @return Returns a reference to the first element if `Index` is 0 and a
- * reference to the second element if `Index` is 1.
- */
- template<std::size_t Index>
- [[nodiscard]] constexpr decltype(auto) get() noexcept {
- if constexpr(Index == 0u) {
- return first();
- } else {
- static_assert(Index == 1u, "Index out of bounds");
- return second();
- }
- }
- /*! @copydoc get */
- template<std::size_t Index>
- [[nodiscard]] constexpr decltype(auto) get() const noexcept {
- if constexpr(Index == 0u) {
- return first();
- } else {
- static_assert(Index == 1u, "Index out of bounds");
- return second();
- }
- }
- };
- /**
- * @brief Deduction guide.
- * @tparam Type Type of value to use to initialize the first element.
- * @tparam Other Type of value to use to initialize the second element.
- */
- template<typename Type, typename Other>
- compressed_pair(Type &&, Other &&) -> compressed_pair<std::decay_t<Type>, std::decay_t<Other>>;
- /**
- * @brief Swaps two compressed pair objects.
- * @tparam First The type of the first element that the pairs store.
- * @tparam Second The type of the second element that the pairs store.
- * @param lhs A valid compressed pair object.
- * @param rhs A valid compressed pair object.
- */
- template<typename First, typename Second>
- constexpr void swap(compressed_pair<First, Second> &lhs, compressed_pair<First, Second> &rhs) noexcept {
- lhs.swap(rhs);
- }
- } // namespace entt
- namespace std {
- /**
- * @brief `std::tuple_size` specialization for `compressed_pair`s.
- * @tparam First The type of the first element that the pair stores.
- * @tparam Second The type of the second element that the pair stores.
- */
- template<typename First, typename Second>
- struct tuple_size<entt::compressed_pair<First, Second>>: integral_constant<size_t, 2u> {};
- /**
- * @brief `std::tuple_element` specialization for `compressed_pair`s.
- * @tparam Index The index of the type to return.
- * @tparam First The type of the first element that the pair stores.
- * @tparam Second The type of the second element that the pair stores.
- */
- template<size_t Index, typename First, typename Second>
- struct tuple_element<Index, entt::compressed_pair<First, Second>>: conditional<Index == 0u, First, Second> {
- static_assert(Index < 2u, "Index out of bounds");
- };
- } // namespace std
- #endif
- // #include "../core/fwd.hpp"
- // #include "../core/iterator.hpp"
- // #include "../core/utility.hpp"
- #ifndef ENTT_CORE_UTILITY_HPP
- #define ENTT_CORE_UTILITY_HPP
- #include <type_traits>
- #include <utility>
- namespace entt {
- /*! @brief Identity function object (waiting for C++20). */
- struct identity {
- /*! @brief Indicates that this is a transparent function object. */
- using is_transparent = void;
- /**
- * @brief Returns its argument unchanged.
- * @tparam Type Type of the argument.
- * @param value The actual argument.
- * @return The submitted value as-is.
- */
- template<typename Type>
- [[nodiscard]] constexpr Type &&operator()(Type &&value) const noexcept {
- return std::forward<Type>(value);
- }
- };
- /**
- * @brief Constant utility to disambiguate overloaded members of a class.
- * @tparam Type Type of the desired overload.
- * @tparam Class Type of class to which the member belongs.
- * @param member A valid pointer to a member.
- * @return Pointer to the member.
- */
- template<typename Type, typename Class>
- [[nodiscard]] constexpr auto overload(Type Class::*member) noexcept {
- return member;
- }
- /**
- * @brief Constant utility to disambiguate overloaded functions.
- * @tparam Func Function type of the desired overload.
- * @param func A valid pointer to a function.
- * @return Pointer to the function.
- */
- template<typename Func>
- [[nodiscard]] constexpr auto overload(Func *func) noexcept {
- return func;
- }
- /**
- * @brief Helper type for visitors.
- * @tparam Func Types of function objects.
- */
- template<typename... Func>
- struct overloaded: Func... {
- using Func::operator()...;
- };
- /**
- * @brief Deduction guide.
- * @tparam Func Types of function objects.
- */
- template<typename... Func>
- overloaded(Func...) -> overloaded<Func...>;
- /**
- * @brief Basic implementation of a y-combinator.
- * @tparam Func Type of a potentially recursive function.
- */
- template<typename Func>
- struct y_combinator {
- /**
- * @brief Constructs a y-combinator from a given function.
- * @param recursive A potentially recursive function.
- */
- constexpr y_combinator(Func recursive) noexcept(std::is_nothrow_move_constructible_v<Func>)
- : func{std::move(recursive)} {}
- /**
- * @brief Invokes a y-combinator and therefore its underlying function.
- * @tparam Args Types of arguments to use to invoke the underlying function.
- * @param args Parameters to use to invoke the underlying function.
- * @return Return value of the underlying function, if any.
- */
- template<typename... Args>
- constexpr decltype(auto) operator()(Args &&...args) const noexcept(std::is_nothrow_invocable_v<Func, const y_combinator &, Args...>) {
- return func(*this, std::forward<Args>(args)...);
- }
- /*! @copydoc operator()() */
- template<typename... Args>
- constexpr decltype(auto) operator()(Args &&...args) noexcept(std::is_nothrow_invocable_v<Func, y_combinator &, Args...>) {
- return func(*this, std::forward<Args>(args)...);
- }
- private:
- Func func;
- };
- } // namespace entt
- #endif
- // #include "adjacency_matrix.hpp"
- #ifndef ENTT_GRAPH_ADJACENCY_MATRIX_HPP
- #define ENTT_GRAPH_ADJACENCY_MATRIX_HPP
- #include <cstddef>
- #include <iterator>
- #include <memory>
- #include <type_traits>
- #include <utility>
- #include <vector>
- // #include "../config/config.h"
- // #include "../core/iterator.hpp"
- // #include "fwd.hpp"
- namespace entt {
- /*! @cond TURN_OFF_DOXYGEN */
- namespace internal {
- template<typename It>
- class edge_iterator {
- using size_type = std::size_t;
- void find_next() noexcept {
- for(; pos != last && !it[static_cast<typename It::difference_type>(pos)]; pos += offset) {}
- }
- public:
- using value_type = std::pair<size_type, size_type>;
- using pointer = input_iterator_pointer<value_type>;
- using reference = value_type;
- using difference_type = std::ptrdiff_t;
- using iterator_category = std::input_iterator_tag;
- using iterator_concept = std::forward_iterator_tag;
- constexpr edge_iterator() noexcept = default;
- // NOLINTNEXTLINE(bugprone-easily-swappable-parameters)
- constexpr edge_iterator(It base, const size_type vertices, const size_type from, const size_type to, const size_type step) noexcept
- : it{std::move(base)},
- vert{vertices},
- pos{from},
- last{to},
- offset{step} {
- find_next();
- }
- constexpr edge_iterator &operator++() noexcept {
- pos += offset;
- find_next();
- return *this;
- }
- constexpr edge_iterator operator++(int) noexcept {
- const edge_iterator orig = *this;
- return ++(*this), orig;
- }
- [[nodiscard]] constexpr reference operator*() const noexcept {
- return *operator->();
- }
- [[nodiscard]] constexpr pointer operator->() const noexcept {
- return std::make_pair<size_type>(pos / vert, pos % vert);
- }
- template<typename Type>
- friend constexpr bool operator==(const edge_iterator<Type> &, const edge_iterator<Type> &) noexcept;
- private:
- It it{};
- size_type vert{};
- size_type pos{};
- size_type last{};
- size_type offset{};
- };
- template<typename Container>
- [[nodiscard]] constexpr bool operator==(const edge_iterator<Container> &lhs, const edge_iterator<Container> &rhs) noexcept {
- return lhs.pos == rhs.pos;
- }
- template<typename Container>
- [[nodiscard]] constexpr bool operator!=(const edge_iterator<Container> &lhs, const edge_iterator<Container> &rhs) noexcept {
- return !(lhs == rhs);
- }
- } // namespace internal
- /*! @endcond */
- /**
- * @brief Basic implementation of a directed adjacency matrix.
- * @tparam Category Either a directed or undirected category tag.
- * @tparam Allocator Type of allocator used to manage memory and elements.
- */
- template<typename Category, typename Allocator>
- class adjacency_matrix {
- using alloc_traits = std::allocator_traits<Allocator>;
- static_assert(std::is_base_of_v<directed_tag, Category>, "Invalid graph category");
- static_assert(std::is_same_v<typename alloc_traits::value_type, std::size_t>, "Invalid value type");
- using container_type = std::vector<std::size_t, typename alloc_traits::template rebind_alloc<std::size_t>>;
- public:
- /*! @brief Allocator type. */
- using allocator_type = Allocator;
- /*! @brief Unsigned integer type. */
- using size_type = std::size_t;
- /*! @brief Vertex type. */
- using vertex_type = size_type;
- /*! @brief Edge type. */
- using edge_type = std::pair<vertex_type, vertex_type>;
- /*! @brief Vertex iterator type. */
- using vertex_iterator = iota_iterator<vertex_type>;
- /*! @brief Edge iterator type. */
- using edge_iterator = internal::edge_iterator<typename container_type::const_iterator>;
- /*! @brief Out-edge iterator type. */
- using out_edge_iterator = edge_iterator;
- /*! @brief In-edge iterator type. */
- using in_edge_iterator = edge_iterator;
- /*! @brief Graph category tag. */
- using graph_category = Category;
- /*! @brief Default constructor. */
- adjacency_matrix() noexcept(noexcept(allocator_type{}))
- : adjacency_matrix{0u} {
- }
- /**
- * @brief Constructs an empty container with a given allocator.
- * @param allocator The allocator to use.
- */
- explicit adjacency_matrix(const allocator_type &allocator) noexcept
- : adjacency_matrix{0u, allocator} {}
- /**
- * @brief Constructs an empty container with a given allocator and user
- * supplied number of vertices.
- * @param vertices Number of vertices.
- * @param allocator The allocator to use.
- */
- adjacency_matrix(const size_type vertices, const allocator_type &allocator = allocator_type{})
- : matrix{vertices * vertices, allocator},
- vert{vertices} {}
- /*! @brief Default copy constructor. */
- adjacency_matrix(const adjacency_matrix &) = default;
- /**
- * @brief Allocator-extended copy constructor.
- * @param other The instance to copy from.
- * @param allocator The allocator to use.
- */
- adjacency_matrix(const adjacency_matrix &other, const allocator_type &allocator)
- : matrix{other.matrix, allocator},
- vert{other.vert} {}
- /*! @brief Default move constructor. */
- adjacency_matrix(adjacency_matrix &&) noexcept = default;
- /**
- * @brief Allocator-extended move constructor.
- * @param other The instance to move from.
- * @param allocator The allocator to use.
- */
- adjacency_matrix(adjacency_matrix &&other, const allocator_type &allocator)
- : matrix{std::move(other.matrix), allocator},
- vert{other.vert} {}
- /*! @brief Default destructor. */
- ~adjacency_matrix() = default;
- /**
- * @brief Default copy assignment operator.
- * @return This container.
- */
- adjacency_matrix &operator=(const adjacency_matrix &) = default;
- /**
- * @brief Default move assignment operator.
- * @return This container.
- */
- adjacency_matrix &operator=(adjacency_matrix &&) noexcept = default;
- /**
- * @brief Exchanges the contents with those of a given adjacency matrix.
- * @param other Adjacency matrix to exchange the content with.
- */
- void swap(adjacency_matrix &other) noexcept {
- using std::swap;
- swap(matrix, other.matrix);
- swap(vert, other.vert);
- }
- /**
- * @brief Returns the associated allocator.
- * @return The associated allocator.
- */
- [[nodiscard]] constexpr allocator_type get_allocator() const noexcept {
- return matrix.get_allocator();
- }
- /*! @brief Clears the adjacency matrix. */
- void clear() noexcept {
- matrix.clear();
- vert = {};
- }
- /**
- * @brief Returns true if an adjacency matrix is empty, false otherwise.
- *
- * @warning
- * Potentially expensive, try to avoid it on hot paths.
- *
- * @return True if the adjacency matrix is empty, false otherwise.
- */
- [[nodiscard]] bool empty() const noexcept {
- const auto iterable = edges();
- return (iterable.begin() == iterable.end());
- }
- /**
- * @brief Returns the number of vertices.
- * @return The number of vertices.
- */
- [[nodiscard]] size_type size() const noexcept {
- return vert;
- }
- /**
- * @brief Returns an iterable object to visit all vertices of a matrix.
- * @return An iterable object to visit all vertices of a matrix.
- */
- [[nodiscard]] iterable_adaptor<vertex_iterator> vertices() const noexcept {
- return {0u, vert};
- }
- /**
- * @brief Returns an iterable object to visit all edges of a matrix.
- * @return An iterable object to visit all edges of a matrix.
- */
- [[nodiscard]] iterable_adaptor<edge_iterator> edges() const noexcept {
- const auto it = matrix.cbegin();
- const auto sz = matrix.size();
- return {{it, vert, 0u, sz, 1u}, {it, vert, sz, sz, 1u}};
- }
- /**
- * @brief Returns an iterable object to visit all out-edges of a vertex.
- * @param vertex The vertex of which to return all out-edges.
- * @return An iterable object to visit all out-edges of a vertex.
- */
- [[nodiscard]] iterable_adaptor<out_edge_iterator> out_edges(const vertex_type vertex) const noexcept {
- const auto it = matrix.cbegin();
- const auto from = vertex * vert;
- const auto to = from + vert;
- return {{it, vert, from, to, 1u}, {it, vert, to, to, 1u}};
- }
- /**
- * @brief Returns an iterable object to visit all in-edges of a vertex.
- * @param vertex The vertex of which to return all in-edges.
- * @return An iterable object to visit all in-edges of a vertex.
- */
- [[nodiscard]] iterable_adaptor<in_edge_iterator> in_edges(const vertex_type vertex) const noexcept {
- const auto it = matrix.cbegin();
- const auto from = vertex;
- const auto to = vert * vert + from;
- return {{it, vert, from, to, vert}, {it, vert, to, to, vert}};
- }
- /**
- * @brief Resizes an adjacency matrix.
- * @param vertices The new number of vertices.
- */
- void resize(const size_type vertices) {
- adjacency_matrix other{vertices, get_allocator()};
- for(auto [lhs, rhs]: edges()) {
- other.insert(lhs, rhs);
- }
- other.swap(*this);
- }
- /**
- * @brief Inserts an edge into the adjacency matrix, if it does not exist.
- * @param lhs The left hand vertex of the edge.
- * @param rhs The right hand vertex of the edge.
- * @return A pair consisting of an iterator to the inserted element (or to
- * the element that prevented the insertion) and a bool denoting whether the
- * insertion took place.
- */
- std::pair<edge_iterator, bool> insert(const vertex_type lhs, const vertex_type rhs) {
- const auto pos = lhs * vert + rhs;
- if constexpr(std::is_same_v<graph_category, undirected_tag>) {
- const auto rev = rhs * vert + lhs;
- ENTT_ASSERT(matrix[pos] == matrix[rev], "Something went really wrong");
- matrix[rev] = 1u;
- }
- const auto inserted = !std::exchange(matrix[pos], 1u);
- return {edge_iterator{matrix.cbegin(), vert, pos, matrix.size(), 1u}, inserted};
- }
- /**
- * @brief Removes the edge associated with a pair of given vertices.
- * @param lhs The left hand vertex of the edge.
- * @param rhs The right hand vertex of the edge.
- * @return Number of elements removed (either 0 or 1).
- */
- size_type erase(const vertex_type lhs, const vertex_type rhs) {
- const auto pos = lhs * vert + rhs;
- if constexpr(std::is_same_v<graph_category, undirected_tag>) {
- const auto rev = rhs * vert + lhs;
- ENTT_ASSERT(matrix[pos] == matrix[rev], "Something went really wrong");
- matrix[rev] = 0u;
- }
- return std::exchange(matrix[pos], 0u);
- }
- /**
- * @brief Checks if an adjacency matrix contains a given edge.
- * @param lhs The left hand vertex of the edge.
- * @param rhs The right hand vertex of the edge.
- * @return True if there is such an edge, false otherwise.
- */
- [[nodiscard]] bool contains(const vertex_type lhs, const vertex_type rhs) const {
- const auto pos = lhs * vert + rhs;
- return pos < matrix.size() && matrix[pos];
- }
- private:
- container_type matrix;
- size_type vert;
- };
- } // namespace entt
- #endif
- // #include "fwd.hpp"
- namespace entt {
- /**
- * @brief Utility class for creating task graphs.
- * @tparam Allocator Type of allocator used to manage memory and elements.
- */
- template<typename Allocator>
- class basic_flow {
- using alloc_traits = std::allocator_traits<Allocator>;
- static_assert(std::is_same_v<typename alloc_traits::value_type, id_type>, "Invalid value type");
- using task_container_type = dense_set<id_type, identity, std::equal_to<>, typename alloc_traits::template rebind_alloc<id_type>>;
- using ro_rw_container_type = std::vector<std::pair<std::size_t, bool>, typename alloc_traits::template rebind_alloc<std::pair<std::size_t, bool>>>;
- using deps_container_type = dense_map<id_type, ro_rw_container_type, identity, std::equal_to<>, typename alloc_traits::template rebind_alloc<std::pair<const id_type, ro_rw_container_type>>>;
- using adjacency_matrix_type = adjacency_matrix<directed_tag, typename alloc_traits::template rebind_alloc<std::size_t>>;
- void emplace(const id_type res, const bool is_rw) {
- ENTT_ASSERT(index.first() < vertices.size(), "Invalid node");
- if(!deps.contains(res) && sync_on != vertices.size()) {
- deps[res].emplace_back(sync_on, true);
- }
- deps[res].emplace_back(index.first(), is_rw);
- }
- void setup_graph(adjacency_matrix_type &matrix) const {
- for(const auto &elem: deps) {
- const auto last = elem.second.cend();
- auto it = elem.second.cbegin();
- while(it != last) {
- if(it->second) {
- // rw item
- if(auto curr = it++; it != last) {
- if(it->second) {
- matrix.insert(curr->first, it->first);
- } else if(const auto next = std::find_if(it, last, [](const auto &value) { return value.second; }); next != last) {
- for(; it != next; ++it) {
- matrix.insert(curr->first, it->first);
- matrix.insert(it->first, next->first);
- }
- } else {
- for(; it != next; ++it) {
- matrix.insert(curr->first, it->first);
- }
- }
- }
- } else {
- // ro item (first iteration only)
- if(const auto next = std::find_if(it, last, [](const auto &value) { return value.second; }); next != last) {
- for(; it != next; ++it) {
- matrix.insert(it->first, next->first);
- }
- } else {
- it = last;
- }
- }
- }
- }
- }
- void transitive_closure(adjacency_matrix_type &matrix) const {
- const auto length = matrix.size();
- for(std::size_t vk{}; vk < length; ++vk) {
- for(std::size_t vi{}; vi < length; ++vi) {
- for(std::size_t vj{}; vj < length; ++vj) {
- if(matrix.contains(vi, vk) && matrix.contains(vk, vj)) {
- matrix.insert(vi, vj);
- }
- }
- }
- }
- }
- void transitive_reduction(adjacency_matrix_type &matrix) const {
- const auto length = matrix.size();
- for(std::size_t vert{}; vert < length; ++vert) {
- matrix.erase(vert, vert);
- }
- for(std::size_t vj{}; vj < length; ++vj) {
- for(std::size_t vi{}; vi < length; ++vi) {
- if(matrix.contains(vi, vj)) {
- for(std::size_t vk{}; vk < length; ++vk) {
- if(matrix.contains(vj, vk)) {
- matrix.erase(vi, vk);
- }
- }
- }
- }
- }
- }
- public:
- /*! @brief Allocator type. */
- using allocator_type = Allocator;
- /*! @brief Unsigned integer type. */
- using size_type = std::size_t;
- /*! @brief Iterable task list. */
- using iterable = iterable_adaptor<typename task_container_type::const_iterator>;
- /*! @brief Adjacency matrix type. */
- using graph_type = adjacency_matrix_type;
- /*! @brief Default constructor. */
- basic_flow()
- : basic_flow{allocator_type{}} {}
- /**
- * @brief Constructs a flow builder with a given allocator.
- * @param allocator The allocator to use.
- */
- explicit basic_flow(const allocator_type &allocator)
- : index{0u, allocator},
- vertices{allocator},
- deps{allocator} {}
- /*! @brief Default copy constructor. */
- basic_flow(const basic_flow &) = default;
- /**
- * @brief Allocator-extended copy constructor.
- * @param other The instance to copy from.
- * @param allocator The allocator to use.
- */
- basic_flow(const basic_flow &other, const allocator_type &allocator)
- : index{other.index.first(), allocator},
- vertices{other.vertices, allocator},
- deps{other.deps, allocator},
- sync_on{other.sync_on} {}
- /*! @brief Default move constructor. */
- basic_flow(basic_flow &&) noexcept = default;
- /**
- * @brief Allocator-extended move constructor.
- * @param other The instance to move from.
- * @param allocator The allocator to use.
- */
- basic_flow(basic_flow &&other, const allocator_type &allocator)
- : index{other.index.first(), allocator},
- vertices{std::move(other.vertices), allocator},
- deps{std::move(other.deps), allocator},
- sync_on{other.sync_on} {}
- /*! @brief Default destructor. */
- ~basic_flow() = default;
- /**
- * @brief Default copy assignment operator.
- * @return This flow builder.
- */
- basic_flow &operator=(const basic_flow &) = default;
- /**
- * @brief Default move assignment operator.
- * @return This flow builder.
- */
- basic_flow &operator=(basic_flow &&) noexcept = default;
- /**
- * @brief Exchanges the contents with those of a given flow builder.
- * @param other Flow builder to exchange the content with.
- */
- void swap(basic_flow &other) noexcept {
- using std::swap;
- std::swap(index, other.index);
- std::swap(vertices, other.vertices);
- std::swap(deps, other.deps);
- std::swap(sync_on, other.sync_on);
- }
- /**
- * @brief Returns the associated allocator.
- * @return The associated allocator.
- */
- [[nodiscard]] constexpr allocator_type get_allocator() const noexcept {
- return allocator_type{index.second()};
- }
- /**
- * @brief Returns the identifier at specified location.
- * @param pos Position of the identifier to return.
- * @return The requested identifier.
- */
- [[nodiscard]] id_type operator[](const size_type pos) const {
- return vertices.cbegin()[static_cast<typename task_container_type::difference_type>(pos)];
- }
- /*! @brief Clears the flow builder. */
- void clear() noexcept {
- index.first() = {};
- vertices.clear();
- deps.clear();
- sync_on = {};
- }
- /**
- * @brief Returns true if a flow builder contains no tasks, false otherwise.
- * @return True if the flow builder contains no tasks, false otherwise.
- */
- [[nodiscard]] bool empty() const noexcept {
- return vertices.empty();
- }
- /**
- * @brief Returns the number of tasks.
- * @return The number of tasks.
- */
- [[nodiscard]] size_type size() const noexcept {
- return vertices.size();
- }
- /**
- * @brief Binds a task to a flow builder.
- * @param value Task identifier.
- * @return This flow builder.
- */
- basic_flow &bind(const id_type value) {
- sync_on += (sync_on == vertices.size());
- const auto it = vertices.emplace(value).first;
- index.first() = size_type(it - vertices.begin());
- return *this;
- }
- /**
- * @brief Turns the current task into a sync point.
- * @return This flow builder.
- */
- basic_flow &sync() {
- ENTT_ASSERT(index.first() < vertices.size(), "Invalid node");
- sync_on = index.first();
- for(const auto &elem: deps) {
- elem.second.emplace_back(sync_on, true);
- }
- return *this;
- }
- /**
- * @brief Assigns a resource to the current task with a given access mode.
- * @param res Resource identifier.
- * @param is_rw Access mode.
- * @return This flow builder.
- */
- basic_flow &set(const id_type res, bool is_rw = false) {
- emplace(res, is_rw);
- return *this;
- }
- /**
- * @brief Assigns a read-only resource to the current task.
- * @param res Resource identifier.
- * @return This flow builder.
- */
- basic_flow &ro(const id_type res) {
- emplace(res, false);
- return *this;
- }
- /**
- * @brief Assigns a range of read-only resources to the current task.
- * @tparam It Type of input iterator.
- * @param first An iterator to the first element of the range of elements.
- * @param last An iterator past the last element of the range of elements.
- * @return This flow builder.
- */
- template<typename It>
- std::enable_if_t<std::is_same_v<std::remove_const_t<typename std::iterator_traits<It>::value_type>, id_type>, basic_flow &>
- ro(It first, It last) {
- for(; first != last; ++first) {
- emplace(*first, false);
- }
- return *this;
- }
- /**
- * @brief Assigns a writable resource to the current task.
- * @param res Resource identifier.
- * @return This flow builder.
- */
- basic_flow &rw(const id_type res) {
- emplace(res, true);
- return *this;
- }
- /**
- * @brief Assigns a range of writable resources to the current task.
- * @tparam It Type of input iterator.
- * @param first An iterator to the first element of the range of elements.
- * @param last An iterator past the last element of the range of elements.
- * @return This flow builder.
- */
- template<typename It>
- std::enable_if_t<std::is_same_v<std::remove_const_t<typename std::iterator_traits<It>::value_type>, id_type>, basic_flow &>
- rw(It first, It last) {
- for(; first != last; ++first) {
- emplace(*first, true);
- }
- return *this;
- }
- /**
- * @brief Generates a task graph for the current content.
- * @return The adjacency matrix of the task graph.
- */
- [[nodiscard]] graph_type graph() const {
- graph_type matrix{vertices.size(), get_allocator()};
- setup_graph(matrix);
- transitive_closure(matrix);
- transitive_reduction(matrix);
- return matrix;
- }
- private:
- compressed_pair<size_type, allocator_type> index;
- task_container_type vertices;
- deps_container_type deps;
- size_type sync_on{};
- };
- } // namespace entt
- #endif
- // #include "fwd.hpp"
- // #include "helper.hpp"
- #ifndef ENTT_ENTITY_HELPER_HPP
- #define ENTT_ENTITY_HELPER_HPP
- #include <memory>
- #include <type_traits>
- #include <utility>
- // #include "../core/fwd.hpp"
- // #include "../core/type_traits.hpp"
- // #include "component.hpp"
- // #include "fwd.hpp"
- // #include "group.hpp"
- // #include "storage.hpp"
- // #include "view.hpp"
- namespace entt {
- /**
- * @brief Converts a registry to a view.
- * @tparam Registry Basic registry type.
- */
- template<typename Registry>
- class as_view {
- template<typename... Get, typename... Exclude>
- [[nodiscard]] auto dispatch(get_t<Get...>, exclude_t<Exclude...>) const {
- return reg->template view<constness_as_t<typename Get::element_type, Get>...>(exclude_t<constness_as_t<typename Exclude::element_type, Exclude>...>{});
- }
- public:
- /*! @brief Type of registry to convert. */
- using registry_type = Registry;
- /*! @brief Underlying entity identifier. */
- using entity_type = typename registry_type::entity_type;
- /**
- * @brief Constructs a converter for a given registry.
- * @param source A valid reference to a registry.
- */
- as_view(registry_type &source) noexcept
- : reg{&source} {}
- /**
- * @brief Conversion function from a registry to a view.
- * @tparam Get Type of storage used to construct the view.
- * @tparam Exclude Types of storage used to filter the view.
- * @return A newly created view.
- */
- template<typename Get, typename Exclude>
- operator basic_view<Get, Exclude>() const {
- return dispatch(Get{}, Exclude{});
- }
- private:
- registry_type *reg;
- };
- /**
- * @brief Converts a registry to a group.
- * @tparam Registry Basic registry type.
- */
- template<typename Registry>
- class as_group {
- template<typename... Owned, typename... Get, typename... Exclude>
- [[nodiscard]] auto dispatch(owned_t<Owned...>, get_t<Get...>, exclude_t<Exclude...>) const {
- if constexpr(std::is_const_v<registry_type>) {
- return reg->template group_if_exists<typename Owned::element_type...>(get_t<typename Get::element_type...>{}, exclude_t<typename Exclude::element_type...>{});
- } else {
- return reg->template group<constness_as_t<typename Owned::element_type, Owned>...>(get_t<constness_as_t<typename Get::element_type, Get>...>{}, exclude_t<constness_as_t<typename Exclude::element_type, Exclude>...>{});
- }
- }
- public:
- /*! @brief Type of registry to convert. */
- using registry_type = Registry;
- /*! @brief Underlying entity identifier. */
- using entity_type = typename registry_type::entity_type;
- /**
- * @brief Constructs a converter for a given registry.
- * @param source A valid reference to a registry.
- */
- as_group(registry_type &source) noexcept
- : reg{&source} {}
- /**
- * @brief Conversion function from a registry to a group.
- * @tparam Owned Types of _owned_ by the group.
- * @tparam Get Types of storage _observed_ by the group.
- * @tparam Exclude Types of storage used to filter the group.
- * @return A newly created group.
- */
- template<typename Owned, typename Get, typename Exclude>
- operator basic_group<Owned, Get, Exclude>() const {
- return dispatch(Owned{}, Get{}, Exclude{});
- }
- private:
- registry_type *reg;
- };
- /**
- * @brief Helper to create a listener that directly invokes a member function.
- * @tparam Member Member function to invoke on an element of the given type.
- * @tparam Registry Basic registry type.
- * @param reg A registry that contains the given entity and its elements.
- * @param entt Entity from which to get the element.
- */
- template<auto Member, typename Registry = std::decay_t<nth_argument_t<0u, decltype(Member)>>>
- void invoke(Registry ®, const typename Registry::entity_type entt) {
- static_assert(std::is_member_function_pointer_v<decltype(Member)>, "Invalid pointer to non-static member function");
- (reg.template get<member_class_t<decltype(Member)>>(entt).*Member)(reg, entt);
- }
- /**
- * @brief Returns the entity associated with a given element.
- *
- * @warning
- * Currently, this function only works correctly with the default storage as it
- * makes assumptions about how the elements are laid out.
- *
- * @tparam Args Storage type template parameters.
- * @param storage A storage that contains the given element.
- * @param instance A valid element instance.
- * @return The entity associated with the given element.
- */
- template<typename... Args>
- typename basic_storage<Args...>::entity_type to_entity(const basic_storage<Args...> &storage, const typename basic_storage<Args...>::value_type &instance) {
- using traits_type = component_traits<typename basic_storage<Args...>::value_type, typename basic_storage<Args...>::entity_type>;
- static_assert(traits_type::page_size != 0u, "Unexpected page size");
- const auto *page = storage.raw();
- // NOLINTBEGIN(cppcoreguidelines-pro-bounds-pointer-arithmetic)
- for(std::size_t pos{}, count = storage.size(); pos < count; pos += traits_type::page_size, ++page) {
- if(const auto dist = (std::addressof(instance) - *page); dist >= 0 && dist < static_cast<decltype(dist)>(traits_type::page_size)) {
- return *(static_cast<const typename basic_storage<Args...>::base_type &>(storage).rbegin() + static_cast<decltype(dist)>(pos) + dist);
- }
- }
- // NOLINTEND(cppcoreguidelines-pro-bounds-pointer-arithmetic)
- return null;
- }
- /*! @brief Primary template isn't defined on purpose. */
- template<typename...>
- struct sigh_helper;
- /**
- * @brief Signal connection helper for registries.
- * @tparam Registry Basic registry type.
- */
- template<typename Registry>
- struct sigh_helper<Registry> {
- /*! @brief Registry type. */
- using registry_type = Registry;
- /**
- * @brief Constructs a helper for a given registry.
- * @param ref A valid reference to a registry.
- */
- sigh_helper(registry_type &ref)
- : bucket{&ref} {}
- /**
- * @brief Binds a properly initialized helper to a given signal type.
- * @tparam Type Type of signal to bind the helper to.
- * @param id Optional name for the underlying storage to use.
- * @return A helper for a given registry and signal type.
- */
- template<typename Type>
- auto with(const id_type id = type_hash<Type>::value()) noexcept {
- return sigh_helper<registry_type, Type>{*bucket, id};
- }
- /**
- * @brief Returns a reference to the underlying registry.
- * @return A reference to the underlying registry.
- */
- [[nodiscard]] registry_type ®istry() noexcept {
- return *bucket;
- }
- private:
- registry_type *bucket;
- };
- /**
- * @brief Signal connection helper for registries.
- * @tparam Registry Basic registry type.
- * @tparam Type Type of signal to connect listeners to.
- */
- template<typename Registry, typename Type>
- struct sigh_helper<Registry, Type> final: sigh_helper<Registry> {
- /*! @brief Registry type. */
- using registry_type = Registry;
- /**
- * @brief Constructs a helper for a given registry.
- * @param ref A valid reference to a registry.
- * @param id Optional name for the underlying storage to use.
- */
- sigh_helper(registry_type &ref, const id_type id = type_hash<Type>::value())
- : sigh_helper<Registry>{ref},
- name{id} {}
- /**
- * @brief Forwards the call to `on_construct` on the underlying storage.
- * @tparam Candidate Function or member to connect.
- * @tparam Args Type of class or type of payload, if any.
- * @param args A valid object that fits the purpose, if any.
- * @return This helper.
- */
- template<auto Candidate, typename... Args>
- auto on_construct(Args &&...args) {
- this->registry().template on_construct<Type>(name).template connect<Candidate>(std::forward<Args>(args)...);
- return *this;
- }
- /**
- * @brief Forwards the call to `on_update` on the underlying storage.
- * @tparam Candidate Function or member to connect.
- * @tparam Args Type of class or type of payload, if any.
- * @param args A valid object that fits the purpose, if any.
- * @return This helper.
- */
- template<auto Candidate, typename... Args>
- auto on_update(Args &&...args) {
- this->registry().template on_update<Type>(name).template connect<Candidate>(std::forward<Args>(args)...);
- return *this;
- }
- /**
- * @brief Forwards the call to `on_destroy` on the underlying storage.
- * @tparam Candidate Function or member to connect.
- * @tparam Args Type of class or type of payload, if any.
- * @param args A valid object that fits the purpose, if any.
- * @return This helper.
- */
- template<auto Candidate, typename... Args>
- auto on_destroy(Args &&...args) {
- this->registry().template on_destroy<Type>(name).template connect<Candidate>(std::forward<Args>(args)...);
- return *this;
- }
- private:
- id_type name;
- };
- /**
- * @brief Deduction guide.
- * @tparam Registry Basic registry type.
- */
- template<typename Registry>
- sigh_helper(Registry &) -> sigh_helper<Registry>;
- } // namespace entt
- #endif
- namespace entt {
- /*! @cond TURN_OFF_DOXYGEN */
- namespace internal {
- template<typename>
- struct is_view: std::false_type {};
- template<typename... Args>
- struct is_view<basic_view<Args...>>: std::true_type {};
- template<typename Type>
- inline constexpr bool is_view_v = is_view<Type>::value;
- template<typename>
- struct is_group: std::false_type {};
- template<typename... Args>
- struct is_group<basic_group<Args...>>: std::true_type {};
- template<typename Type>
- inline constexpr bool is_group_v = is_group<Type>::value;
- template<typename Type, typename Override>
- struct unpack_type {
- using ro = std::conditional_t<
- type_list_contains_v<Override, const Type> || (std::is_const_v<Type> && !type_list_contains_v<Override, std::remove_const_t<Type>>),
- type_list<std::remove_const_t<Type>>,
- type_list<>>;
- using rw = std::conditional_t<
- type_list_contains_v<Override, std::remove_const_t<Type>> || (!std::is_const_v<Type> && !type_list_contains_v<Override, const Type>),
- type_list<Type>,
- type_list<>>;
- };
- template<typename... Args, typename... Override>
- struct unpack_type<basic_registry<Args...>, type_list<Override...>> {
- using ro = type_list<>;
- using rw = type_list<>;
- };
- template<typename... Args, typename... Override>
- struct unpack_type<const basic_registry<Args...>, type_list<Override...>>
- : unpack_type<basic_registry<Args...>, type_list<Override...>> {};
- template<typename... Get, typename... Exclude, typename... Override>
- struct unpack_type<basic_view<get_t<Get...>, exclude_t<Exclude...>>, type_list<Override...>> {
- using ro = type_list_cat_t<type_list<typename Exclude::element_type...>, typename unpack_type<constness_as_t<typename Get::element_type, Get>, type_list<Override...>>::ro...>;
- using rw = type_list_cat_t<typename unpack_type<constness_as_t<typename Get::element_type, Get>, type_list<Override...>>::rw...>;
- };
- template<typename... Get, typename... Exclude, typename... Override>
- struct unpack_type<const basic_view<get_t<Get...>, exclude_t<Exclude...>>, type_list<Override...>>
- : unpack_type<basic_view<get_t<Get...>, exclude_t<Exclude...>>, type_list<Override...>> {};
- template<typename... Owned, typename... Get, typename... Exclude, typename... Override>
- struct unpack_type<basic_group<owned_t<Owned...>, get_t<Get...>, exclude_t<Exclude...>>, type_list<Override...>> {
- using ro = type_list_cat_t<type_list<typename Exclude::element_type...>, typename unpack_type<constness_as_t<typename Get::element_type, Get>, type_list<Override...>>::ro..., typename unpack_type<constness_as_t<typename Owned::element_type, Owned>, type_list<Override...>>::ro...>;
- using rw = type_list_cat_t<typename unpack_type<constness_as_t<typename Get::element_type, Get>, type_list<Override...>>::rw..., typename unpack_type<constness_as_t<typename Owned::element_type, Owned>, type_list<Override...>>::rw...>;
- };
- template<typename... Owned, typename... Get, typename... Exclude, typename... Override>
- struct unpack_type<const basic_group<owned_t<Owned...>, get_t<Get...>, exclude_t<Exclude...>>, type_list<Override...>>
- : unpack_type<basic_group<owned_t<Owned...>, get_t<Get...>, exclude_t<Exclude...>>, type_list<Override...>> {};
- template<typename, typename, typename>
- struct resource_traits;
- template<typename Registry, typename... Args, typename... Req>
- struct resource_traits<Registry, type_list<Args...>, type_list<Req...>> {
- using args = type_list<std::remove_const_t<Args>...>;
- using ro = type_list_cat_t<typename unpack_type<Args, type_list<Req...>>::ro..., typename unpack_type<Req, type_list<>>::ro...>;
- using rw = type_list_cat_t<typename unpack_type<Args, type_list<Req...>>::rw..., typename unpack_type<Req, type_list<>>::rw...>;
- static constexpr auto sync_point = (std::is_same_v<Args, Registry> || ...);
- };
- template<typename Registry, typename... Req, typename Ret, typename... Args>
- resource_traits<Registry, type_list<std::remove_reference_t<Args>...>, type_list<Req...>> free_function_to_resource_traits(Ret (*)(Args...));
- template<typename Registry, typename... Req, typename Ret, typename Type, typename... Args>
- resource_traits<Registry, type_list<std::remove_reference_t<Args>...>, type_list<Req...>> constrained_function_to_resource_traits(Ret (*)(Type &, Args...));
- template<typename Registry, typename... Req, typename Ret, typename Class, typename... Args>
- resource_traits<Registry, type_list<std::remove_reference_t<Args>...>, type_list<Req...>> constrained_function_to_resource_traits(Ret (Class::*)(Args...));
- template<typename Registry, typename... Req, typename Ret, typename Class, typename... Args>
- resource_traits<Registry, type_list<std::remove_reference_t<Args>...>, type_list<Req...>> constrained_function_to_resource_traits(Ret (Class::*)(Args...) const);
- } // namespace internal
- /*! @endcond */
- /**
- * @brief Utility class for creating a static task graph.
- *
- * This class offers minimal support (but sufficient in many cases) for creating
- * an execution graph from functions and their requirements on resources.<br/>
- * Note that the resulting tasks aren't executed in any case. This isn't the
- * goal of the tool. Instead, they are returned to the user in the form of a
- * graph that allows for safe execution.
- *
- * @tparam Registry Basic registry type.
- */
- template<typename Registry>
- class basic_organizer final {
- using callback_type = void(const void *, Registry &);
- using prepare_type = void(Registry &);
- using dependency_type = std::size_t(const bool, const type_info **, const std::size_t);
- struct vertex_data final {
- std::size_t ro_count{};
- std::size_t rw_count{};
- const char *name{};
- const void *payload{};
- callback_type *callback{};
- dependency_type *dependency{};
- prepare_type *prepare{};
- const type_info *info{};
- };
- template<typename Type>
- [[nodiscard]] static decltype(auto) extract(Registry ®) {
- if constexpr(std::is_same_v<Type, Registry>) {
- return reg;
- } else if constexpr(internal::is_view_v<Type>) {
- return static_cast<Type>(as_view{reg});
- } else if constexpr(internal::is_group_v<Type>) {
- return static_cast<Type>(as_group{reg});
- } else {
- return reg.ctx().template emplace<std::remove_reference_t<Type>>();
- }
- }
- template<typename... Args>
- [[nodiscard]] static auto to_args(Registry ®, type_list<Args...>) {
- return std::tuple<decltype(extract<Args>(reg))...>(extract<Args>(reg)...);
- }
- template<typename... Type>
- [[nodiscard]] static std::size_t fill_dependencies(type_list<Type...>, [[maybe_unused]] const type_info **buffer, [[maybe_unused]] const std::size_t count) {
- if constexpr(sizeof...(Type) == 0u) {
- return {};
- } else {
- // NOLINTNEXTLINE(cppcoreguidelines-avoid-c-arrays, modernize-avoid-c-arrays)
- const type_info *info[]{&type_id<Type>()...};
- const auto length = count < sizeof...(Type) ? count : sizeof...(Type);
- for(std::size_t pos{}; pos < length; ++pos) {
- // NOLINTNEXTLINE(cppcoreguidelines-pro-bounds-pointer-arithmetic)
- buffer[pos] = info[pos];
- }
- return length;
- }
- }
- template<typename... RO, typename... RW>
- void track_dependencies(std::size_t index, const bool sync_point, type_list<RO...>, type_list<RW...>) {
- builder.bind(static_cast<id_type>(index));
- builder.set(type_hash<Registry>::value(), sync_point || (sizeof...(RO) + sizeof...(RW) == 0u));
- (builder.ro(type_hash<RO>::value()), ...);
- (builder.rw(type_hash<RW>::value()), ...);
- }
- public:
- /*! Basic registry type. */
- using registry_type = Registry;
- /*! @brief Underlying entity identifier. */
- using entity_type = typename registry_type::entity_type;
- /*! @brief Unsigned integer type. */
- using size_type = std::size_t;
- /*! @brief Raw task function type. */
- using function_type = callback_type;
- /*! @brief Vertex type of a task graph defined as an adjacency list. */
- struct vertex {
- /**
- * @brief Constructs a vertex of the task graph.
- * @param data The data associated with the vertex.
- * @param from List of in-edges of the vertex.
- * @param to List of out-edges of the vertex.
- */
- vertex(vertex_data data, std::vector<std::size_t> from, std::vector<std::size_t> to)
- : node{std::move(data)},
- in{std::move(from)},
- out{std::move(to)} {}
- /**
- * @brief Fills a buffer with the type info objects for the writable
- * resources of a vertex.
- * @param buffer A buffer pre-allocated by the user.
- * @param length The length of the user-supplied buffer.
- * @return The number of type info objects written to the buffer.
- */
- [[nodiscard]] size_type ro_dependency(const type_info **buffer, const std::size_t length) const noexcept {
- return node.dependency(false, buffer, length);
- }
- /**
- * @brief Fills a buffer with the type info objects for the read-only
- * resources of a vertex.
- * @param buffer A buffer pre-allocated by the user.
- * @param length The length of the user-supplied buffer.
- * @return The number of type info objects written to the buffer.
- */
- [[nodiscard]] size_type rw_dependency(const type_info **buffer, const std::size_t length) const noexcept {
- return node.dependency(true, buffer, length);
- }
- /**
- * @brief Returns the number of read-only resources of a vertex.
- * @return The number of read-only resources of the vertex.
- */
- [[nodiscard]] size_type ro_count() const noexcept {
- return node.ro_count;
- }
- /**
- * @brief Returns the number of writable resources of a vertex.
- * @return The number of writable resources of the vertex.
- */
- [[nodiscard]] size_type rw_count() const noexcept {
- return node.rw_count;
- }
- /**
- * @brief Checks if a vertex is also a top-level one.
- * @return True if the vertex is a top-level one, false otherwise.
- */
- [[nodiscard]] bool top_level() const noexcept {
- return in.empty();
- }
- /**
- * @brief Returns a type info object associated with a vertex.
- * @return A properly initialized type info object.
- */
- [[nodiscard]] const type_info &info() const noexcept {
- return *node.info;
- }
- /**
- * @brief Returns a user defined name associated with a vertex, if any.
- * @return The user defined name associated with the vertex, if any.
- */
- [[nodiscard]] const char *name() const noexcept {
- return node.name;
- }
- /**
- * @brief Returns the function associated with a vertex.
- * @return The function associated with the vertex.
- */
- [[nodiscard]] function_type *callback() const noexcept {
- return node.callback;
- }
- /**
- * @brief Returns the payload associated with a vertex, if any.
- * @return The payload associated with the vertex, if any.
- */
- [[nodiscard]] const void *data() const noexcept {
- return node.payload;
- }
- /**
- * @brief Returns the list of in-edges of a vertex.
- * @return The list of in-edges of a vertex.
- */
- [[nodiscard]] const std::vector<std::size_t> &in_edges() const noexcept {
- return in;
- }
- /**
- * @brief Returns the list of out-edges of a vertex.
- * @return The list of out-edges of a vertex.
- */
- [[nodiscard]] const std::vector<std::size_t> &out_edges() const noexcept {
- return out;
- }
- /**
- * @brief Prepares a registry and assures that all required resources
- * are properly instantiated before using them.
- * @param reg A valid registry.
- */
- void prepare(registry_type ®) const {
- node.prepare ? node.prepare(reg) : void();
- }
- private:
- vertex_data node;
- std::vector<std::size_t> in;
- std::vector<std::size_t> out;
- };
- /**
- * @brief Adds a free function to the task list.
- * @tparam Candidate Function to add to the task list.
- * @tparam Req Additional requirements and/or override resource access mode.
- * @param name Optional name to associate with the task.
- */
- template<auto Candidate, typename... Req>
- void emplace(const char *name = nullptr) {
- using resource_type = decltype(internal::free_function_to_resource_traits<registry_type, Req...>(Candidate));
- callback_type *callback = +[](const void *, registry_type ®) {
- std::apply(Candidate, to_args(reg, typename resource_type::args{}));
- };
- vertex_data vdata{
- resource_type::ro::size,
- resource_type::rw::size,
- name,
- nullptr,
- callback,
- +[](const bool rw, const type_info **buffer, const std::size_t length) { return rw ? fill_dependencies(typename resource_type::rw{}, buffer, length) : fill_dependencies(typename resource_type::ro{}, buffer, length); },
- +[](registry_type ®) { void(to_args(reg, typename resource_type::args{})); },
- &type_id<std::integral_constant<decltype(Candidate), Candidate>>()};
- track_dependencies(vertices.size(), resource_type::sync_point, typename resource_type::ro{}, typename resource_type::rw{});
- vertices.push_back(std::move(vdata));
- }
- /**
- * @brief Adds a free function with payload or a member function with an
- * instance to the task list.
- * @tparam Candidate Function or member to add to the task list.
- * @tparam Req Additional requirements and/or override resource access mode.
- * @tparam Type Type of class or type of payload.
- * @param value_or_instance A valid object that fits the purpose.
- * @param name Optional name to associate with the task.
- */
- template<auto Candidate, typename... Req, typename Type>
- void emplace(Type &value_or_instance, const char *name = nullptr) {
- using resource_type = decltype(internal::constrained_function_to_resource_traits<registry_type, Req...>(Candidate));
- callback_type *callback = +[](const void *payload, registry_type ®) {
- Type *curr = static_cast<Type *>(const_cast<constness_as_t<void, Type> *>(payload));
- std::apply(Candidate, std::tuple_cat(std::forward_as_tuple(*curr), to_args(reg, typename resource_type::args{})));
- };
- vertex_data vdata{
- resource_type::ro::size,
- resource_type::rw::size,
- name,
- &value_or_instance,
- callback,
- +[](const bool rw, const type_info **buffer, const std::size_t length) { return rw ? fill_dependencies(typename resource_type::rw{}, buffer, length) : fill_dependencies(typename resource_type::ro{}, buffer, length); },
- +[](registry_type ®) { void(to_args(reg, typename resource_type::args{})); },
- &type_id<std::integral_constant<decltype(Candidate), Candidate>>()};
- track_dependencies(vertices.size(), resource_type::sync_point, typename resource_type::ro{}, typename resource_type::rw{});
- vertices.push_back(std::move(vdata));
- }
- /**
- * @brief Adds an user defined function with optional payload to the task
- * list.
- * @tparam Req Additional requirements and/or override resource access mode.
- * @param func Function to add to the task list.
- * @param payload User defined arbitrary data.
- * @param name Optional name to associate with the task.
- */
- template<typename... Req>
- void emplace(function_type *func, const void *payload = nullptr, const char *name = nullptr) {
- using resource_type = internal::resource_traits<registry_type, type_list<>, type_list<Req...>>;
- track_dependencies(vertices.size(), true, typename resource_type::ro{}, typename resource_type::rw{});
- vertex_data vdata{
- resource_type::ro::size,
- resource_type::rw::size,
- name,
- payload,
- func,
- +[](const bool rw, const type_info **buffer, const std::size_t length) { return rw ? fill_dependencies(typename resource_type::rw{}, buffer, length) : fill_dependencies(typename resource_type::ro{}, buffer, length); },
- nullptr,
- &type_id<void>()};
- vertices.push_back(std::move(vdata));
- }
- /**
- * @brief Generates a task graph for the current content.
- * @return The adjacency list of the task graph.
- */
- [[nodiscard]] std::vector<vertex> graph() const {
- std::vector<vertex> adjacency_list{};
- adjacency_list.reserve(vertices.size());
- auto adjacency_matrix = builder.graph();
- for(auto curr: adjacency_matrix.vertices()) {
- std::vector<std::size_t> in{};
- std::vector<std::size_t> out{};
- for(auto &&edge: adjacency_matrix.in_edges(curr)) {
- in.push_back(edge.first);
- }
- for(auto &&edge: adjacency_matrix.out_edges(curr)) {
- out.push_back(edge.second);
- }
- adjacency_list.emplace_back(vertices[curr], std::move(in), std::move(out));
- }
- return adjacency_list;
- }
- /*! @brief Erases all elements from a container. */
- void clear() {
- builder.clear();
- vertices.clear();
- }
- private:
- std::vector<vertex_data> vertices;
- flow builder;
- };
- } // namespace entt
- #endif
- // #include "entity/ranges.hpp"
- #ifndef ENTT_ENTITY_RANGES_HPP
- #define ENTT_ENTITY_RANGES_HPP
- #if __has_include(<version>)
- # include <version>
- #
- # if defined(__cpp_lib_ranges)
- # include <ranges>
- // # include "fwd.hpp"
- template<class... Args>
- inline constexpr bool std::ranges::enable_borrowed_range<entt::basic_view<Args...>>{true};
- template<class... Args>
- inline constexpr bool std::ranges::enable_borrowed_range<entt::basic_group<Args...>>{true};
- template<class... Args>
- inline constexpr bool std::ranges::enable_view<entt::basic_view<Args...>>{true};
- template<class... Args>
- inline constexpr bool std::ranges::enable_view<entt::basic_group<Args...>>{true};
- # endif
- #endif
- #endif
- // #include "entity/registry.hpp"
- #ifndef ENTT_ENTITY_REGISTRY_HPP
- #define ENTT_ENTITY_REGISTRY_HPP
- #include <algorithm>
- #include <array>
- #include <cstddef>
- #include <functional>
- #include <iterator>
- #include <memory>
- #include <tuple>
- #include <type_traits>
- #include <utility>
- #include <vector>
- // #include "../config/config.h"
- // #include "../container/dense_map.hpp"
- #ifndef ENTT_CONTAINER_DENSE_MAP_HPP
- #define ENTT_CONTAINER_DENSE_MAP_HPP
- #include <cmath>
- #include <cstddef>
- #include <functional>
- #include <iterator>
- #include <limits>
- #include <memory>
- #include <tuple>
- #include <type_traits>
- #include <utility>
- #include <vector>
- // #include "../config/config.h"
- #ifndef ENTT_CONFIG_CONFIG_H
- #define ENTT_CONFIG_CONFIG_H
- // #include "version.h"
- #ifndef ENTT_CONFIG_VERSION_H
- #define ENTT_CONFIG_VERSION_H
- // #include "macro.h"
- #ifndef ENTT_CONFIG_MACRO_H
- #define ENTT_CONFIG_MACRO_H
- // NOLINTBEGIN(cppcoreguidelines-macro-usage)
- #define ENTT_STR(arg) #arg
- #define ENTT_XSTR(arg) ENTT_STR(arg)
- // NOLINTEND(cppcoreguidelines-macro-usage)
- #endif
- // NOLINTBEGIN(cppcoreguidelines-macro-*,modernize-macro-*)
- #define ENTT_VERSION_MAJOR 3
- #define ENTT_VERSION_MINOR 16
- #define ENTT_VERSION_PATCH 0
- #define ENTT_VERSION \
- ENTT_XSTR(ENTT_VERSION_MAJOR) \
- "." ENTT_XSTR(ENTT_VERSION_MINOR) "." ENTT_XSTR(ENTT_VERSION_PATCH)
- // NOLINTEND(cppcoreguidelines-macro-*,modernize-macro-*)
- #endif
- // NOLINTBEGIN(cppcoreguidelines-macro-usage)
- #if defined(__cpp_exceptions) && !defined(ENTT_NOEXCEPTION)
- # define ENTT_CONSTEXPR
- # define ENTT_THROW throw
- # define ENTT_TRY try
- # define ENTT_CATCH catch(...)
- #else
- # define ENTT_CONSTEXPR constexpr // use only with throwing functions (waiting for C++20)
- # define ENTT_THROW
- # define ENTT_TRY if(true)
- # define ENTT_CATCH if(false)
- #endif
- #if __has_include(<version>)
- # include <version>
- #
- # if defined(__cpp_consteval)
- # define ENTT_CONSTEVAL consteval
- # endif
- #endif
- #ifndef ENTT_CONSTEVAL
- # define ENTT_CONSTEVAL constexpr
- #endif
- #ifdef ENTT_USE_ATOMIC
- # include <atomic>
- # define ENTT_MAYBE_ATOMIC(Type) std::atomic<Type>
- #else
- # define ENTT_MAYBE_ATOMIC(Type) Type
- #endif
- #ifndef ENTT_ID_TYPE
- # include <cstdint>
- # define ENTT_ID_TYPE std::uint32_t
- #else
- # include <cstdint> // provides coverage for types in the std namespace
- #endif
- #ifndef ENTT_SPARSE_PAGE
- # define ENTT_SPARSE_PAGE 4096
- #endif
- #ifndef ENTT_PACKED_PAGE
- # define ENTT_PACKED_PAGE 1024
- #endif
- #ifdef ENTT_DISABLE_ASSERT
- # undef ENTT_ASSERT
- # define ENTT_ASSERT(condition, msg) (void(0))
- #elif !defined ENTT_ASSERT
- # include <cassert>
- # define ENTT_ASSERT(condition, msg) assert(((condition) && (msg)))
- #endif
- #ifdef ENTT_DISABLE_ASSERT
- # undef ENTT_ASSERT_CONSTEXPR
- # define ENTT_ASSERT_CONSTEXPR(condition, msg) (void(0))
- #elif !defined ENTT_ASSERT_CONSTEXPR
- # define ENTT_ASSERT_CONSTEXPR(condition, msg) ENTT_ASSERT(condition, msg)
- #endif
- #define ENTT_FAIL(msg) ENTT_ASSERT(false, msg);
- #ifdef ENTT_NO_ETO
- # define ENTT_ETO_TYPE(Type) void
- #else
- # define ENTT_ETO_TYPE(Type) Type
- #endif
- #ifdef ENTT_NO_MIXIN
- # define ENTT_STORAGE(Mixin, ...) __VA_ARGS__
- #else
- # define ENTT_STORAGE(Mixin, ...) Mixin<__VA_ARGS__>
- #endif
- #ifdef ENTT_STANDARD_CPP
- # define ENTT_NONSTD false
- #else
- # define ENTT_NONSTD true
- # if defined __clang__ || defined __GNUC__
- # define ENTT_PRETTY_FUNCTION __PRETTY_FUNCTION__
- # define ENTT_PRETTY_FUNCTION_PREFIX '='
- # define ENTT_PRETTY_FUNCTION_SUFFIX ']'
- # elif defined _MSC_VER
- # define ENTT_PRETTY_FUNCTION __FUNCSIG__
- # define ENTT_PRETTY_FUNCTION_PREFIX '<'
- # define ENTT_PRETTY_FUNCTION_SUFFIX '>'
- # endif
- #endif
- #ifndef ENTT_EXPORT
- # if defined _WIN32 || defined __CYGWIN__ || defined _MSC_VER
- # define ENTT_EXPORT __declspec(dllexport)
- # define ENTT_IMPORT __declspec(dllimport)
- # define ENTT_HIDDEN
- # elif defined __GNUC__ && __GNUC__ >= 4
- # define ENTT_EXPORT __attribute__((visibility("default")))
- # define ENTT_IMPORT __attribute__((visibility("default")))
- # define ENTT_HIDDEN __attribute__((visibility("hidden")))
- # else /* Unsupported compiler */
- # define ENTT_EXPORT
- # define ENTT_IMPORT
- # define ENTT_HIDDEN
- # endif
- #endif
- #ifndef ENTT_API
- # if defined ENTT_API_EXPORT
- # define ENTT_API ENTT_EXPORT
- # elif defined ENTT_API_IMPORT
- # define ENTT_API ENTT_IMPORT
- # else /* No API */
- # define ENTT_API
- # endif
- #endif
- #if defined _MSC_VER
- # pragma detect_mismatch("entt.version", ENTT_VERSION)
- # pragma detect_mismatch("entt.noexcept", ENTT_XSTR(ENTT_TRY))
- # pragma detect_mismatch("entt.id", ENTT_XSTR(ENTT_ID_TYPE))
- # pragma detect_mismatch("entt.nonstd", ENTT_XSTR(ENTT_NONSTD))
- #endif
- // NOLINTEND(cppcoreguidelines-macro-usage)
- #endif
- // #include "../core/bit.hpp"
- #ifndef ENTT_CORE_BIT_HPP
- #define ENTT_CORE_BIT_HPP
- #include <cstddef>
- #include <limits>
- #include <type_traits>
- // #include "../config/config.h"
- #ifndef ENTT_CONFIG_CONFIG_H
- #define ENTT_CONFIG_CONFIG_H
- // #include "version.h"
- #ifndef ENTT_CONFIG_VERSION_H
- #define ENTT_CONFIG_VERSION_H
- // #include "macro.h"
- #ifndef ENTT_CONFIG_MACRO_H
- #define ENTT_CONFIG_MACRO_H
- // NOLINTBEGIN(cppcoreguidelines-macro-usage)
- #define ENTT_STR(arg) #arg
- #define ENTT_XSTR(arg) ENTT_STR(arg)
- // NOLINTEND(cppcoreguidelines-macro-usage)
- #endif
- // NOLINTBEGIN(cppcoreguidelines-macro-*,modernize-macro-*)
- #define ENTT_VERSION_MAJOR 3
- #define ENTT_VERSION_MINOR 16
- #define ENTT_VERSION_PATCH 0
- #define ENTT_VERSION \
- ENTT_XSTR(ENTT_VERSION_MAJOR) \
- "." ENTT_XSTR(ENTT_VERSION_MINOR) "." ENTT_XSTR(ENTT_VERSION_PATCH)
- // NOLINTEND(cppcoreguidelines-macro-*,modernize-macro-*)
- #endif
- // NOLINTBEGIN(cppcoreguidelines-macro-usage)
- #if defined(__cpp_exceptions) && !defined(ENTT_NOEXCEPTION)
- # define ENTT_CONSTEXPR
- # define ENTT_THROW throw
- # define ENTT_TRY try
- # define ENTT_CATCH catch(...)
- #else
- # define ENTT_CONSTEXPR constexpr // use only with throwing functions (waiting for C++20)
- # define ENTT_THROW
- # define ENTT_TRY if(true)
- # define ENTT_CATCH if(false)
- #endif
- #if __has_include(<version>)
- # include <version>
- #
- # if defined(__cpp_consteval)
- # define ENTT_CONSTEVAL consteval
- # endif
- #endif
- #ifndef ENTT_CONSTEVAL
- # define ENTT_CONSTEVAL constexpr
- #endif
- #ifdef ENTT_USE_ATOMIC
- # include <atomic>
- # define ENTT_MAYBE_ATOMIC(Type) std::atomic<Type>
- #else
- # define ENTT_MAYBE_ATOMIC(Type) Type
- #endif
- #ifndef ENTT_ID_TYPE
- # include <cstdint>
- # define ENTT_ID_TYPE std::uint32_t
- #else
- # include <cstdint> // provides coverage for types in the std namespace
- #endif
- #ifndef ENTT_SPARSE_PAGE
- # define ENTT_SPARSE_PAGE 4096
- #endif
- #ifndef ENTT_PACKED_PAGE
- # define ENTT_PACKED_PAGE 1024
- #endif
- #ifdef ENTT_DISABLE_ASSERT
- # undef ENTT_ASSERT
- # define ENTT_ASSERT(condition, msg) (void(0))
- #elif !defined ENTT_ASSERT
- # include <cassert>
- # define ENTT_ASSERT(condition, msg) assert(((condition) && (msg)))
- #endif
- #ifdef ENTT_DISABLE_ASSERT
- # undef ENTT_ASSERT_CONSTEXPR
- # define ENTT_ASSERT_CONSTEXPR(condition, msg) (void(0))
- #elif !defined ENTT_ASSERT_CONSTEXPR
- # define ENTT_ASSERT_CONSTEXPR(condition, msg) ENTT_ASSERT(condition, msg)
- #endif
- #define ENTT_FAIL(msg) ENTT_ASSERT(false, msg);
- #ifdef ENTT_NO_ETO
- # define ENTT_ETO_TYPE(Type) void
- #else
- # define ENTT_ETO_TYPE(Type) Type
- #endif
- #ifdef ENTT_NO_MIXIN
- # define ENTT_STORAGE(Mixin, ...) __VA_ARGS__
- #else
- # define ENTT_STORAGE(Mixin, ...) Mixin<__VA_ARGS__>
- #endif
- #ifdef ENTT_STANDARD_CPP
- # define ENTT_NONSTD false
- #else
- # define ENTT_NONSTD true
- # if defined __clang__ || defined __GNUC__
- # define ENTT_PRETTY_FUNCTION __PRETTY_FUNCTION__
- # define ENTT_PRETTY_FUNCTION_PREFIX '='
- # define ENTT_PRETTY_FUNCTION_SUFFIX ']'
- # elif defined _MSC_VER
- # define ENTT_PRETTY_FUNCTION __FUNCSIG__
- # define ENTT_PRETTY_FUNCTION_PREFIX '<'
- # define ENTT_PRETTY_FUNCTION_SUFFIX '>'
- # endif
- #endif
- #ifndef ENTT_EXPORT
- # if defined _WIN32 || defined __CYGWIN__ || defined _MSC_VER
- # define ENTT_EXPORT __declspec(dllexport)
- # define ENTT_IMPORT __declspec(dllimport)
- # define ENTT_HIDDEN
- # elif defined __GNUC__ && __GNUC__ >= 4
- # define ENTT_EXPORT __attribute__((visibility("default")))
- # define ENTT_IMPORT __attribute__((visibility("default")))
- # define ENTT_HIDDEN __attribute__((visibility("hidden")))
- # else /* Unsupported compiler */
- # define ENTT_EXPORT
- # define ENTT_IMPORT
- # define ENTT_HIDDEN
- # endif
- #endif
- #ifndef ENTT_API
- # if defined ENTT_API_EXPORT
- # define ENTT_API ENTT_EXPORT
- # elif defined ENTT_API_IMPORT
- # define ENTT_API ENTT_IMPORT
- # else /* No API */
- # define ENTT_API
- # endif
- #endif
- #if defined _MSC_VER
- # pragma detect_mismatch("entt.version", ENTT_VERSION)
- # pragma detect_mismatch("entt.noexcept", ENTT_XSTR(ENTT_TRY))
- # pragma detect_mismatch("entt.id", ENTT_XSTR(ENTT_ID_TYPE))
- # pragma detect_mismatch("entt.nonstd", ENTT_XSTR(ENTT_NONSTD))
- #endif
- // NOLINTEND(cppcoreguidelines-macro-usage)
- #endif
- namespace entt {
- /**
- * @brief Returns the number of set bits in a value (waiting for C++20 and
- * `std::popcount`).
- * @tparam Type Unsigned integer type.
- * @param value A value of unsigned integer type.
- * @return The number of set bits in the value.
- */
- template<typename Type>
- [[nodiscard]] constexpr std::enable_if_t<std::is_unsigned_v<Type>, int> popcount(const Type value) noexcept {
- return value ? (int(value & 1) + popcount(static_cast<Type>(value >> 1))) : 0;
- }
- /**
- * @brief Checks whether a value is a power of two or not (waiting for C++20 and
- * `std::has_single_bit`).
- * @tparam Type Unsigned integer type.
- * @param value A value of unsigned integer type.
- * @return True if the value is a power of two, false otherwise.
- */
- template<typename Type>
- [[nodiscard]] constexpr std::enable_if_t<std::is_unsigned_v<Type>, bool> has_single_bit(const Type value) noexcept {
- return value && ((value & (value - 1)) == 0);
- }
- /**
- * @brief Computes the smallest power of two greater than or equal to a value
- * (waiting for C++20 and `std::bit_ceil`).
- * @tparam Type Unsigned integer type.
- * @param value A value of unsigned integer type.
- * @return The smallest power of two greater than or equal to the given value.
- */
- template<typename Type>
- [[nodiscard]] constexpr std::enable_if_t<std::is_unsigned_v<Type>, Type> next_power_of_two(const Type value) noexcept {
- // NOLINTNEXTLINE(bugprone-assert-side-effect)
- ENTT_ASSERT_CONSTEXPR(value < (Type{1u} << (std::numeric_limits<Type>::digits - 1)), "Numeric limits exceeded");
- Type curr = value - (value != 0u);
- for(int next = 1; next < std::numeric_limits<Type>::digits; next = next * 2) {
- curr |= (curr >> next);
- }
- return ++curr;
- }
- /**
- * @brief Fast module utility function (powers of two only).
- * @tparam Type Unsigned integer type.
- * @param value A value of unsigned integer type.
- * @param mod _Modulus_, it must be a power of two.
- * @return The common remainder.
- */
- template<typename Type>
- [[nodiscard]] constexpr std::enable_if_t<std::is_unsigned_v<Type>, Type> fast_mod(const Type value, const std::size_t mod) noexcept {
- ENTT_ASSERT_CONSTEXPR(has_single_bit(mod), "Value must be a power of two");
- return static_cast<Type>(value & (mod - 1u));
- }
- } // namespace entt
- #endif
- // #include "../core/compressed_pair.hpp"
- #ifndef ENTT_CORE_COMPRESSED_PAIR_HPP
- #define ENTT_CORE_COMPRESSED_PAIR_HPP
- #include <cstddef>
- #include <tuple>
- #include <type_traits>
- #include <utility>
- // #include "fwd.hpp"
- #ifndef ENTT_CORE_FWD_HPP
- #define ENTT_CORE_FWD_HPP
- #include <cstddef>
- #include <cstdint>
- // #include "../config/config.h"
- namespace entt {
- /*! @brief Possible modes of an any object. */
- enum class any_policy : std::uint8_t {
- /*! @brief Default mode, no element available. */
- empty,
- /*! @brief Owning mode, dynamically allocated element. */
- dynamic,
- /*! @brief Owning mode, embedded element. */
- embedded,
- /*! @brief Aliasing mode, non-const reference. */
- ref,
- /*! @brief Const aliasing mode, const reference. */
- cref
- };
- // NOLINTNEXTLINE(cppcoreguidelines-avoid-c-arrays, modernize-avoid-c-arrays)
- template<std::size_t Len = sizeof(double[2]), std::size_t = alignof(double[2])>
- class basic_any;
- /*! @brief Alias declaration for type identifiers. */
- using id_type = ENTT_ID_TYPE;
- /*! @brief Alias declaration for the most common use case. */
- using any = basic_any<>;
- template<typename, typename>
- class compressed_pair;
- template<typename>
- class basic_hashed_string;
- /*! @brief Aliases for common character types. */
- using hashed_string = basic_hashed_string<char>;
- /*! @brief Aliases for common character types. */
- using hashed_wstring = basic_hashed_string<wchar_t>;
- // NOLINTNEXTLINE(bugprone-forward-declaration-namespace)
- struct type_info;
- } // namespace entt
- #endif
- // #include "type_traits.hpp"
- #ifndef ENTT_CORE_TYPE_TRAITS_HPP
- #define ENTT_CORE_TYPE_TRAITS_HPP
- #include <cstddef>
- #include <iterator>
- #include <tuple>
- #include <type_traits>
- #include <utility>
- // #include "../config/config.h"
- // #include "fwd.hpp"
- namespace entt {
- /**
- * @brief Utility class to disambiguate overloaded functions.
- * @tparam N Number of choices available.
- */
- template<std::size_t N>
- struct choice_t
- // unfortunately, doxygen cannot parse such a construct
- : /*! @cond TURN_OFF_DOXYGEN */ choice_t<N - 1> /*! @endcond */
- {};
- /*! @copybrief choice_t */
- template<>
- struct choice_t<0> {};
- /**
- * @brief Variable template for the choice trick.
- * @tparam N Number of choices available.
- */
- template<std::size_t N>
- inline constexpr choice_t<N> choice{};
- /**
- * @brief Identity type trait.
- *
- * Useful to establish non-deduced contexts in template argument deduction
- * (waiting for C++20) or to provide types through function arguments.
- *
- * @tparam Type A type.
- */
- template<typename Type>
- struct type_identity {
- /*! @brief Identity type. */
- using type = Type;
- };
- /**
- * @brief Helper type.
- * @tparam Type A type.
- */
- template<typename Type>
- using type_identity_t = typename type_identity<Type>::type;
- /**
- * @brief A type-only `sizeof` wrapper that returns 0 where `sizeof` complains.
- * @tparam Type The type of which to return the size.
- */
- template<typename Type, typename = void>
- struct size_of: std::integral_constant<std::size_t, 0u> {};
- /*! @copydoc size_of */
- template<typename Type>
- struct size_of<Type, std::void_t<decltype(sizeof(Type))>>
- // NOLINTNEXTLINE(bugprone-sizeof-expression)
- : std::integral_constant<std::size_t, sizeof(Type)> {};
- /**
- * @brief Helper variable template.
- * @tparam Type The type of which to return the size.
- */
- template<typename Type>
- inline constexpr std::size_t size_of_v = size_of<Type>::value;
- /**
- * @brief Using declaration to be used to _repeat_ the same type a number of
- * times equal to the size of a given parameter pack.
- * @tparam Type A type to repeat.
- */
- template<typename Type, typename>
- using unpack_as_type = Type;
- /**
- * @brief Helper variable template to be used to _repeat_ the same value a
- * number of times equal to the size of a given parameter pack.
- * @tparam Value A value to repeat.
- */
- template<auto Value, typename>
- inline constexpr auto unpack_as_value = Value;
- /**
- * @brief Wraps a static constant.
- * @tparam Value A static constant.
- */
- template<auto Value>
- using integral_constant = std::integral_constant<decltype(Value), Value>;
- /**
- * @brief Alias template to facilitate the creation of named values.
- * @tparam Value A constant value at least convertible to `id_type`.
- */
- template<id_type Value>
- using tag = integral_constant<Value>;
- /**
- * @brief A class to use to push around lists of types, nothing more.
- * @tparam Type Types provided by the type list.
- */
- template<typename... Type>
- struct type_list {
- /*! @brief Type list type. */
- using type = type_list;
- /*! @brief Compile-time number of elements in the type list. */
- static constexpr auto size = sizeof...(Type);
- };
- /*! @brief Primary template isn't defined on purpose. */
- template<std::size_t, typename>
- struct type_list_element;
- /**
- * @brief Provides compile-time indexed access to the types of a type list.
- * @tparam Index Index of the type to return.
- * @tparam First First type provided by the type list.
- * @tparam Other Other types provided by the type list.
- */
- template<std::size_t Index, typename First, typename... Other>
- struct type_list_element<Index, type_list<First, Other...>>
- : type_list_element<Index - 1u, type_list<Other...>> {};
- /**
- * @brief Provides compile-time indexed access to the types of a type list.
- * @tparam First First type provided by the type list.
- * @tparam Other Other types provided by the type list.
- */
- template<typename First, typename... Other>
- struct type_list_element<0u, type_list<First, Other...>> {
- /*! @brief Searched type. */
- using type = First;
- };
- /**
- * @brief Helper type.
- * @tparam Index Index of the type to return.
- * @tparam List Type list to search into.
- */
- template<std::size_t Index, typename List>
- using type_list_element_t = typename type_list_element<Index, List>::type;
- /*! @brief Primary template isn't defined on purpose. */
- template<typename, typename>
- struct type_list_index;
- /**
- * @brief Provides compile-time type access to the types of a type list.
- * @tparam Type Type to look for and for which to return the index.
- * @tparam First First type provided by the type list.
- * @tparam Other Other types provided by the type list.
- */
- template<typename Type, typename First, typename... Other>
- struct type_list_index<Type, type_list<First, Other...>> {
- /*! @brief Unsigned integer type. */
- using value_type = std::size_t;
- /*! @brief Compile-time position of the given type in the sublist. */
- static constexpr value_type value = 1u + type_list_index<Type, type_list<Other...>>::value;
- };
- /**
- * @brief Provides compile-time type access to the types of a type list.
- * @tparam Type Type to look for and for which to return the index.
- * @tparam Other Other types provided by the type list.
- */
- template<typename Type, typename... Other>
- struct type_list_index<Type, type_list<Type, Other...>> {
- static_assert(type_list_index<Type, type_list<Other...>>::value == sizeof...(Other), "Non-unique type");
- /*! @brief Unsigned integer type. */
- using value_type = std::size_t;
- /*! @brief Compile-time position of the given type in the sublist. */
- static constexpr value_type value = 0u;
- };
- /**
- * @brief Provides compile-time type access to the types of a type list.
- * @tparam Type Type to look for and for which to return the index.
- */
- template<typename Type>
- struct type_list_index<Type, type_list<>> {
- /*! @brief Unsigned integer type. */
- using value_type = std::size_t;
- /*! @brief Compile-time position of the given type in the sublist. */
- static constexpr value_type value = 0u;
- };
- /**
- * @brief Helper variable template.
- * @tparam List Type list.
- * @tparam Type Type to look for and for which to return the index.
- */
- template<typename Type, typename List>
- inline constexpr std::size_t type_list_index_v = type_list_index<Type, List>::value;
- /**
- * @brief Concatenates multiple type lists.
- * @tparam Type Types provided by the first type list.
- * @tparam Other Types provided by the second type list.
- * @return A type list composed by the types of both the type lists.
- */
- template<typename... Type, typename... Other>
- constexpr type_list<Type..., Other...> operator+(type_list<Type...>, type_list<Other...>) {
- return {};
- }
- /*! @brief Primary template isn't defined on purpose. */
- template<typename...>
- struct type_list_cat;
- /*! @brief Concatenates multiple type lists. */
- template<>
- struct type_list_cat<> {
- /*! @brief A type list composed by the types of all the type lists. */
- using type = type_list<>;
- };
- /**
- * @brief Concatenates multiple type lists.
- * @tparam Type Types provided by the first type list.
- * @tparam Other Types provided by the second type list.
- * @tparam List Other type lists, if any.
- */
- template<typename... Type, typename... Other, typename... List>
- struct type_list_cat<type_list<Type...>, type_list<Other...>, List...> {
- /*! @brief A type list composed by the types of all the type lists. */
- using type = typename type_list_cat<type_list<Type..., Other...>, List...>::type;
- };
- /**
- * @brief Concatenates multiple type lists.
- * @tparam Type Types provided by the type list.
- */
- template<typename... Type>
- struct type_list_cat<type_list<Type...>> {
- /*! @brief A type list composed by the types of all the type lists. */
- using type = type_list<Type...>;
- };
- /**
- * @brief Helper type.
- * @tparam List Type lists to concatenate.
- */
- template<typename... List>
- using type_list_cat_t = typename type_list_cat<List...>::type;
- /*! @cond TURN_OFF_DOXYGEN */
- namespace internal {
- template<typename...>
- struct type_list_unique;
- template<typename First, typename... Other, typename... Type>
- struct type_list_unique<type_list<First, Other...>, Type...>
- : std::conditional_t<(std::is_same_v<First, Type> || ...), type_list_unique<type_list<Other...>, Type...>, type_list_unique<type_list<Other...>, Type..., First>> {};
- template<typename... Type>
- struct type_list_unique<type_list<>, Type...> {
- using type = type_list<Type...>;
- };
- } // namespace internal
- /*! @endcond */
- /**
- * @brief Removes duplicates types from a type list.
- * @tparam List Type list.
- */
- template<typename List>
- struct type_list_unique {
- /*! @brief A type list without duplicate types. */
- using type = typename internal::type_list_unique<List>::type;
- };
- /**
- * @brief Helper type.
- * @tparam List Type list.
- */
- template<typename List>
- using type_list_unique_t = typename type_list_unique<List>::type;
- /**
- * @brief Provides the member constant `value` to true if a type list contains a
- * given type, false otherwise.
- * @tparam List Type list.
- * @tparam Type Type to look for.
- */
- template<typename List, typename Type>
- struct type_list_contains;
- /**
- * @copybrief type_list_contains
- * @tparam Type Types provided by the type list.
- * @tparam Other Type to look for.
- */
- template<typename... Type, typename Other>
- struct type_list_contains<type_list<Type...>, Other>
- : std::bool_constant<(std::is_same_v<Type, Other> || ...)> {};
- /**
- * @brief Helper variable template.
- * @tparam List Type list.
- * @tparam Type Type to look for.
- */
- template<typename List, typename Type>
- inline constexpr bool type_list_contains_v = type_list_contains<List, Type>::value;
- /*! @brief Primary template isn't defined on purpose. */
- template<typename...>
- struct type_list_diff;
- /**
- * @brief Computes the difference between two type lists.
- * @tparam Type Types provided by the first type list.
- * @tparam Other Types provided by the second type list.
- */
- template<typename... Type, typename... Other>
- struct type_list_diff<type_list<Type...>, type_list<Other...>> {
- /*! @brief A type list that is the difference between the two type lists. */
- using type = type_list_cat_t<std::conditional_t<type_list_contains_v<type_list<Other...>, Type>, type_list<>, type_list<Type>>...>;
- };
- /**
- * @brief Helper type.
- * @tparam List Type lists between which to compute the difference.
- */
- template<typename... List>
- using type_list_diff_t = typename type_list_diff<List...>::type;
- /*! @brief Primary template isn't defined on purpose. */
- template<typename, template<typename...> class>
- struct type_list_transform;
- /**
- * @brief Applies a given _function_ to a type list and generate a new list.
- * @tparam Type Types provided by the type list.
- * @tparam Op Unary operation as template class with a type member named `type`.
- */
- template<typename... Type, template<typename...> class Op>
- struct type_list_transform<type_list<Type...>, Op> {
- /*! @brief Resulting type list after applying the transform function. */
- // NOLINTNEXTLINE(modernize-type-traits)
- using type = type_list<typename Op<Type>::type...>;
- };
- /**
- * @brief Helper type.
- * @tparam List Type list.
- * @tparam Op Unary operation as template class with a type member named `type`.
- */
- template<typename List, template<typename...> class Op>
- using type_list_transform_t = typename type_list_transform<List, Op>::type;
- /**
- * @brief A class to use to push around lists of constant values, nothing more.
- * @tparam Value Values provided by the value list.
- */
- template<auto... Value>
- struct value_list {
- /*! @brief Value list type. */
- using type = value_list;
- /*! @brief Compile-time number of elements in the value list. */
- static constexpr auto size = sizeof...(Value);
- };
- /*! @brief Primary template isn't defined on purpose. */
- template<std::size_t, typename>
- struct value_list_element;
- /**
- * @brief Provides compile-time indexed access to the values of a value list.
- * @tparam Index Index of the value to return.
- * @tparam Value First value provided by the value list.
- * @tparam Other Other values provided by the value list.
- */
- template<std::size_t Index, auto Value, auto... Other>
- struct value_list_element<Index, value_list<Value, Other...>>
- : value_list_element<Index - 1u, value_list<Other...>> {};
- /**
- * @brief Provides compile-time indexed access to the types of a type list.
- * @tparam Value First value provided by the value list.
- * @tparam Other Other values provided by the value list.
- */
- template<auto Value, auto... Other>
- struct value_list_element<0u, value_list<Value, Other...>> {
- /*! @brief Searched type. */
- using type = decltype(Value);
- /*! @brief Searched value. */
- static constexpr auto value = Value;
- };
- /**
- * @brief Helper type.
- * @tparam Index Index of the type to return.
- * @tparam List Value list to search into.
- */
- template<std::size_t Index, typename List>
- using value_list_element_t = typename value_list_element<Index, List>::type;
- /**
- * @brief Helper type.
- * @tparam Index Index of the value to return.
- * @tparam List Value list to search into.
- */
- template<std::size_t Index, typename List>
- inline constexpr auto value_list_element_v = value_list_element<Index, List>::value;
- /*! @brief Primary template isn't defined on purpose. */
- template<auto, typename>
- struct value_list_index;
- /**
- * @brief Provides compile-time type access to the values of a value list.
- * @tparam Value Value to look for and for which to return the index.
- * @tparam First First value provided by the value list.
- * @tparam Other Other values provided by the value list.
- */
- template<auto Value, auto First, auto... Other>
- struct value_list_index<Value, value_list<First, Other...>> {
- /*! @brief Unsigned integer type. */
- using value_type = std::size_t;
- /*! @brief Compile-time position of the given value in the sublist. */
- static constexpr value_type value = 1u + value_list_index<Value, value_list<Other...>>::value;
- };
- /**
- * @brief Provides compile-time type access to the values of a value list.
- * @tparam Value Value to look for and for which to return the index.
- * @tparam Other Other values provided by the value list.
- */
- template<auto Value, auto... Other>
- struct value_list_index<Value, value_list<Value, Other...>> {
- static_assert(value_list_index<Value, value_list<Other...>>::value == sizeof...(Other), "Non-unique type");
- /*! @brief Unsigned integer type. */
- using value_type = std::size_t;
- /*! @brief Compile-time position of the given value in the sublist. */
- static constexpr value_type value = 0u;
- };
- /**
- * @brief Provides compile-time type access to the values of a value list.
- * @tparam Value Value to look for and for which to return the index.
- */
- template<auto Value>
- struct value_list_index<Value, value_list<>> {
- /*! @brief Unsigned integer type. */
- using value_type = std::size_t;
- /*! @brief Compile-time position of the given type in the sublist. */
- static constexpr value_type value = 0u;
- };
- /**
- * @brief Helper variable template.
- * @tparam List Value list.
- * @tparam Value Value to look for and for which to return the index.
- */
- template<auto Value, typename List>
- inline constexpr std::size_t value_list_index_v = value_list_index<Value, List>::value;
- /**
- * @brief Concatenates multiple value lists.
- * @tparam Value Values provided by the first value list.
- * @tparam Other Values provided by the second value list.
- * @return A value list composed by the values of both the value lists.
- */
- template<auto... Value, auto... Other>
- constexpr value_list<Value..., Other...> operator+(value_list<Value...>, value_list<Other...>) {
- return {};
- }
- /*! @brief Primary template isn't defined on purpose. */
- template<typename...>
- struct value_list_cat;
- /*! @brief Concatenates multiple value lists. */
- template<>
- struct value_list_cat<> {
- /*! @brief A value list composed by the values of all the value lists. */
- using type = value_list<>;
- };
- /**
- * @brief Concatenates multiple value lists.
- * @tparam Value Values provided by the first value list.
- * @tparam Other Values provided by the second value list.
- * @tparam List Other value lists, if any.
- */
- template<auto... Value, auto... Other, typename... List>
- struct value_list_cat<value_list<Value...>, value_list<Other...>, List...> {
- /*! @brief A value list composed by the values of all the value lists. */
- using type = typename value_list_cat<value_list<Value..., Other...>, List...>::type;
- };
- /**
- * @brief Concatenates multiple value lists.
- * @tparam Value Values provided by the value list.
- */
- template<auto... Value>
- struct value_list_cat<value_list<Value...>> {
- /*! @brief A value list composed by the values of all the value lists. */
- using type = value_list<Value...>;
- };
- /**
- * @brief Helper type.
- * @tparam List Value lists to concatenate.
- */
- template<typename... List>
- using value_list_cat_t = typename value_list_cat<List...>::type;
- /*! @brief Primary template isn't defined on purpose. */
- template<typename>
- struct value_list_unique;
- /**
- * @brief Removes duplicates values from a value list.
- * @tparam Value One of the values provided by the given value list.
- * @tparam Other The other values provided by the given value list.
- */
- template<auto Value, auto... Other>
- struct value_list_unique<value_list<Value, Other...>> {
- /*! @brief A value list without duplicate types. */
- using type = std::conditional_t<
- ((Value == Other) || ...),
- typename value_list_unique<value_list<Other...>>::type,
- value_list_cat_t<value_list<Value>, typename value_list_unique<value_list<Other...>>::type>>;
- };
- /*! @brief Removes duplicates values from a value list. */
- template<>
- struct value_list_unique<value_list<>> {
- /*! @brief A value list without duplicate types. */
- using type = value_list<>;
- };
- /**
- * @brief Helper type.
- * @tparam Type A value list.
- */
- template<typename Type>
- using value_list_unique_t = typename value_list_unique<Type>::type;
- /**
- * @brief Provides the member constant `value` to true if a value list contains
- * a given value, false otherwise.
- * @tparam List Value list.
- * @tparam Value Value to look for.
- */
- template<typename List, auto Value>
- struct value_list_contains;
- /**
- * @copybrief value_list_contains
- * @tparam Value Values provided by the value list.
- * @tparam Other Value to look for.
- */
- template<auto... Value, auto Other>
- struct value_list_contains<value_list<Value...>, Other>
- : std::bool_constant<((Value == Other) || ...)> {};
- /**
- * @brief Helper variable template.
- * @tparam List Value list.
- * @tparam Value Value to look for.
- */
- template<typename List, auto Value>
- inline constexpr bool value_list_contains_v = value_list_contains<List, Value>::value;
- /*! @brief Primary template isn't defined on purpose. */
- template<typename...>
- struct value_list_diff;
- /**
- * @brief Computes the difference between two value lists.
- * @tparam Value Values provided by the first value list.
- * @tparam Other Values provided by the second value list.
- */
- template<auto... Value, auto... Other>
- struct value_list_diff<value_list<Value...>, value_list<Other...>> {
- /*! @brief A value list that is the difference between the two value lists. */
- using type = value_list_cat_t<std::conditional_t<value_list_contains_v<value_list<Other...>, Value>, value_list<>, value_list<Value>>...>;
- };
- /**
- * @brief Helper type.
- * @tparam List Value lists between which to compute the difference.
- */
- template<typename... List>
- using value_list_diff_t = typename value_list_diff<List...>::type;
- /*! @brief Same as std::is_invocable, but with tuples. */
- template<typename, typename>
- struct is_applicable: std::false_type {};
- /**
- * @copybrief is_applicable
- * @tparam Func A valid function type.
- * @tparam Tuple Tuple-like type.
- * @tparam Args The list of arguments to use to probe the function type.
- */
- template<typename Func, template<typename...> class Tuple, typename... Args>
- struct is_applicable<Func, Tuple<Args...>>: std::is_invocable<Func, Args...> {};
- /**
- * @copybrief is_applicable
- * @tparam Func A valid function type.
- * @tparam Tuple Tuple-like type.
- * @tparam Args The list of arguments to use to probe the function type.
- */
- template<typename Func, template<typename...> class Tuple, typename... Args>
- struct is_applicable<Func, const Tuple<Args...>>: std::is_invocable<Func, Args...> {};
- /**
- * @brief Helper variable template.
- * @tparam Func A valid function type.
- * @tparam Args The list of arguments to use to probe the function type.
- */
- template<typename Func, typename Args>
- inline constexpr bool is_applicable_v = is_applicable<Func, Args>::value;
- /*! @brief Same as std::is_invocable_r, but with tuples for arguments. */
- template<typename, typename, typename>
- struct is_applicable_r: std::false_type {};
- /**
- * @copybrief is_applicable_r
- * @tparam Ret The type to which the return type of the function should be
- * convertible.
- * @tparam Func A valid function type.
- * @tparam Args The list of arguments to use to probe the function type.
- */
- template<typename Ret, typename Func, typename... Args>
- struct is_applicable_r<Ret, Func, std::tuple<Args...>>: std::is_invocable_r<Ret, Func, Args...> {};
- /**
- * @brief Helper variable template.
- * @tparam Ret The type to which the return type of the function should be
- * convertible.
- * @tparam Func A valid function type.
- * @tparam Args The list of arguments to use to probe the function type.
- */
- template<typename Ret, typename Func, typename Args>
- inline constexpr bool is_applicable_r_v = is_applicable_r<Ret, Func, Args>::value;
- /**
- * @brief Provides the member constant `value` to true if a given type is
- * complete, false otherwise.
- * @tparam Type The type to test.
- */
- template<typename Type, typename = void>
- struct is_complete: std::false_type {};
- /*! @copydoc is_complete */
- template<typename Type>
- struct is_complete<Type, std::void_t<decltype(sizeof(Type))>>: std::true_type {};
- /**
- * @brief Helper variable template.
- * @tparam Type The type to test.
- */
- template<typename Type>
- inline constexpr bool is_complete_v = is_complete<Type>::value;
- /**
- * @brief Provides the member constant `value` to true if a given type is an
- * iterator, false otherwise.
- * @tparam Type The type to test.
- */
- template<typename Type, typename = void>
- struct is_iterator: std::false_type {};
- /*! @cond TURN_OFF_DOXYGEN */
- namespace internal {
- template<typename, typename = void>
- struct has_iterator_category: std::false_type {};
- template<typename Type>
- struct has_iterator_category<Type, std::void_t<typename std::iterator_traits<Type>::iterator_category>>: std::true_type {};
- } // namespace internal
- /*! @endcond */
- /*! @copydoc is_iterator */
- template<typename Type>
- struct is_iterator<Type, std::enable_if_t<!std::is_void_v<std::remove_const_t<std::remove_pointer_t<Type>>>>>
- : internal::has_iterator_category<Type> {};
- /**
- * @brief Helper variable template.
- * @tparam Type The type to test.
- */
- template<typename Type>
- inline constexpr bool is_iterator_v = is_iterator<Type>::value;
- /**
- * @brief Provides the member constant `value` to true if a given type is both
- * an empty and non-final class, false otherwise.
- * @tparam Type The type to test
- */
- template<typename Type>
- struct is_ebco_eligible
- : std::bool_constant<std::is_empty_v<Type> && !std::is_final_v<Type>> {};
- /**
- * @brief Helper variable template.
- * @tparam Type The type to test.
- */
- template<typename Type>
- inline constexpr bool is_ebco_eligible_v = is_ebco_eligible<Type>::value;
- /**
- * @brief Provides the member constant `value` to true if `Type::is_transparent`
- * is valid and denotes a type, false otherwise.
- * @tparam Type The type to test.
- */
- template<typename Type, typename = void>
- struct is_transparent: std::false_type {};
- /*! @copydoc is_transparent */
- template<typename Type>
- struct is_transparent<Type, std::void_t<typename Type::is_transparent>>: std::true_type {};
- /**
- * @brief Helper variable template.
- * @tparam Type The type to test.
- */
- template<typename Type>
- inline constexpr bool is_transparent_v = is_transparent<Type>::value;
- /*! @cond TURN_OFF_DOXYGEN */
- namespace internal {
- template<typename, typename = void>
- struct has_tuple_size_value: std::false_type {};
- template<typename Type>
- struct has_tuple_size_value<Type, std::void_t<decltype(std::tuple_size<const Type>::value)>>: std::true_type {};
- template<typename, typename = void>
- struct has_value_type: std::false_type {};
- template<typename Type>
- struct has_value_type<Type, std::void_t<typename Type::value_type>>: std::true_type {};
- template<typename>
- [[nodiscard]] constexpr bool dispatch_is_equality_comparable();
- template<typename Type, std::size_t... Index>
- [[nodiscard]] constexpr bool unpack_maybe_equality_comparable(std::index_sequence<Index...>) {
- return (dispatch_is_equality_comparable<std::tuple_element_t<Index, Type>>() && ...);
- }
- template<typename>
- [[nodiscard]] constexpr bool maybe_equality_comparable(char) {
- return false;
- }
- template<typename Type>
- [[nodiscard]] constexpr auto maybe_equality_comparable(int) -> decltype(std::declval<Type>() == std::declval<Type>()) {
- return true;
- }
- template<typename Type>
- [[nodiscard]] constexpr bool dispatch_is_equality_comparable() {
- // NOLINTBEGIN(modernize-use-transparent-functors)
- if constexpr(std::is_array_v<Type>) {
- return false;
- } else if constexpr(is_complete_v<std::tuple_size<std::remove_const_t<Type>>>) {
- if constexpr(has_tuple_size_value<Type>::value) {
- return maybe_equality_comparable<Type>(0) && unpack_maybe_equality_comparable<Type>(std::make_index_sequence<std::tuple_size<Type>::value>{});
- } else {
- return maybe_equality_comparable<Type>(0);
- }
- } else if constexpr(has_value_type<Type>::value) {
- if constexpr(is_iterator_v<Type> || std::is_same_v<typename Type::value_type, Type> || dispatch_is_equality_comparable<typename Type::value_type>()) {
- return maybe_equality_comparable<Type>(0);
- } else {
- return false;
- }
- } else {
- return maybe_equality_comparable<Type>(0);
- }
- // NOLINTEND(modernize-use-transparent-functors)
- }
- } // namespace internal
- /*! @endcond */
- /**
- * @brief Provides the member constant `value` to true if a given type is
- * equality comparable, false otherwise.
- * @tparam Type The type to test.
- */
- template<typename Type>
- struct is_equality_comparable: std::bool_constant<internal::dispatch_is_equality_comparable<Type>()> {};
- /*! @copydoc is_equality_comparable */
- template<typename Type>
- struct is_equality_comparable<const Type>: is_equality_comparable<Type> {};
- /**
- * @brief Helper variable template.
- * @tparam Type The type to test.
- */
- template<typename Type>
- inline constexpr bool is_equality_comparable_v = is_equality_comparable<Type>::value;
- /**
- * @brief Transcribes the constness of a type to another type.
- * @tparam To The type to which to transcribe the constness.
- * @tparam From The type from which to transcribe the constness.
- */
- template<typename To, typename From>
- struct constness_as {
- /*! @brief The type resulting from the transcription of the constness. */
- using type = std::remove_const_t<To>;
- };
- /*! @copydoc constness_as */
- template<typename To, typename From>
- struct constness_as<To, const From> {
- /*! @brief The type resulting from the transcription of the constness. */
- using type = const To;
- };
- /**
- * @brief Alias template to facilitate the transcription of the constness.
- * @tparam To The type to which to transcribe the constness.
- * @tparam From The type from which to transcribe the constness.
- */
- template<typename To, typename From>
- using constness_as_t = typename constness_as<To, From>::type;
- /**
- * @brief Extracts the class of a non-static member object or function.
- * @tparam Member A pointer to a non-static member object or function.
- */
- template<typename Member>
- class member_class {
- static_assert(std::is_member_pointer_v<Member>, "Invalid pointer type to non-static member object or function");
- template<typename Class, typename Ret, typename... Args>
- static Class *clazz(Ret (Class::*)(Args...));
- template<typename Class, typename Ret, typename... Args>
- static Class *clazz(Ret (Class::*)(Args...) const);
- template<typename Class, typename Type>
- static Class *clazz(Type Class::*);
- public:
- /*! @brief The class of the given non-static member object or function. */
- using type = std::remove_pointer_t<decltype(clazz(std::declval<Member>()))>;
- };
- /**
- * @brief Helper type.
- * @tparam Member A pointer to a non-static member object or function.
- */
- template<typename Member>
- using member_class_t = typename member_class<Member>::type;
- /**
- * @brief Extracts the n-th argument of a _callable_ type.
- * @tparam Index The index of the argument to extract.
- * @tparam Candidate A valid _callable_ type.
- */
- template<std::size_t Index, typename Candidate>
- class nth_argument {
- template<typename Ret, typename... Args>
- static constexpr type_list<Args...> pick_up(Ret (*)(Args...));
- template<typename Ret, typename Class, typename... Args>
- static constexpr type_list<Args...> pick_up(Ret (Class ::*)(Args...));
- template<typename Ret, typename Class, typename... Args>
- static constexpr type_list<Args...> pick_up(Ret (Class ::*)(Args...) const);
- template<typename Type, typename Class>
- static constexpr type_list<Type> pick_up(Type Class ::*);
- template<typename Type>
- static constexpr decltype(pick_up(&Type::operator())) pick_up(Type &&);
- public:
- /*! @brief N-th argument of the _callable_ type. */
- using type = type_list_element_t<Index, decltype(pick_up(std::declval<Candidate>()))>;
- };
- /**
- * @brief Helper type.
- * @tparam Index The index of the argument to extract.
- * @tparam Candidate A valid function, member function or data member type.
- */
- template<std::size_t Index, typename Candidate>
- using nth_argument_t = typename nth_argument<Index, Candidate>::type;
- } // namespace entt
- template<typename... Type>
- struct std::tuple_size<entt::type_list<Type...>>: std::integral_constant<std::size_t, entt::type_list<Type...>::size> {};
- template<std::size_t Index, typename... Type>
- struct std::tuple_element<Index, entt::type_list<Type...>>: entt::type_list_element<Index, entt::type_list<Type...>> {};
- template<auto... Value>
- struct std::tuple_size<entt::value_list<Value...>>: std::integral_constant<std::size_t, entt::value_list<Value...>::size> {};
- template<std::size_t Index, auto... Value>
- struct std::tuple_element<Index, entt::value_list<Value...>>: entt::value_list_element<Index, entt::value_list<Value...>> {};
- #endif
- namespace entt {
- /*! @cond TURN_OFF_DOXYGEN */
- namespace internal {
- template<typename Type, std::size_t, typename = void>
- struct compressed_pair_element {
- using reference = Type &;
- using const_reference = const Type &;
- template<typename Dummy = Type, typename = std::enable_if_t<std::is_default_constructible_v<Dummy>>>
- // NOLINTNEXTLINE(modernize-use-equals-default)
- constexpr compressed_pair_element() noexcept(std::is_nothrow_default_constructible_v<Type>) {}
- template<typename Arg, typename = std::enable_if_t<!std::is_same_v<std::remove_const_t<std::remove_reference_t<Arg>>, compressed_pair_element>>>
- constexpr compressed_pair_element(Arg &&arg) noexcept(std::is_nothrow_constructible_v<Type, Arg>)
- : value{std::forward<Arg>(arg)} {}
- template<typename... Args, std::size_t... Index>
- constexpr compressed_pair_element(std::tuple<Args...> args, std::index_sequence<Index...>) noexcept(std::is_nothrow_constructible_v<Type, Args...>)
- : value{std::forward<Args>(std::get<Index>(args))...} {}
- [[nodiscard]] constexpr reference get() noexcept {
- return value;
- }
- [[nodiscard]] constexpr const_reference get() const noexcept {
- return value;
- }
- private:
- Type value{};
- };
- template<typename Type, std::size_t Tag>
- struct compressed_pair_element<Type, Tag, std::enable_if_t<is_ebco_eligible_v<Type>>>: Type {
- using reference = Type &;
- using const_reference = const Type &;
- using base_type = Type;
- template<typename Dummy = Type, typename = std::enable_if_t<std::is_default_constructible_v<Dummy>>>
- constexpr compressed_pair_element() noexcept(std::is_nothrow_default_constructible_v<base_type>)
- : base_type{} {}
- template<typename Arg, typename = std::enable_if_t<!std::is_same_v<std::remove_const_t<std::remove_reference_t<Arg>>, compressed_pair_element>>>
- constexpr compressed_pair_element(Arg &&arg) noexcept(std::is_nothrow_constructible_v<base_type, Arg>)
- : base_type{std::forward<Arg>(arg)} {}
- template<typename... Args, std::size_t... Index>
- constexpr compressed_pair_element(std::tuple<Args...> args, std::index_sequence<Index...>) noexcept(std::is_nothrow_constructible_v<base_type, Args...>)
- : base_type{std::forward<Args>(std::get<Index>(args))...} {}
- [[nodiscard]] constexpr reference get() noexcept {
- return *this;
- }
- [[nodiscard]] constexpr const_reference get() const noexcept {
- return *this;
- }
- };
- } // namespace internal
- /*! @endcond */
- /**
- * @brief A compressed pair.
- *
- * A pair that exploits the _Empty Base Class Optimization_ (or _EBCO_) to
- * reduce its final size to a minimum.
- *
- * @tparam First The type of the first element that the pair stores.
- * @tparam Second The type of the second element that the pair stores.
- */
- template<typename First, typename Second>
- class compressed_pair final
- : internal::compressed_pair_element<First, 0u>,
- internal::compressed_pair_element<Second, 1u> {
- using first_base = internal::compressed_pair_element<First, 0u>;
- using second_base = internal::compressed_pair_element<Second, 1u>;
- public:
- /*! @brief The type of the first element that the pair stores. */
- using first_type = First;
- /*! @brief The type of the second element that the pair stores. */
- using second_type = Second;
- /**
- * @brief Default constructor, conditionally enabled.
- *
- * This constructor is only available when the types that the pair stores
- * are both at least default constructible.
- *
- * @tparam Dummy Dummy template parameter used for internal purposes.
- */
- template<bool Dummy = true, typename = std::enable_if_t<Dummy && std::is_default_constructible_v<first_type> && std::is_default_constructible_v<second_type>>>
- constexpr compressed_pair() noexcept(std::is_nothrow_default_constructible_v<first_base> && std::is_nothrow_default_constructible_v<second_base>)
- : first_base{},
- second_base{} {}
- /**
- * @brief Copy constructor.
- * @param other The instance to copy from.
- */
- constexpr compressed_pair(const compressed_pair &other) = default;
- /**
- * @brief Move constructor.
- * @param other The instance to move from.
- */
- constexpr compressed_pair(compressed_pair &&other) noexcept = default;
- /**
- * @brief Constructs a pair from its values.
- * @tparam Arg Type of value to use to initialize the first element.
- * @tparam Other Type of value to use to initialize the second element.
- * @param arg Value to use to initialize the first element.
- * @param other Value to use to initialize the second element.
- */
- template<typename Arg, typename Other>
- constexpr compressed_pair(Arg &&arg, Other &&other) noexcept(std::is_nothrow_constructible_v<first_base, Arg> && std::is_nothrow_constructible_v<second_base, Other>)
- : first_base{std::forward<Arg>(arg)},
- second_base{std::forward<Other>(other)} {}
- /**
- * @brief Constructs a pair by forwarding the arguments to its parts.
- * @tparam Args Types of arguments to use to initialize the first element.
- * @tparam Other Types of arguments to use to initialize the second element.
- * @param args Arguments to use to initialize the first element.
- * @param other Arguments to use to initialize the second element.
- */
- template<typename... Args, typename... Other>
- constexpr compressed_pair(std::piecewise_construct_t, std::tuple<Args...> args, std::tuple<Other...> other) noexcept(std::is_nothrow_constructible_v<first_base, Args...> && std::is_nothrow_constructible_v<second_base, Other...>)
- : first_base{std::move(args), std::index_sequence_for<Args...>{}},
- second_base{std::move(other), std::index_sequence_for<Other...>{}} {}
- /*! @brief Default destructor. */
- ~compressed_pair() = default;
- /**
- * @brief Copy assignment operator.
- * @param other The instance to copy from.
- * @return This compressed pair object.
- */
- constexpr compressed_pair &operator=(const compressed_pair &other) = default;
- /**
- * @brief Move assignment operator.
- * @param other The instance to move from.
- * @return This compressed pair object.
- */
- constexpr compressed_pair &operator=(compressed_pair &&other) noexcept = default;
- /**
- * @brief Returns the first element that a pair stores.
- * @return The first element that a pair stores.
- */
- [[nodiscard]] constexpr first_type &first() noexcept {
- return static_cast<first_base &>(*this).get();
- }
- /*! @copydoc first */
- [[nodiscard]] constexpr const first_type &first() const noexcept {
- return static_cast<const first_base &>(*this).get();
- }
- /**
- * @brief Returns the second element that a pair stores.
- * @return The second element that a pair stores.
- */
- [[nodiscard]] constexpr second_type &second() noexcept {
- return static_cast<second_base &>(*this).get();
- }
- /*! @copydoc second */
- [[nodiscard]] constexpr const second_type &second() const noexcept {
- return static_cast<const second_base &>(*this).get();
- }
- /**
- * @brief Swaps two compressed pair objects.
- * @param other The compressed pair to swap with.
- */
- constexpr void swap(compressed_pair &other) noexcept {
- using std::swap;
- swap(first(), other.first());
- swap(second(), other.second());
- }
- /**
- * @brief Extracts an element from the compressed pair.
- * @tparam Index An integer value that is either 0 or 1.
- * @return Returns a reference to the first element if `Index` is 0 and a
- * reference to the second element if `Index` is 1.
- */
- template<std::size_t Index>
- [[nodiscard]] constexpr decltype(auto) get() noexcept {
- if constexpr(Index == 0u) {
- return first();
- } else {
- static_assert(Index == 1u, "Index out of bounds");
- return second();
- }
- }
- /*! @copydoc get */
- template<std::size_t Index>
- [[nodiscard]] constexpr decltype(auto) get() const noexcept {
- if constexpr(Index == 0u) {
- return first();
- } else {
- static_assert(Index == 1u, "Index out of bounds");
- return second();
- }
- }
- };
- /**
- * @brief Deduction guide.
- * @tparam Type Type of value to use to initialize the first element.
- * @tparam Other Type of value to use to initialize the second element.
- */
- template<typename Type, typename Other>
- compressed_pair(Type &&, Other &&) -> compressed_pair<std::decay_t<Type>, std::decay_t<Other>>;
- /**
- * @brief Swaps two compressed pair objects.
- * @tparam First The type of the first element that the pairs store.
- * @tparam Second The type of the second element that the pairs store.
- * @param lhs A valid compressed pair object.
- * @param rhs A valid compressed pair object.
- */
- template<typename First, typename Second>
- constexpr void swap(compressed_pair<First, Second> &lhs, compressed_pair<First, Second> &rhs) noexcept {
- lhs.swap(rhs);
- }
- } // namespace entt
- namespace std {
- /**
- * @brief `std::tuple_size` specialization for `compressed_pair`s.
- * @tparam First The type of the first element that the pair stores.
- * @tparam Second The type of the second element that the pair stores.
- */
- template<typename First, typename Second>
- struct tuple_size<entt::compressed_pair<First, Second>>: integral_constant<size_t, 2u> {};
- /**
- * @brief `std::tuple_element` specialization for `compressed_pair`s.
- * @tparam Index The index of the type to return.
- * @tparam First The type of the first element that the pair stores.
- * @tparam Second The type of the second element that the pair stores.
- */
- template<size_t Index, typename First, typename Second>
- struct tuple_element<Index, entt::compressed_pair<First, Second>>: conditional<Index == 0u, First, Second> {
- static_assert(Index < 2u, "Index out of bounds");
- };
- } // namespace std
- #endif
- // #include "../core/iterator.hpp"
- #ifndef ENTT_CORE_ITERATOR_HPP
- #define ENTT_CORE_ITERATOR_HPP
- #include <iterator>
- #include <memory>
- #include <type_traits>
- #include <utility>
- namespace entt {
- /**
- * @brief Helper type to use as pointer with input iterators.
- * @tparam Type of wrapped value.
- */
- template<typename Type>
- struct input_iterator_pointer final {
- /*! @brief Value type. */
- using value_type = Type;
- /*! @brief Pointer type. */
- using pointer = Type *;
- /*! @brief Reference type. */
- using reference = Type &;
- /**
- * @brief Constructs a proxy object by move.
- * @param val Value to use to initialize the proxy object.
- */
- constexpr input_iterator_pointer(value_type &&val) noexcept(std::is_nothrow_move_constructible_v<value_type>)
- : value{std::move(val)} {}
- /**
- * @brief Access operator for accessing wrapped values.
- * @return A pointer to the wrapped value.
- */
- [[nodiscard]] constexpr pointer operator->() noexcept {
- return std::addressof(value);
- }
- /**
- * @brief Dereference operator for accessing wrapped values.
- * @return A reference to the wrapped value.
- */
- [[nodiscard]] constexpr reference operator*() noexcept {
- return value;
- }
- private:
- Type value;
- };
- /**
- * @brief Plain iota iterator (waiting for C++20).
- * @tparam Type Value type.
- */
- template<typename Type>
- class iota_iterator final {
- static_assert(std::is_integral_v<Type>, "Not an integral type");
- public:
- /*! @brief Value type, likely an integral one. */
- using value_type = Type;
- /*! @brief Invalid pointer type. */
- using pointer = void;
- /*! @brief Non-reference type, same as value type. */
- using reference = value_type;
- /*! @brief Difference type. */
- using difference_type = std::ptrdiff_t;
- /*! @brief Iterator category. */
- using iterator_category = std::input_iterator_tag;
- /*! @brief Default constructor. */
- constexpr iota_iterator() noexcept
- : current{} {}
- /**
- * @brief Constructs an iota iterator from a given value.
- * @param init The initial value assigned to the iota iterator.
- */
- constexpr iota_iterator(const value_type init) noexcept
- : current{init} {}
- /**
- * @brief Pre-increment operator.
- * @return This iota iterator.
- */
- constexpr iota_iterator &operator++() noexcept {
- return ++current, *this;
- }
- /**
- * @brief Post-increment operator.
- * @return This iota iterator.
- */
- constexpr iota_iterator operator++(int) noexcept {
- const iota_iterator orig = *this;
- return ++(*this), orig;
- }
- /**
- * @brief Dereference operator.
- * @return The underlying value.
- */
- [[nodiscard]] constexpr reference operator*() const noexcept {
- return current;
- }
- private:
- value_type current;
- };
- /**
- * @brief Comparison operator.
- * @tparam Type Value type of the iota iterator.
- * @param lhs A properly initialized iota iterator.
- * @param rhs A properly initialized iota iterator.
- * @return True if the two iterators are identical, false otherwise.
- */
- template<typename Type>
- [[nodiscard]] constexpr bool operator==(const iota_iterator<Type> &lhs, const iota_iterator<Type> &rhs) noexcept {
- return *lhs == *rhs;
- }
- /**
- * @brief Comparison operator.
- * @tparam Type Value type of the iota iterator.
- * @param lhs A properly initialized iota iterator.
- * @param rhs A properly initialized iota iterator.
- * @return True if the two iterators differ, false otherwise.
- */
- template<typename Type>
- [[nodiscard]] constexpr bool operator!=(const iota_iterator<Type> &lhs, const iota_iterator<Type> &rhs) noexcept {
- return !(lhs == rhs);
- }
- /**
- * @brief Utility class to create an iterable object from a pair of iterators.
- * @tparam It Type of iterator.
- * @tparam Sentinel Type of sentinel.
- */
- template<typename It, typename Sentinel = It>
- struct iterable_adaptor final {
- /*! @brief Value type. */
- using value_type = typename std::iterator_traits<It>::value_type;
- /*! @brief Iterator type. */
- using iterator = It;
- /*! @brief Sentinel type. */
- using sentinel = Sentinel;
- /*! @brief Default constructor. */
- constexpr iterable_adaptor() noexcept(std::is_nothrow_default_constructible_v<iterator> && std::is_nothrow_default_constructible_v<sentinel>)
- : first{},
- last{} {}
- /**
- * @brief Creates an iterable object from a pair of iterators.
- * @param from Begin iterator.
- * @param to End iterator.
- */
- constexpr iterable_adaptor(iterator from, sentinel to) noexcept(std::is_nothrow_move_constructible_v<iterator> && std::is_nothrow_move_constructible_v<sentinel>)
- : first{std::move(from)},
- last{std::move(to)} {}
- /**
- * @brief Returns an iterator to the beginning.
- * @return An iterator to the first element of the range.
- */
- [[nodiscard]] constexpr iterator begin() const noexcept {
- return first;
- }
- /**
- * @brief Returns an iterator to the end.
- * @return An iterator to the element following the last element of the
- * range.
- */
- [[nodiscard]] constexpr sentinel end() const noexcept {
- return last;
- }
- /*! @copydoc begin */
- [[nodiscard]] constexpr iterator cbegin() const noexcept {
- return begin();
- }
- /*! @copydoc end */
- [[nodiscard]] constexpr sentinel cend() const noexcept {
- return end();
- }
- private:
- It first;
- Sentinel last;
- };
- } // namespace entt
- #endif
- // #include "../core/memory.hpp"
- #ifndef ENTT_CORE_MEMORY_HPP
- #define ENTT_CORE_MEMORY_HPP
- #include <cstddef>
- #include <memory>
- #include <tuple>
- #include <type_traits>
- #include <utility>
- // #include "../config/config.h"
- namespace entt {
- /**
- * @brief Unwraps fancy pointers, does nothing otherwise (waiting for C++20).
- * @tparam Type Pointer type.
- * @param ptr Fancy or raw pointer.
- * @return A raw pointer that represents the address of the original pointer.
- */
- template<typename Type>
- [[nodiscard]] constexpr auto to_address(Type &&ptr) noexcept {
- if constexpr(std::is_pointer_v<std::decay_t<Type>>) {
- return ptr;
- } else {
- return to_address(std::forward<Type>(ptr).operator->());
- }
- }
- /**
- * @brief Utility function to design allocation-aware containers.
- * @tparam Allocator Type of allocator.
- * @param lhs A valid allocator.
- * @param rhs Another valid allocator.
- */
- template<typename Allocator>
- constexpr void propagate_on_container_copy_assignment([[maybe_unused]] Allocator &lhs, [[maybe_unused]] Allocator &rhs) noexcept {
- if constexpr(std::allocator_traits<Allocator>::propagate_on_container_copy_assignment::value) {
- lhs = rhs;
- }
- }
- /**
- * @brief Utility function to design allocation-aware containers.
- * @tparam Allocator Type of allocator.
- * @param lhs A valid allocator.
- * @param rhs Another valid allocator.
- */
- template<typename Allocator>
- constexpr void propagate_on_container_move_assignment([[maybe_unused]] Allocator &lhs, [[maybe_unused]] Allocator &rhs) noexcept {
- if constexpr(std::allocator_traits<Allocator>::propagate_on_container_move_assignment::value) {
- lhs = std::move(rhs);
- }
- }
- /**
- * @brief Utility function to design allocation-aware containers.
- * @tparam Allocator Type of allocator.
- * @param lhs A valid allocator.
- * @param rhs Another valid allocator.
- */
- template<typename Allocator>
- constexpr void propagate_on_container_swap([[maybe_unused]] Allocator &lhs, [[maybe_unused]] Allocator &rhs) noexcept {
- if constexpr(std::allocator_traits<Allocator>::propagate_on_container_swap::value) {
- using std::swap;
- swap(lhs, rhs);
- } else {
- ENTT_ASSERT_CONSTEXPR(lhs == rhs, "Cannot swap the containers");
- }
- }
- /**
- * @brief Deleter for allocator-aware unique pointers (waiting for C++20).
- * @tparam Allocator Type of allocator used to manage memory and elements.
- */
- template<typename Allocator>
- struct allocation_deleter: private Allocator {
- /*! @brief Allocator type. */
- using allocator_type = Allocator;
- /*! @brief Pointer type. */
- using pointer = typename std::allocator_traits<Allocator>::pointer;
- /**
- * @brief Inherited constructors.
- * @param alloc The allocator to use.
- */
- constexpr allocation_deleter(const allocator_type &alloc) noexcept(std::is_nothrow_copy_constructible_v<allocator_type>)
- : Allocator{alloc} {}
- /**
- * @brief Destroys the pointed object and deallocates its memory.
- * @param ptr A valid pointer to an object of the given type.
- */
- constexpr void operator()(pointer ptr) noexcept(std::is_nothrow_destructible_v<typename allocator_type::value_type>) {
- using alloc_traits = std::allocator_traits<Allocator>;
- alloc_traits::destroy(*this, to_address(ptr));
- alloc_traits::deallocate(*this, ptr, 1u);
- }
- };
- /**
- * @brief Allows `std::unique_ptr` to use allocators (waiting for C++20).
- * @tparam Type Type of object to allocate for and to construct.
- * @tparam Allocator Type of allocator used to manage memory and elements.
- * @tparam Args Types of arguments to use to construct the object.
- * @param allocator The allocator to use.
- * @param args Parameters to use to construct the object.
- * @return A properly initialized unique pointer with a custom deleter.
- */
- template<typename Type, typename Allocator, typename... Args>
- ENTT_CONSTEXPR auto allocate_unique(Allocator &allocator, Args &&...args) {
- static_assert(!std::is_array_v<Type>, "Array types are not supported");
- using alloc_traits = typename std::allocator_traits<Allocator>::template rebind_traits<Type>;
- using allocator_type = typename alloc_traits::allocator_type;
- allocator_type alloc{allocator};
- auto ptr = alloc_traits::allocate(alloc, 1u);
- ENTT_TRY {
- alloc_traits::construct(alloc, to_address(ptr), std::forward<Args>(args)...);
- }
- ENTT_CATCH {
- alloc_traits::deallocate(alloc, ptr, 1u);
- ENTT_THROW;
- }
- return std::unique_ptr<Type, allocation_deleter<allocator_type>>{ptr, alloc};
- }
- /*! @cond TURN_OFF_DOXYGEN */
- namespace internal {
- template<typename Type>
- struct uses_allocator_construction {
- template<typename Allocator, typename... Params>
- static constexpr auto args([[maybe_unused]] const Allocator &allocator, Params &&...params) noexcept {
- if constexpr(!std::uses_allocator_v<Type, Allocator> && std::is_constructible_v<Type, Params...>) {
- return std::forward_as_tuple(std::forward<Params>(params)...);
- } else {
- static_assert(std::uses_allocator_v<Type, Allocator>, "Ill-formed request");
- if constexpr(std::is_constructible_v<Type, std::allocator_arg_t, const Allocator &, Params...>) {
- return std::tuple<std::allocator_arg_t, const Allocator &, Params &&...>{std::allocator_arg, allocator, std::forward<Params>(params)...};
- } else {
- static_assert(std::is_constructible_v<Type, Params..., const Allocator &>, "Ill-formed request");
- return std::forward_as_tuple(std::forward<Params>(params)..., allocator);
- }
- }
- }
- };
- template<typename Type, typename Other>
- struct uses_allocator_construction<std::pair<Type, Other>> {
- using type = std::pair<Type, Other>;
- template<typename Allocator, typename First, typename Second>
- static constexpr auto args(const Allocator &allocator, std::piecewise_construct_t, First &&first, Second &&second) noexcept {
- return std::make_tuple(
- std::piecewise_construct,
- std::apply([&allocator](auto &&...curr) { return uses_allocator_construction<Type>::args(allocator, std::forward<decltype(curr)>(curr)...); }, std::forward<First>(first)),
- std::apply([&allocator](auto &&...curr) { return uses_allocator_construction<Other>::args(allocator, std::forward<decltype(curr)>(curr)...); }, std::forward<Second>(second)));
- }
- template<typename Allocator>
- static constexpr auto args(const Allocator &allocator) noexcept {
- return uses_allocator_construction<type>::args(allocator, std::piecewise_construct, std::tuple<>{}, std::tuple<>{});
- }
- template<typename Allocator, typename First, typename Second>
- static constexpr auto args(const Allocator &allocator, First &&first, Second &&second) noexcept {
- return uses_allocator_construction<type>::args(allocator, std::piecewise_construct, std::forward_as_tuple(std::forward<First>(first)), std::forward_as_tuple(std::forward<Second>(second)));
- }
- template<typename Allocator, typename First, typename Second>
- static constexpr auto args(const Allocator &allocator, const std::pair<First, Second> &value) noexcept {
- return uses_allocator_construction<type>::args(allocator, std::piecewise_construct, std::forward_as_tuple(value.first), std::forward_as_tuple(value.second));
- }
- template<typename Allocator, typename First, typename Second>
- static constexpr auto args(const Allocator &allocator, std::pair<First, Second> &&value) noexcept {
- return uses_allocator_construction<type>::args(allocator, std::piecewise_construct, std::forward_as_tuple(std::move(value.first)), std::forward_as_tuple(std::move(value.second)));
- }
- };
- } // namespace internal
- /*! @endcond */
- /**
- * @brief Uses-allocator construction utility (waiting for C++20).
- *
- * Primarily intended for internal use. Prepares the argument list needed to
- * create an object of a given type by means of uses-allocator construction.
- *
- * @tparam Type Type to return arguments for.
- * @tparam Allocator Type of allocator used to manage memory and elements.
- * @tparam Args Types of arguments to use to construct the object.
- * @param allocator The allocator to use.
- * @param args Parameters to use to construct the object.
- * @return The arguments needed to create an object of the given type.
- */
- template<typename Type, typename Allocator, typename... Args>
- constexpr auto uses_allocator_construction_args(const Allocator &allocator, Args &&...args) noexcept {
- return internal::uses_allocator_construction<Type>::args(allocator, std::forward<Args>(args)...);
- }
- /**
- * @brief Uses-allocator construction utility (waiting for C++20).
- *
- * Primarily intended for internal use. Creates an object of a given type by
- * means of uses-allocator construction.
- *
- * @tparam Type Type of object to create.
- * @tparam Allocator Type of allocator used to manage memory and elements.
- * @tparam Args Types of arguments to use to construct the object.
- * @param allocator The allocator to use.
- * @param args Parameters to use to construct the object.
- * @return A newly created object of the given type.
- */
- template<typename Type, typename Allocator, typename... Args>
- constexpr Type make_obj_using_allocator(const Allocator &allocator, Args &&...args) {
- return std::make_from_tuple<Type>(internal::uses_allocator_construction<Type>::args(allocator, std::forward<Args>(args)...));
- }
- /**
- * @brief Uses-allocator construction utility (waiting for C++20).
- *
- * Primarily intended for internal use. Creates an object of a given type by
- * means of uses-allocator construction at an uninitialized memory location.
- *
- * @tparam Type Type of object to create.
- * @tparam Allocator Type of allocator used to manage memory and elements.
- * @tparam Args Types of arguments to use to construct the object.
- * @param value Memory location in which to place the object.
- * @param allocator The allocator to use.
- * @param args Parameters to use to construct the object.
- * @return A pointer to the newly created object of the given type.
- */
- template<typename Type, typename Allocator, typename... Args>
- constexpr Type *uninitialized_construct_using_allocator(Type *value, const Allocator &allocator, Args &&...args) {
- return std::apply([value](auto &&...curr) { return ::new(value) Type(std::forward<decltype(curr)>(curr)...); }, internal::uses_allocator_construction<Type>::args(allocator, std::forward<Args>(args)...));
- }
- } // namespace entt
- #endif
- // #include "../core/type_traits.hpp"
- #ifndef ENTT_CORE_TYPE_TRAITS_HPP
- #define ENTT_CORE_TYPE_TRAITS_HPP
- #include <cstddef>
- #include <iterator>
- #include <tuple>
- #include <type_traits>
- #include <utility>
- // #include "../config/config.h"
- // #include "fwd.hpp"
- namespace entt {
- /**
- * @brief Utility class to disambiguate overloaded functions.
- * @tparam N Number of choices available.
- */
- template<std::size_t N>
- struct choice_t
- // unfortunately, doxygen cannot parse such a construct
- : /*! @cond TURN_OFF_DOXYGEN */ choice_t<N - 1> /*! @endcond */
- {};
- /*! @copybrief choice_t */
- template<>
- struct choice_t<0> {};
- /**
- * @brief Variable template for the choice trick.
- * @tparam N Number of choices available.
- */
- template<std::size_t N>
- inline constexpr choice_t<N> choice{};
- /**
- * @brief Identity type trait.
- *
- * Useful to establish non-deduced contexts in template argument deduction
- * (waiting for C++20) or to provide types through function arguments.
- *
- * @tparam Type A type.
- */
- template<typename Type>
- struct type_identity {
- /*! @brief Identity type. */
- using type = Type;
- };
- /**
- * @brief Helper type.
- * @tparam Type A type.
- */
- template<typename Type>
- using type_identity_t = typename type_identity<Type>::type;
- /**
- * @brief A type-only `sizeof` wrapper that returns 0 where `sizeof` complains.
- * @tparam Type The type of which to return the size.
- */
- template<typename Type, typename = void>
- struct size_of: std::integral_constant<std::size_t, 0u> {};
- /*! @copydoc size_of */
- template<typename Type>
- struct size_of<Type, std::void_t<decltype(sizeof(Type))>>
- // NOLINTNEXTLINE(bugprone-sizeof-expression)
- : std::integral_constant<std::size_t, sizeof(Type)> {};
- /**
- * @brief Helper variable template.
- * @tparam Type The type of which to return the size.
- */
- template<typename Type>
- inline constexpr std::size_t size_of_v = size_of<Type>::value;
- /**
- * @brief Using declaration to be used to _repeat_ the same type a number of
- * times equal to the size of a given parameter pack.
- * @tparam Type A type to repeat.
- */
- template<typename Type, typename>
- using unpack_as_type = Type;
- /**
- * @brief Helper variable template to be used to _repeat_ the same value a
- * number of times equal to the size of a given parameter pack.
- * @tparam Value A value to repeat.
- */
- template<auto Value, typename>
- inline constexpr auto unpack_as_value = Value;
- /**
- * @brief Wraps a static constant.
- * @tparam Value A static constant.
- */
- template<auto Value>
- using integral_constant = std::integral_constant<decltype(Value), Value>;
- /**
- * @brief Alias template to facilitate the creation of named values.
- * @tparam Value A constant value at least convertible to `id_type`.
- */
- template<id_type Value>
- using tag = integral_constant<Value>;
- /**
- * @brief A class to use to push around lists of types, nothing more.
- * @tparam Type Types provided by the type list.
- */
- template<typename... Type>
- struct type_list {
- /*! @brief Type list type. */
- using type = type_list;
- /*! @brief Compile-time number of elements in the type list. */
- static constexpr auto size = sizeof...(Type);
- };
- /*! @brief Primary template isn't defined on purpose. */
- template<std::size_t, typename>
- struct type_list_element;
- /**
- * @brief Provides compile-time indexed access to the types of a type list.
- * @tparam Index Index of the type to return.
- * @tparam First First type provided by the type list.
- * @tparam Other Other types provided by the type list.
- */
- template<std::size_t Index, typename First, typename... Other>
- struct type_list_element<Index, type_list<First, Other...>>
- : type_list_element<Index - 1u, type_list<Other...>> {};
- /**
- * @brief Provides compile-time indexed access to the types of a type list.
- * @tparam First First type provided by the type list.
- * @tparam Other Other types provided by the type list.
- */
- template<typename First, typename... Other>
- struct type_list_element<0u, type_list<First, Other...>> {
- /*! @brief Searched type. */
- using type = First;
- };
- /**
- * @brief Helper type.
- * @tparam Index Index of the type to return.
- * @tparam List Type list to search into.
- */
- template<std::size_t Index, typename List>
- using type_list_element_t = typename type_list_element<Index, List>::type;
- /*! @brief Primary template isn't defined on purpose. */
- template<typename, typename>
- struct type_list_index;
- /**
- * @brief Provides compile-time type access to the types of a type list.
- * @tparam Type Type to look for and for which to return the index.
- * @tparam First First type provided by the type list.
- * @tparam Other Other types provided by the type list.
- */
- template<typename Type, typename First, typename... Other>
- struct type_list_index<Type, type_list<First, Other...>> {
- /*! @brief Unsigned integer type. */
- using value_type = std::size_t;
- /*! @brief Compile-time position of the given type in the sublist. */
- static constexpr value_type value = 1u + type_list_index<Type, type_list<Other...>>::value;
- };
- /**
- * @brief Provides compile-time type access to the types of a type list.
- * @tparam Type Type to look for and for which to return the index.
- * @tparam Other Other types provided by the type list.
- */
- template<typename Type, typename... Other>
- struct type_list_index<Type, type_list<Type, Other...>> {
- static_assert(type_list_index<Type, type_list<Other...>>::value == sizeof...(Other), "Non-unique type");
- /*! @brief Unsigned integer type. */
- using value_type = std::size_t;
- /*! @brief Compile-time position of the given type in the sublist. */
- static constexpr value_type value = 0u;
- };
- /**
- * @brief Provides compile-time type access to the types of a type list.
- * @tparam Type Type to look for and for which to return the index.
- */
- template<typename Type>
- struct type_list_index<Type, type_list<>> {
- /*! @brief Unsigned integer type. */
- using value_type = std::size_t;
- /*! @brief Compile-time position of the given type in the sublist. */
- static constexpr value_type value = 0u;
- };
- /**
- * @brief Helper variable template.
- * @tparam List Type list.
- * @tparam Type Type to look for and for which to return the index.
- */
- template<typename Type, typename List>
- inline constexpr std::size_t type_list_index_v = type_list_index<Type, List>::value;
- /**
- * @brief Concatenates multiple type lists.
- * @tparam Type Types provided by the first type list.
- * @tparam Other Types provided by the second type list.
- * @return A type list composed by the types of both the type lists.
- */
- template<typename... Type, typename... Other>
- constexpr type_list<Type..., Other...> operator+(type_list<Type...>, type_list<Other...>) {
- return {};
- }
- /*! @brief Primary template isn't defined on purpose. */
- template<typename...>
- struct type_list_cat;
- /*! @brief Concatenates multiple type lists. */
- template<>
- struct type_list_cat<> {
- /*! @brief A type list composed by the types of all the type lists. */
- using type = type_list<>;
- };
- /**
- * @brief Concatenates multiple type lists.
- * @tparam Type Types provided by the first type list.
- * @tparam Other Types provided by the second type list.
- * @tparam List Other type lists, if any.
- */
- template<typename... Type, typename... Other, typename... List>
- struct type_list_cat<type_list<Type...>, type_list<Other...>, List...> {
- /*! @brief A type list composed by the types of all the type lists. */
- using type = typename type_list_cat<type_list<Type..., Other...>, List...>::type;
- };
- /**
- * @brief Concatenates multiple type lists.
- * @tparam Type Types provided by the type list.
- */
- template<typename... Type>
- struct type_list_cat<type_list<Type...>> {
- /*! @brief A type list composed by the types of all the type lists. */
- using type = type_list<Type...>;
- };
- /**
- * @brief Helper type.
- * @tparam List Type lists to concatenate.
- */
- template<typename... List>
- using type_list_cat_t = typename type_list_cat<List...>::type;
- /*! @cond TURN_OFF_DOXYGEN */
- namespace internal {
- template<typename...>
- struct type_list_unique;
- template<typename First, typename... Other, typename... Type>
- struct type_list_unique<type_list<First, Other...>, Type...>
- : std::conditional_t<(std::is_same_v<First, Type> || ...), type_list_unique<type_list<Other...>, Type...>, type_list_unique<type_list<Other...>, Type..., First>> {};
- template<typename... Type>
- struct type_list_unique<type_list<>, Type...> {
- using type = type_list<Type...>;
- };
- } // namespace internal
- /*! @endcond */
- /**
- * @brief Removes duplicates types from a type list.
- * @tparam List Type list.
- */
- template<typename List>
- struct type_list_unique {
- /*! @brief A type list without duplicate types. */
- using type = typename internal::type_list_unique<List>::type;
- };
- /**
- * @brief Helper type.
- * @tparam List Type list.
- */
- template<typename List>
- using type_list_unique_t = typename type_list_unique<List>::type;
- /**
- * @brief Provides the member constant `value` to true if a type list contains a
- * given type, false otherwise.
- * @tparam List Type list.
- * @tparam Type Type to look for.
- */
- template<typename List, typename Type>
- struct type_list_contains;
- /**
- * @copybrief type_list_contains
- * @tparam Type Types provided by the type list.
- * @tparam Other Type to look for.
- */
- template<typename... Type, typename Other>
- struct type_list_contains<type_list<Type...>, Other>
- : std::bool_constant<(std::is_same_v<Type, Other> || ...)> {};
- /**
- * @brief Helper variable template.
- * @tparam List Type list.
- * @tparam Type Type to look for.
- */
- template<typename List, typename Type>
- inline constexpr bool type_list_contains_v = type_list_contains<List, Type>::value;
- /*! @brief Primary template isn't defined on purpose. */
- template<typename...>
- struct type_list_diff;
- /**
- * @brief Computes the difference between two type lists.
- * @tparam Type Types provided by the first type list.
- * @tparam Other Types provided by the second type list.
- */
- template<typename... Type, typename... Other>
- struct type_list_diff<type_list<Type...>, type_list<Other...>> {
- /*! @brief A type list that is the difference between the two type lists. */
- using type = type_list_cat_t<std::conditional_t<type_list_contains_v<type_list<Other...>, Type>, type_list<>, type_list<Type>>...>;
- };
- /**
- * @brief Helper type.
- * @tparam List Type lists between which to compute the difference.
- */
- template<typename... List>
- using type_list_diff_t = typename type_list_diff<List...>::type;
- /*! @brief Primary template isn't defined on purpose. */
- template<typename, template<typename...> class>
- struct type_list_transform;
- /**
- * @brief Applies a given _function_ to a type list and generate a new list.
- * @tparam Type Types provided by the type list.
- * @tparam Op Unary operation as template class with a type member named `type`.
- */
- template<typename... Type, template<typename...> class Op>
- struct type_list_transform<type_list<Type...>, Op> {
- /*! @brief Resulting type list after applying the transform function. */
- // NOLINTNEXTLINE(modernize-type-traits)
- using type = type_list<typename Op<Type>::type...>;
- };
- /**
- * @brief Helper type.
- * @tparam List Type list.
- * @tparam Op Unary operation as template class with a type member named `type`.
- */
- template<typename List, template<typename...> class Op>
- using type_list_transform_t = typename type_list_transform<List, Op>::type;
- /**
- * @brief A class to use to push around lists of constant values, nothing more.
- * @tparam Value Values provided by the value list.
- */
- template<auto... Value>
- struct value_list {
- /*! @brief Value list type. */
- using type = value_list;
- /*! @brief Compile-time number of elements in the value list. */
- static constexpr auto size = sizeof...(Value);
- };
- /*! @brief Primary template isn't defined on purpose. */
- template<std::size_t, typename>
- struct value_list_element;
- /**
- * @brief Provides compile-time indexed access to the values of a value list.
- * @tparam Index Index of the value to return.
- * @tparam Value First value provided by the value list.
- * @tparam Other Other values provided by the value list.
- */
- template<std::size_t Index, auto Value, auto... Other>
- struct value_list_element<Index, value_list<Value, Other...>>
- : value_list_element<Index - 1u, value_list<Other...>> {};
- /**
- * @brief Provides compile-time indexed access to the types of a type list.
- * @tparam Value First value provided by the value list.
- * @tparam Other Other values provided by the value list.
- */
- template<auto Value, auto... Other>
- struct value_list_element<0u, value_list<Value, Other...>> {
- /*! @brief Searched type. */
- using type = decltype(Value);
- /*! @brief Searched value. */
- static constexpr auto value = Value;
- };
- /**
- * @brief Helper type.
- * @tparam Index Index of the type to return.
- * @tparam List Value list to search into.
- */
- template<std::size_t Index, typename List>
- using value_list_element_t = typename value_list_element<Index, List>::type;
- /**
- * @brief Helper type.
- * @tparam Index Index of the value to return.
- * @tparam List Value list to search into.
- */
- template<std::size_t Index, typename List>
- inline constexpr auto value_list_element_v = value_list_element<Index, List>::value;
- /*! @brief Primary template isn't defined on purpose. */
- template<auto, typename>
- struct value_list_index;
- /**
- * @brief Provides compile-time type access to the values of a value list.
- * @tparam Value Value to look for and for which to return the index.
- * @tparam First First value provided by the value list.
- * @tparam Other Other values provided by the value list.
- */
- template<auto Value, auto First, auto... Other>
- struct value_list_index<Value, value_list<First, Other...>> {
- /*! @brief Unsigned integer type. */
- using value_type = std::size_t;
- /*! @brief Compile-time position of the given value in the sublist. */
- static constexpr value_type value = 1u + value_list_index<Value, value_list<Other...>>::value;
- };
- /**
- * @brief Provides compile-time type access to the values of a value list.
- * @tparam Value Value to look for and for which to return the index.
- * @tparam Other Other values provided by the value list.
- */
- template<auto Value, auto... Other>
- struct value_list_index<Value, value_list<Value, Other...>> {
- static_assert(value_list_index<Value, value_list<Other...>>::value == sizeof...(Other), "Non-unique type");
- /*! @brief Unsigned integer type. */
- using value_type = std::size_t;
- /*! @brief Compile-time position of the given value in the sublist. */
- static constexpr value_type value = 0u;
- };
- /**
- * @brief Provides compile-time type access to the values of a value list.
- * @tparam Value Value to look for and for which to return the index.
- */
- template<auto Value>
- struct value_list_index<Value, value_list<>> {
- /*! @brief Unsigned integer type. */
- using value_type = std::size_t;
- /*! @brief Compile-time position of the given type in the sublist. */
- static constexpr value_type value = 0u;
- };
- /**
- * @brief Helper variable template.
- * @tparam List Value list.
- * @tparam Value Value to look for and for which to return the index.
- */
- template<auto Value, typename List>
- inline constexpr std::size_t value_list_index_v = value_list_index<Value, List>::value;
- /**
- * @brief Concatenates multiple value lists.
- * @tparam Value Values provided by the first value list.
- * @tparam Other Values provided by the second value list.
- * @return A value list composed by the values of both the value lists.
- */
- template<auto... Value, auto... Other>
- constexpr value_list<Value..., Other...> operator+(value_list<Value...>, value_list<Other...>) {
- return {};
- }
- /*! @brief Primary template isn't defined on purpose. */
- template<typename...>
- struct value_list_cat;
- /*! @brief Concatenates multiple value lists. */
- template<>
- struct value_list_cat<> {
- /*! @brief A value list composed by the values of all the value lists. */
- using type = value_list<>;
- };
- /**
- * @brief Concatenates multiple value lists.
- * @tparam Value Values provided by the first value list.
- * @tparam Other Values provided by the second value list.
- * @tparam List Other value lists, if any.
- */
- template<auto... Value, auto... Other, typename... List>
- struct value_list_cat<value_list<Value...>, value_list<Other...>, List...> {
- /*! @brief A value list composed by the values of all the value lists. */
- using type = typename value_list_cat<value_list<Value..., Other...>, List...>::type;
- };
- /**
- * @brief Concatenates multiple value lists.
- * @tparam Value Values provided by the value list.
- */
- template<auto... Value>
- struct value_list_cat<value_list<Value...>> {
- /*! @brief A value list composed by the values of all the value lists. */
- using type = value_list<Value...>;
- };
- /**
- * @brief Helper type.
- * @tparam List Value lists to concatenate.
- */
- template<typename... List>
- using value_list_cat_t = typename value_list_cat<List...>::type;
- /*! @brief Primary template isn't defined on purpose. */
- template<typename>
- struct value_list_unique;
- /**
- * @brief Removes duplicates values from a value list.
- * @tparam Value One of the values provided by the given value list.
- * @tparam Other The other values provided by the given value list.
- */
- template<auto Value, auto... Other>
- struct value_list_unique<value_list<Value, Other...>> {
- /*! @brief A value list without duplicate types. */
- using type = std::conditional_t<
- ((Value == Other) || ...),
- typename value_list_unique<value_list<Other...>>::type,
- value_list_cat_t<value_list<Value>, typename value_list_unique<value_list<Other...>>::type>>;
- };
- /*! @brief Removes duplicates values from a value list. */
- template<>
- struct value_list_unique<value_list<>> {
- /*! @brief A value list without duplicate types. */
- using type = value_list<>;
- };
- /**
- * @brief Helper type.
- * @tparam Type A value list.
- */
- template<typename Type>
- using value_list_unique_t = typename value_list_unique<Type>::type;
- /**
- * @brief Provides the member constant `value` to true if a value list contains
- * a given value, false otherwise.
- * @tparam List Value list.
- * @tparam Value Value to look for.
- */
- template<typename List, auto Value>
- struct value_list_contains;
- /**
- * @copybrief value_list_contains
- * @tparam Value Values provided by the value list.
- * @tparam Other Value to look for.
- */
- template<auto... Value, auto Other>
- struct value_list_contains<value_list<Value...>, Other>
- : std::bool_constant<((Value == Other) || ...)> {};
- /**
- * @brief Helper variable template.
- * @tparam List Value list.
- * @tparam Value Value to look for.
- */
- template<typename List, auto Value>
- inline constexpr bool value_list_contains_v = value_list_contains<List, Value>::value;
- /*! @brief Primary template isn't defined on purpose. */
- template<typename...>
- struct value_list_diff;
- /**
- * @brief Computes the difference between two value lists.
- * @tparam Value Values provided by the first value list.
- * @tparam Other Values provided by the second value list.
- */
- template<auto... Value, auto... Other>
- struct value_list_diff<value_list<Value...>, value_list<Other...>> {
- /*! @brief A value list that is the difference between the two value lists. */
- using type = value_list_cat_t<std::conditional_t<value_list_contains_v<value_list<Other...>, Value>, value_list<>, value_list<Value>>...>;
- };
- /**
- * @brief Helper type.
- * @tparam List Value lists between which to compute the difference.
- */
- template<typename... List>
- using value_list_diff_t = typename value_list_diff<List...>::type;
- /*! @brief Same as std::is_invocable, but with tuples. */
- template<typename, typename>
- struct is_applicable: std::false_type {};
- /**
- * @copybrief is_applicable
- * @tparam Func A valid function type.
- * @tparam Tuple Tuple-like type.
- * @tparam Args The list of arguments to use to probe the function type.
- */
- template<typename Func, template<typename...> class Tuple, typename... Args>
- struct is_applicable<Func, Tuple<Args...>>: std::is_invocable<Func, Args...> {};
- /**
- * @copybrief is_applicable
- * @tparam Func A valid function type.
- * @tparam Tuple Tuple-like type.
- * @tparam Args The list of arguments to use to probe the function type.
- */
- template<typename Func, template<typename...> class Tuple, typename... Args>
- struct is_applicable<Func, const Tuple<Args...>>: std::is_invocable<Func, Args...> {};
- /**
- * @brief Helper variable template.
- * @tparam Func A valid function type.
- * @tparam Args The list of arguments to use to probe the function type.
- */
- template<typename Func, typename Args>
- inline constexpr bool is_applicable_v = is_applicable<Func, Args>::value;
- /*! @brief Same as std::is_invocable_r, but with tuples for arguments. */
- template<typename, typename, typename>
- struct is_applicable_r: std::false_type {};
- /**
- * @copybrief is_applicable_r
- * @tparam Ret The type to which the return type of the function should be
- * convertible.
- * @tparam Func A valid function type.
- * @tparam Args The list of arguments to use to probe the function type.
- */
- template<typename Ret, typename Func, typename... Args>
- struct is_applicable_r<Ret, Func, std::tuple<Args...>>: std::is_invocable_r<Ret, Func, Args...> {};
- /**
- * @brief Helper variable template.
- * @tparam Ret The type to which the return type of the function should be
- * convertible.
- * @tparam Func A valid function type.
- * @tparam Args The list of arguments to use to probe the function type.
- */
- template<typename Ret, typename Func, typename Args>
- inline constexpr bool is_applicable_r_v = is_applicable_r<Ret, Func, Args>::value;
- /**
- * @brief Provides the member constant `value` to true if a given type is
- * complete, false otherwise.
- * @tparam Type The type to test.
- */
- template<typename Type, typename = void>
- struct is_complete: std::false_type {};
- /*! @copydoc is_complete */
- template<typename Type>
- struct is_complete<Type, std::void_t<decltype(sizeof(Type))>>: std::true_type {};
- /**
- * @brief Helper variable template.
- * @tparam Type The type to test.
- */
- template<typename Type>
- inline constexpr bool is_complete_v = is_complete<Type>::value;
- /**
- * @brief Provides the member constant `value` to true if a given type is an
- * iterator, false otherwise.
- * @tparam Type The type to test.
- */
- template<typename Type, typename = void>
- struct is_iterator: std::false_type {};
- /*! @cond TURN_OFF_DOXYGEN */
- namespace internal {
- template<typename, typename = void>
- struct has_iterator_category: std::false_type {};
- template<typename Type>
- struct has_iterator_category<Type, std::void_t<typename std::iterator_traits<Type>::iterator_category>>: std::true_type {};
- } // namespace internal
- /*! @endcond */
- /*! @copydoc is_iterator */
- template<typename Type>
- struct is_iterator<Type, std::enable_if_t<!std::is_void_v<std::remove_const_t<std::remove_pointer_t<Type>>>>>
- : internal::has_iterator_category<Type> {};
- /**
- * @brief Helper variable template.
- * @tparam Type The type to test.
- */
- template<typename Type>
- inline constexpr bool is_iterator_v = is_iterator<Type>::value;
- /**
- * @brief Provides the member constant `value` to true if a given type is both
- * an empty and non-final class, false otherwise.
- * @tparam Type The type to test
- */
- template<typename Type>
- struct is_ebco_eligible
- : std::bool_constant<std::is_empty_v<Type> && !std::is_final_v<Type>> {};
- /**
- * @brief Helper variable template.
- * @tparam Type The type to test.
- */
- template<typename Type>
- inline constexpr bool is_ebco_eligible_v = is_ebco_eligible<Type>::value;
- /**
- * @brief Provides the member constant `value` to true if `Type::is_transparent`
- * is valid and denotes a type, false otherwise.
- * @tparam Type The type to test.
- */
- template<typename Type, typename = void>
- struct is_transparent: std::false_type {};
- /*! @copydoc is_transparent */
- template<typename Type>
- struct is_transparent<Type, std::void_t<typename Type::is_transparent>>: std::true_type {};
- /**
- * @brief Helper variable template.
- * @tparam Type The type to test.
- */
- template<typename Type>
- inline constexpr bool is_transparent_v = is_transparent<Type>::value;
- /*! @cond TURN_OFF_DOXYGEN */
- namespace internal {
- template<typename, typename = void>
- struct has_tuple_size_value: std::false_type {};
- template<typename Type>
- struct has_tuple_size_value<Type, std::void_t<decltype(std::tuple_size<const Type>::value)>>: std::true_type {};
- template<typename, typename = void>
- struct has_value_type: std::false_type {};
- template<typename Type>
- struct has_value_type<Type, std::void_t<typename Type::value_type>>: std::true_type {};
- template<typename>
- [[nodiscard]] constexpr bool dispatch_is_equality_comparable();
- template<typename Type, std::size_t... Index>
- [[nodiscard]] constexpr bool unpack_maybe_equality_comparable(std::index_sequence<Index...>) {
- return (dispatch_is_equality_comparable<std::tuple_element_t<Index, Type>>() && ...);
- }
- template<typename>
- [[nodiscard]] constexpr bool maybe_equality_comparable(char) {
- return false;
- }
- template<typename Type>
- [[nodiscard]] constexpr auto maybe_equality_comparable(int) -> decltype(std::declval<Type>() == std::declval<Type>()) {
- return true;
- }
- template<typename Type>
- [[nodiscard]] constexpr bool dispatch_is_equality_comparable() {
- // NOLINTBEGIN(modernize-use-transparent-functors)
- if constexpr(std::is_array_v<Type>) {
- return false;
- } else if constexpr(is_complete_v<std::tuple_size<std::remove_const_t<Type>>>) {
- if constexpr(has_tuple_size_value<Type>::value) {
- return maybe_equality_comparable<Type>(0) && unpack_maybe_equality_comparable<Type>(std::make_index_sequence<std::tuple_size<Type>::value>{});
- } else {
- return maybe_equality_comparable<Type>(0);
- }
- } else if constexpr(has_value_type<Type>::value) {
- if constexpr(is_iterator_v<Type> || std::is_same_v<typename Type::value_type, Type> || dispatch_is_equality_comparable<typename Type::value_type>()) {
- return maybe_equality_comparable<Type>(0);
- } else {
- return false;
- }
- } else {
- return maybe_equality_comparable<Type>(0);
- }
- // NOLINTEND(modernize-use-transparent-functors)
- }
- } // namespace internal
- /*! @endcond */
- /**
- * @brief Provides the member constant `value` to true if a given type is
- * equality comparable, false otherwise.
- * @tparam Type The type to test.
- */
- template<typename Type>
- struct is_equality_comparable: std::bool_constant<internal::dispatch_is_equality_comparable<Type>()> {};
- /*! @copydoc is_equality_comparable */
- template<typename Type>
- struct is_equality_comparable<const Type>: is_equality_comparable<Type> {};
- /**
- * @brief Helper variable template.
- * @tparam Type The type to test.
- */
- template<typename Type>
- inline constexpr bool is_equality_comparable_v = is_equality_comparable<Type>::value;
- /**
- * @brief Transcribes the constness of a type to another type.
- * @tparam To The type to which to transcribe the constness.
- * @tparam From The type from which to transcribe the constness.
- */
- template<typename To, typename From>
- struct constness_as {
- /*! @brief The type resulting from the transcription of the constness. */
- using type = std::remove_const_t<To>;
- };
- /*! @copydoc constness_as */
- template<typename To, typename From>
- struct constness_as<To, const From> {
- /*! @brief The type resulting from the transcription of the constness. */
- using type = const To;
- };
- /**
- * @brief Alias template to facilitate the transcription of the constness.
- * @tparam To The type to which to transcribe the constness.
- * @tparam From The type from which to transcribe the constness.
- */
- template<typename To, typename From>
- using constness_as_t = typename constness_as<To, From>::type;
- /**
- * @brief Extracts the class of a non-static member object or function.
- * @tparam Member A pointer to a non-static member object or function.
- */
- template<typename Member>
- class member_class {
- static_assert(std::is_member_pointer_v<Member>, "Invalid pointer type to non-static member object or function");
- template<typename Class, typename Ret, typename... Args>
- static Class *clazz(Ret (Class::*)(Args...));
- template<typename Class, typename Ret, typename... Args>
- static Class *clazz(Ret (Class::*)(Args...) const);
- template<typename Class, typename Type>
- static Class *clazz(Type Class::*);
- public:
- /*! @brief The class of the given non-static member object or function. */
- using type = std::remove_pointer_t<decltype(clazz(std::declval<Member>()))>;
- };
- /**
- * @brief Helper type.
- * @tparam Member A pointer to a non-static member object or function.
- */
- template<typename Member>
- using member_class_t = typename member_class<Member>::type;
- /**
- * @brief Extracts the n-th argument of a _callable_ type.
- * @tparam Index The index of the argument to extract.
- * @tparam Candidate A valid _callable_ type.
- */
- template<std::size_t Index, typename Candidate>
- class nth_argument {
- template<typename Ret, typename... Args>
- static constexpr type_list<Args...> pick_up(Ret (*)(Args...));
- template<typename Ret, typename Class, typename... Args>
- static constexpr type_list<Args...> pick_up(Ret (Class ::*)(Args...));
- template<typename Ret, typename Class, typename... Args>
- static constexpr type_list<Args...> pick_up(Ret (Class ::*)(Args...) const);
- template<typename Type, typename Class>
- static constexpr type_list<Type> pick_up(Type Class ::*);
- template<typename Type>
- static constexpr decltype(pick_up(&Type::operator())) pick_up(Type &&);
- public:
- /*! @brief N-th argument of the _callable_ type. */
- using type = type_list_element_t<Index, decltype(pick_up(std::declval<Candidate>()))>;
- };
- /**
- * @brief Helper type.
- * @tparam Index The index of the argument to extract.
- * @tparam Candidate A valid function, member function or data member type.
- */
- template<std::size_t Index, typename Candidate>
- using nth_argument_t = typename nth_argument<Index, Candidate>::type;
- } // namespace entt
- template<typename... Type>
- struct std::tuple_size<entt::type_list<Type...>>: std::integral_constant<std::size_t, entt::type_list<Type...>::size> {};
- template<std::size_t Index, typename... Type>
- struct std::tuple_element<Index, entt::type_list<Type...>>: entt::type_list_element<Index, entt::type_list<Type...>> {};
- template<auto... Value>
- struct std::tuple_size<entt::value_list<Value...>>: std::integral_constant<std::size_t, entt::value_list<Value...>::size> {};
- template<std::size_t Index, auto... Value>
- struct std::tuple_element<Index, entt::value_list<Value...>>: entt::value_list_element<Index, entt::value_list<Value...>> {};
- #endif
- // #include "fwd.hpp"
- #ifndef ENTT_CONTAINER_FWD_HPP
- #define ENTT_CONTAINER_FWD_HPP
- #include <functional>
- #include <memory>
- #include <utility>
- #include <vector>
- namespace entt {
- template<
- typename Key,
- typename Type,
- typename = std::hash<Key>,
- typename = std::equal_to<>,
- typename = std::allocator<std::pair<const Key, Type>>>
- class dense_map;
- template<
- typename Type,
- typename = std::hash<Type>,
- typename = std::equal_to<>,
- typename = std::allocator<Type>>
- class dense_set;
- template<typename...>
- class basic_table;
- /**
- * @brief Alias declaration for the most common use case.
- * @tparam Type Element types.
- */
- template<typename... Type>
- using table = basic_table<std::vector<Type>...>;
- } // namespace entt
- #endif
- namespace entt {
- /*! @cond TURN_OFF_DOXYGEN */
- namespace internal {
- static constexpr std::size_t dense_map_placeholder_position = (std::numeric_limits<std::size_t>::max)();
- template<typename Key, typename Type>
- struct dense_map_node final {
- using value_type = std::pair<Key, Type>;
- template<typename... Args>
- dense_map_node(const std::size_t pos, Args &&...args)
- : next{pos},
- element{std::forward<Args>(args)...} {}
- template<typename Allocator, typename... Args>
- dense_map_node(std::allocator_arg_t, const Allocator &allocator, const std::size_t pos, Args &&...args)
- : next{pos},
- element{entt::make_obj_using_allocator<value_type>(allocator, std::forward<Args>(args)...)} {}
- template<typename Allocator>
- dense_map_node(std::allocator_arg_t, const Allocator &allocator, const dense_map_node &other)
- : next{other.next},
- element{entt::make_obj_using_allocator<value_type>(allocator, other.element)} {}
- template<typename Allocator>
- dense_map_node(std::allocator_arg_t, const Allocator &allocator, dense_map_node &&other)
- : next{other.next},
- element{entt::make_obj_using_allocator<value_type>(allocator, std::move(other.element))} {}
- std::size_t next;
- value_type element;
- };
- template<typename It>
- class dense_map_iterator final {
- template<typename>
- friend class dense_map_iterator;
- using first_type = decltype(std::as_const(std::declval<It>()->element.first));
- using second_type = decltype((std::declval<It>()->element.second));
- public:
- using value_type = std::pair<first_type, second_type>;
- using pointer = input_iterator_pointer<value_type>;
- using reference = value_type;
- using difference_type = std::ptrdiff_t;
- using iterator_category = std::input_iterator_tag;
- using iterator_concept = std::random_access_iterator_tag;
- constexpr dense_map_iterator() noexcept
- : it{} {}
- constexpr dense_map_iterator(const It iter) noexcept
- : it{iter} {}
- template<typename Other, typename = std::enable_if_t<!std::is_same_v<It, Other> && std::is_constructible_v<It, Other>>>
- constexpr dense_map_iterator(const dense_map_iterator<Other> &other) noexcept
- : it{other.it} {}
- constexpr dense_map_iterator &operator++() noexcept {
- return ++it, *this;
- }
- constexpr dense_map_iterator operator++(int) noexcept {
- const dense_map_iterator orig = *this;
- return ++(*this), orig;
- }
- constexpr dense_map_iterator &operator--() noexcept {
- return --it, *this;
- }
- constexpr dense_map_iterator operator--(int) noexcept {
- const dense_map_iterator orig = *this;
- return operator--(), orig;
- }
- constexpr dense_map_iterator &operator+=(const difference_type value) noexcept {
- it += value;
- return *this;
- }
- constexpr dense_map_iterator operator+(const difference_type value) const noexcept {
- dense_map_iterator copy = *this;
- return (copy += value);
- }
- constexpr dense_map_iterator &operator-=(const difference_type value) noexcept {
- return (*this += -value);
- }
- constexpr dense_map_iterator operator-(const difference_type value) const noexcept {
- return (*this + -value);
- }
- [[nodiscard]] constexpr reference operator[](const difference_type value) const noexcept {
- return {it[value].element.first, it[value].element.second};
- }
- [[nodiscard]] constexpr pointer operator->() const noexcept {
- return operator*();
- }
- [[nodiscard]] constexpr reference operator*() const noexcept {
- return operator[](0);
- }
- template<typename Lhs, typename Rhs>
- friend constexpr std::ptrdiff_t operator-(const dense_map_iterator<Lhs> &, const dense_map_iterator<Rhs> &) noexcept;
- template<typename Lhs, typename Rhs>
- friend constexpr bool operator==(const dense_map_iterator<Lhs> &, const dense_map_iterator<Rhs> &) noexcept;
- template<typename Lhs, typename Rhs>
- friend constexpr bool operator<(const dense_map_iterator<Lhs> &, const dense_map_iterator<Rhs> &) noexcept;
- private:
- It it;
- };
- template<typename Lhs, typename Rhs>
- [[nodiscard]] constexpr std::ptrdiff_t operator-(const dense_map_iterator<Lhs> &lhs, const dense_map_iterator<Rhs> &rhs) noexcept {
- return lhs.it - rhs.it;
- }
- template<typename Lhs, typename Rhs>
- [[nodiscard]] constexpr bool operator==(const dense_map_iterator<Lhs> &lhs, const dense_map_iterator<Rhs> &rhs) noexcept {
- return lhs.it == rhs.it;
- }
- template<typename Lhs, typename Rhs>
- [[nodiscard]] constexpr bool operator!=(const dense_map_iterator<Lhs> &lhs, const dense_map_iterator<Rhs> &rhs) noexcept {
- return !(lhs == rhs);
- }
- template<typename Lhs, typename Rhs>
- [[nodiscard]] constexpr bool operator<(const dense_map_iterator<Lhs> &lhs, const dense_map_iterator<Rhs> &rhs) noexcept {
- return lhs.it < rhs.it;
- }
- template<typename Lhs, typename Rhs>
- [[nodiscard]] constexpr bool operator>(const dense_map_iterator<Lhs> &lhs, const dense_map_iterator<Rhs> &rhs) noexcept {
- return rhs < lhs;
- }
- template<typename Lhs, typename Rhs>
- [[nodiscard]] constexpr bool operator<=(const dense_map_iterator<Lhs> &lhs, const dense_map_iterator<Rhs> &rhs) noexcept {
- return !(lhs > rhs);
- }
- template<typename Lhs, typename Rhs>
- [[nodiscard]] constexpr bool operator>=(const dense_map_iterator<Lhs> &lhs, const dense_map_iterator<Rhs> &rhs) noexcept {
- return !(lhs < rhs);
- }
- template<typename It>
- class dense_map_local_iterator final {
- template<typename>
- friend class dense_map_local_iterator;
- using first_type = decltype(std::as_const(std::declval<It>()->element.first));
- using second_type = decltype((std::declval<It>()->element.second));
- public:
- using value_type = std::pair<first_type, second_type>;
- using pointer = input_iterator_pointer<value_type>;
- using reference = value_type;
- using difference_type = std::ptrdiff_t;
- using iterator_category = std::input_iterator_tag;
- using iterator_concept = std::forward_iterator_tag;
- constexpr dense_map_local_iterator() noexcept = default;
- constexpr dense_map_local_iterator(It iter, const std::size_t pos) noexcept
- : it{iter},
- offset{pos} {}
- template<typename Other, typename = std::enable_if_t<!std::is_same_v<It, Other> && std::is_constructible_v<It, Other>>>
- constexpr dense_map_local_iterator(const dense_map_local_iterator<Other> &other) noexcept
- : it{other.it},
- offset{other.offset} {}
- constexpr dense_map_local_iterator &operator++() noexcept {
- return (offset = it[static_cast<typename It::difference_type>(offset)].next), *this;
- }
- constexpr dense_map_local_iterator operator++(int) noexcept {
- const dense_map_local_iterator orig = *this;
- return ++(*this), orig;
- }
- [[nodiscard]] constexpr pointer operator->() const noexcept {
- return operator*();
- }
- [[nodiscard]] constexpr reference operator*() const noexcept {
- const auto idx = static_cast<typename It::difference_type>(offset);
- return {it[idx].element.first, it[idx].element.second};
- }
- [[nodiscard]] constexpr std::size_t index() const noexcept {
- return offset;
- }
- private:
- It it{};
- std::size_t offset{dense_map_placeholder_position};
- };
- template<typename Lhs, typename Rhs>
- [[nodiscard]] constexpr bool operator==(const dense_map_local_iterator<Lhs> &lhs, const dense_map_local_iterator<Rhs> &rhs) noexcept {
- return lhs.index() == rhs.index();
- }
- template<typename Lhs, typename Rhs>
- [[nodiscard]] constexpr bool operator!=(const dense_map_local_iterator<Lhs> &lhs, const dense_map_local_iterator<Rhs> &rhs) noexcept {
- return !(lhs == rhs);
- }
- } // namespace internal
- /*! @endcond */
- /**
- * @brief Associative container for key-value pairs with unique keys.
- *
- * Internally, elements are organized into buckets. Which bucket an element is
- * placed into depends entirely on the hash of its key. Keys with the same hash
- * code appear in the same bucket.
- *
- * @tparam Key Key type of the associative container.
- * @tparam Type Mapped type of the associative container.
- * @tparam Hash Type of function to use to hash the keys.
- * @tparam KeyEqual Type of function to use to compare the keys for equality.
- * @tparam Allocator Type of allocator used to manage memory and elements.
- */
- template<typename Key, typename Type, typename Hash, typename KeyEqual, typename Allocator>
- class dense_map {
- static constexpr float default_threshold = 0.875f;
- static constexpr std::size_t minimum_capacity = 8u;
- static constexpr std::size_t placeholder_position = internal::dense_map_placeholder_position;
- using node_type = internal::dense_map_node<Key, Type>;
- using alloc_traits = std::allocator_traits<Allocator>;
- static_assert(std::is_same_v<typename alloc_traits::value_type, std::pair<const Key, Type>>, "Invalid value type");
- using sparse_container_type = std::vector<std::size_t, typename alloc_traits::template rebind_alloc<std::size_t>>;
- using packed_container_type = std::vector<node_type, typename alloc_traits::template rebind_alloc<node_type>>;
- template<typename Other>
- [[nodiscard]] std::size_t key_to_bucket(const Other &key) const noexcept {
- // NOLINTNEXTLINE(cppcoreguidelines-pro-bounds-array-to-pointer-decay)
- return fast_mod(static_cast<size_type>(sparse.second()(key)), bucket_count());
- }
- template<typename Other>
- [[nodiscard]] auto constrained_find(const Other &key, const std::size_t bucket) {
- for(auto offset = sparse.first()[bucket]; offset != placeholder_position; offset = packed.first()[offset].next) {
- if(packed.second()(packed.first()[offset].element.first, key)) {
- return begin() + static_cast<typename iterator::difference_type>(offset);
- }
- }
- return end();
- }
- template<typename Other>
- [[nodiscard]] auto constrained_find(const Other &key, const std::size_t bucket) const {
- for(auto offset = sparse.first()[bucket]; offset != placeholder_position; offset = packed.first()[offset].next) {
- if(packed.second()(packed.first()[offset].element.first, key)) {
- return cbegin() + static_cast<typename const_iterator::difference_type>(offset);
- }
- }
- return cend();
- }
- template<typename Other, typename... Args>
- [[nodiscard]] auto insert_or_do_nothing(Other &&key, Args &&...args) {
- const auto index = key_to_bucket(key);
- if(auto it = constrained_find(key, index); it != end()) {
- return std::make_pair(it, false);
- }
- packed.first().emplace_back(sparse.first()[index], std::piecewise_construct, std::forward_as_tuple(std::forward<Other>(key)), std::forward_as_tuple(std::forward<Args>(args)...));
- sparse.first()[index] = packed.first().size() - 1u;
- rehash_if_required();
- return std::make_pair(--end(), true);
- }
- template<typename Other, typename Arg>
- [[nodiscard]] auto insert_or_overwrite(Other &&key, Arg &&value) {
- const auto index = key_to_bucket(key);
- if(auto it = constrained_find(key, index); it != end()) {
- it->second = std::forward<Arg>(value);
- return std::make_pair(it, false);
- }
- packed.first().emplace_back(sparse.first()[index], std::forward<Other>(key), std::forward<Arg>(value));
- sparse.first()[index] = packed.first().size() - 1u;
- rehash_if_required();
- return std::make_pair(--end(), true);
- }
- void move_and_pop(const std::size_t pos) {
- if(const auto last = size() - 1u; pos != last) {
- size_type *curr = &sparse.first()[key_to_bucket(packed.first().back().element.first)];
- packed.first()[pos] = std::move(packed.first().back());
- for(; *curr != last; curr = &packed.first()[*curr].next) {}
- *curr = pos;
- }
- packed.first().pop_back();
- }
- void rehash_if_required() {
- if(const auto bc = bucket_count(); size() > static_cast<size_type>(static_cast<float>(bc) * max_load_factor())) {
- rehash(bc * 2u);
- }
- }
- public:
- /*! @brief Allocator type. */
- using allocator_type = Allocator;
- /*! @brief Key type of the container. */
- using key_type = Key;
- /*! @brief Mapped type of the container. */
- using mapped_type = Type;
- /*! @brief Key-value type of the container. */
- using value_type = std::pair<const Key, Type>;
- /*! @brief Unsigned integer type. */
- using size_type = std::size_t;
- /*! @brief Signed integer type. */
- using difference_type = std::ptrdiff_t;
- /*! @brief Type of function to use to hash the keys. */
- using hasher = Hash;
- /*! @brief Type of function to use to compare the keys for equality. */
- using key_equal = KeyEqual;
- /*! @brief Input iterator type. */
- using iterator = internal::dense_map_iterator<typename packed_container_type::iterator>;
- /*! @brief Constant input iterator type. */
- using const_iterator = internal::dense_map_iterator<typename packed_container_type::const_iterator>;
- /*! @brief Input iterator type. */
- using local_iterator = internal::dense_map_local_iterator<typename packed_container_type::iterator>;
- /*! @brief Constant input iterator type. */
- using const_local_iterator = internal::dense_map_local_iterator<typename packed_container_type::const_iterator>;
- /*! @brief Default constructor. */
- dense_map()
- : dense_map{minimum_capacity} {}
- /**
- * @brief Constructs an empty container with a given allocator.
- * @param allocator The allocator to use.
- */
- explicit dense_map(const allocator_type &allocator)
- : dense_map{minimum_capacity, hasher{}, key_equal{}, allocator} {}
- /**
- * @brief Constructs an empty container with a given allocator and user
- * supplied minimal number of buckets.
- * @param cnt Minimal number of buckets.
- * @param allocator The allocator to use.
- */
- dense_map(const size_type cnt, const allocator_type &allocator)
- : dense_map{cnt, hasher{}, key_equal{}, allocator} {}
- /**
- * @brief Constructs an empty container with a given allocator, hash
- * function and user supplied minimal number of buckets.
- * @param cnt Minimal number of buckets.
- * @param hash Hash function to use.
- * @param allocator The allocator to use.
- */
- dense_map(const size_type cnt, const hasher &hash, const allocator_type &allocator)
- : dense_map{cnt, hash, key_equal{}, allocator} {}
- /**
- * @brief Constructs an empty container with a given allocator, hash
- * function, compare function and user supplied minimal number of buckets.
- * @param cnt Minimal number of buckets.
- * @param hash Hash function to use.
- * @param equal Compare function to use.
- * @param allocator The allocator to use.
- */
- explicit dense_map(const size_type cnt, const hasher &hash = hasher{}, const key_equal &equal = key_equal{}, const allocator_type &allocator = allocator_type{})
- : sparse{allocator, hash},
- packed{allocator, equal} {
- rehash(cnt);
- }
- /*! @brief Default copy constructor. */
- dense_map(const dense_map &) = default;
- /**
- * @brief Allocator-extended copy constructor.
- * @param other The instance to copy from.
- * @param allocator The allocator to use.
- */
- dense_map(const dense_map &other, const allocator_type &allocator)
- : sparse{std::piecewise_construct, std::forward_as_tuple(other.sparse.first(), allocator), std::forward_as_tuple(other.sparse.second())},
- packed{std::piecewise_construct, std::forward_as_tuple(other.packed.first(), allocator), std::forward_as_tuple(other.packed.second())},
- threshold{other.threshold} {}
- /*! @brief Default move constructor. */
- dense_map(dense_map &&) noexcept = default;
- /**
- * @brief Allocator-extended move constructor.
- * @param other The instance to move from.
- * @param allocator The allocator to use.
- */
- dense_map(dense_map &&other, const allocator_type &allocator)
- : sparse{std::piecewise_construct, std::forward_as_tuple(std::move(other.sparse.first()), allocator), std::forward_as_tuple(std::move(other.sparse.second()))},
- packed{std::piecewise_construct, std::forward_as_tuple(std::move(other.packed.first()), allocator), std::forward_as_tuple(std::move(other.packed.second()))},
- threshold{other.threshold} {}
- /*! @brief Default destructor. */
- ~dense_map() = default;
- /**
- * @brief Default copy assignment operator.
- * @return This container.
- */
- dense_map &operator=(const dense_map &) = default;
- /**
- * @brief Default move assignment operator.
- * @return This container.
- */
- dense_map &operator=(dense_map &&) noexcept = default;
- /**
- * @brief Exchanges the contents with those of a given container.
- * @param other Container to exchange the content with.
- */
- void swap(dense_map &other) noexcept {
- using std::swap;
- swap(sparse, other.sparse);
- swap(packed, other.packed);
- swap(threshold, other.threshold);
- }
- /**
- * @brief Returns the associated allocator.
- * @return The associated allocator.
- */
- [[nodiscard]] constexpr allocator_type get_allocator() const noexcept {
- return sparse.first().get_allocator();
- }
- /**
- * @brief Returns an iterator to the beginning.
- *
- * If the array is empty, the returned iterator will be equal to `end()`.
- *
- * @return An iterator to the first instance of the internal array.
- */
- [[nodiscard]] const_iterator cbegin() const noexcept {
- return packed.first().begin();
- }
- /*! @copydoc cbegin */
- [[nodiscard]] const_iterator begin() const noexcept {
- return cbegin();
- }
- /*! @copydoc begin */
- [[nodiscard]] iterator begin() noexcept {
- return packed.first().begin();
- }
- /**
- * @brief Returns an iterator to the end.
- * @return An iterator to the element following the last instance of the
- * internal array.
- */
- [[nodiscard]] const_iterator cend() const noexcept {
- return packed.first().end();
- }
- /*! @copydoc cend */
- [[nodiscard]] const_iterator end() const noexcept {
- return cend();
- }
- /*! @copydoc end */
- [[nodiscard]] iterator end() noexcept {
- return packed.first().end();
- }
- /**
- * @brief Checks whether a container is empty.
- * @return True if the container is empty, false otherwise.
- */
- [[nodiscard]] bool empty() const noexcept {
- return packed.first().empty();
- }
- /**
- * @brief Returns the number of elements in a container.
- * @return Number of elements in a container.
- */
- [[nodiscard]] size_type size() const noexcept {
- return packed.first().size();
- }
- /**
- * @brief Returns the maximum possible number of elements.
- * @return Maximum possible number of elements.
- */
- [[nodiscard]] size_type max_size() const noexcept {
- return packed.first().max_size();
- }
- /*! @brief Clears the container. */
- void clear() noexcept {
- sparse.first().clear();
- packed.first().clear();
- rehash(0u);
- }
- /**
- * @brief Inserts an element into the container, if the key does not exist.
- * @param value A key-value pair eventually convertible to the value type.
- * @return A pair consisting of an iterator to the inserted element (or to
- * the element that prevented the insertion) and a bool denoting whether the
- * insertion took place.
- */
- std::pair<iterator, bool> insert(const value_type &value) {
- return insert_or_do_nothing(value.first, value.second);
- }
- /*! @copydoc insert */
- std::pair<iterator, bool> insert(value_type &&value) {
- return insert_or_do_nothing(std::move(value.first), std::move(value.second));
- }
- /**
- * @copydoc insert
- * @tparam Arg Type of the key-value pair to insert into the container.
- */
- template<typename Arg>
- std::enable_if_t<std::is_constructible_v<value_type, Arg &&>, std::pair<iterator, bool>>
- insert(Arg &&value) {
- return insert_or_do_nothing(std::forward<Arg>(value).first, std::forward<Arg>(value).second);
- }
- /**
- * @brief Inserts elements into the container, if their keys do not exist.
- * @tparam It Type of input iterator.
- * @param first An iterator to the first element of the range of elements.
- * @param last An iterator past the last element of the range of elements.
- */
- template<typename It>
- void insert(It first, It last) {
- for(; first != last; ++first) {
- insert(*first);
- }
- }
- /**
- * @brief Inserts an element into the container or assigns to the current
- * element if the key already exists.
- * @tparam Arg Type of the value to insert or assign.
- * @param key A key used both to look up and to insert if not found.
- * @param value A value to insert or assign.
- * @return A pair consisting of an iterator to the element and a bool
- * denoting whether the insertion took place.
- */
- template<typename Arg>
- std::pair<iterator, bool> insert_or_assign(const key_type &key, Arg &&value) {
- return insert_or_overwrite(key, std::forward<Arg>(value));
- }
- /*! @copydoc insert_or_assign */
- template<typename Arg>
- std::pair<iterator, bool> insert_or_assign(key_type &&key, Arg &&value) {
- return insert_or_overwrite(std::move(key), std::forward<Arg>(value));
- }
- /**
- * @brief Constructs an element in-place, if the key does not exist.
- *
- * The element is also constructed when the container already has the key,
- * in which case the newly constructed object is destroyed immediately.
- *
- * @tparam Args Types of arguments to forward to the constructor of the
- * element.
- * @param args Arguments to forward to the constructor of the element.
- * @return A pair consisting of an iterator to the inserted element (or to
- * the element that prevented the insertion) and a bool denoting whether the
- * insertion took place.
- */
- template<typename... Args>
- std::pair<iterator, bool> emplace([[maybe_unused]] Args &&...args) {
- if constexpr(sizeof...(Args) == 0u) {
- return insert_or_do_nothing(key_type{});
- } else if constexpr(sizeof...(Args) == 1u) {
- return insert_or_do_nothing(std::forward<Args>(args).first..., std::forward<Args>(args).second...);
- } else if constexpr(sizeof...(Args) == 2u) {
- return insert_or_do_nothing(std::forward<Args>(args)...);
- } else {
- auto &node = packed.first().emplace_back(packed.first().size(), std::forward<Args>(args)...);
- const auto index = key_to_bucket(node.element.first);
- if(auto it = constrained_find(node.element.first, index); it != end()) {
- packed.first().pop_back();
- return std::make_pair(it, false);
- }
- std::swap(node.next, sparse.first()[index]);
- rehash_if_required();
- return std::make_pair(--end(), true);
- }
- }
- /**
- * @brief Inserts in-place if the key does not exist, does nothing if the
- * key exists.
- * @tparam Args Types of arguments to forward to the constructor of the
- * element.
- * @param key A key used both to look up and to insert if not found.
- * @param args Arguments to forward to the constructor of the element.
- * @return A pair consisting of an iterator to the inserted element (or to
- * the element that prevented the insertion) and a bool denoting whether the
- * insertion took place.
- */
- template<typename... Args>
- std::pair<iterator, bool> try_emplace(const key_type &key, Args &&...args) {
- return insert_or_do_nothing(key, std::forward<Args>(args)...);
- }
- /*! @copydoc try_emplace */
- template<typename... Args>
- std::pair<iterator, bool> try_emplace(key_type &&key, Args &&...args) {
- return insert_or_do_nothing(std::move(key), std::forward<Args>(args)...);
- }
- /**
- * @brief Removes an element from a given position.
- * @param pos An iterator to the element to remove.
- * @return An iterator following the removed element.
- */
- iterator erase(const_iterator pos) {
- const auto diff = pos - cbegin();
- erase(pos->first);
- return begin() + diff;
- }
- /**
- * @brief Removes the given elements from a container.
- * @param first An iterator to the first element of the range of elements.
- * @param last An iterator past the last element of the range of elements.
- * @return An iterator following the last removed element.
- */
- iterator erase(const_iterator first, const_iterator last) {
- const auto dist = first - cbegin();
- for(auto from = last - cbegin(); from != dist; --from) {
- erase(packed.first()[static_cast<size_type>(from) - 1u].element.first);
- }
- return (begin() + dist);
- }
- /**
- * @brief Removes the element associated with a given key.
- * @param key A key value of an element to remove.
- * @return Number of elements removed (either 0 or 1).
- */
- size_type erase(const key_type &key) {
- for(size_type *curr = &sparse.first()[key_to_bucket(key)]; *curr != placeholder_position; curr = &packed.first()[*curr].next) {
- if(packed.second()(packed.first()[*curr].element.first, key)) {
- const auto index = *curr;
- *curr = packed.first()[*curr].next;
- move_and_pop(index);
- return 1u;
- }
- }
- return 0u;
- }
- /**
- * @brief Accesses a given element with bounds checking.
- * @param key A key of an element to find.
- * @return A reference to the mapped value of the requested element.
- */
- [[nodiscard]] mapped_type &at(const key_type &key) {
- auto it = find(key);
- ENTT_ASSERT(it != end(), "Invalid key");
- return it->second;
- }
- /*! @copydoc at */
- [[nodiscard]] const mapped_type &at(const key_type &key) const {
- auto it = find(key);
- ENTT_ASSERT(it != cend(), "Invalid key");
- return it->second;
- }
- /**
- * @brief Accesses a given element with bounds checking.
- * @tparam Other Type of the key of an element to find.
- * @param key A key of an element to find.
- * @return A reference to the mapped value of the requested element.
- */
- template<typename Other>
- [[nodiscard]] std::enable_if_t<is_transparent_v<hasher> && is_transparent_v<key_equal>, std::conditional_t<false, Other, mapped_type const &>>
- at(const Other &key) const {
- auto it = find(key);
- ENTT_ASSERT(it != cend(), "Invalid key");
- return it->second;
- }
- /*! @copydoc at */
- template<typename Other>
- [[nodiscard]] std::enable_if_t<is_transparent_v<hasher> && is_transparent_v<key_equal>, std::conditional_t<false, Other, mapped_type &>>
- at(const Other &key) {
- auto it = find(key);
- ENTT_ASSERT(it != end(), "Invalid key");
- return it->second;
- }
- /**
- * @brief Accesses or inserts a given element.
- * @param key A key of an element to find or insert.
- * @return A reference to the mapped value of the requested element.
- */
- [[nodiscard]] mapped_type &operator[](const key_type &key) {
- return insert_or_do_nothing(key).first->second;
- }
- /**
- * @brief Accesses or inserts a given element.
- * @param key A key of an element to find or insert.
- * @return A reference to the mapped value of the requested element.
- */
- [[nodiscard]] mapped_type &operator[](key_type &&key) {
- return insert_or_do_nothing(std::move(key)).first->second;
- }
- /**
- * @brief Returns the number of elements matching a key (either 1 or 0).
- * @param key Key value of an element to search for.
- * @return Number of elements matching the key (either 1 or 0).
- */
- [[nodiscard]] size_type count(const key_type &key) const {
- return find(key) != end();
- }
- /**
- * @brief Returns the number of elements matching a key (either 1 or 0).
- * @tparam Other Type of the key value of an element to search for.
- * @param key Key value of an element to search for.
- * @return Number of elements matching the key (either 1 or 0).
- */
- template<typename Other>
- [[nodiscard]] std::enable_if_t<is_transparent_v<hasher> && is_transparent_v<key_equal>, std::conditional_t<false, Other, size_type>>
- count(const Other &key) const {
- return find(key) != end();
- }
- /**
- * @brief Finds an element with a given key.
- * @param key Key value of an element to search for.
- * @return An iterator to an element with the given key. If no such element
- * is found, a past-the-end iterator is returned.
- */
- [[nodiscard]] iterator find(const key_type &key) {
- return constrained_find(key, key_to_bucket(key));
- }
- /*! @copydoc find */
- [[nodiscard]] const_iterator find(const key_type &key) const {
- return constrained_find(key, key_to_bucket(key));
- }
- /**
- * @brief Finds an element with a key that compares _equivalent_ to a given
- * key.
- * @tparam Other Type of the key value of an element to search for.
- * @param key Key value of an element to search for.
- * @return An iterator to an element with the given key. If no such element
- * is found, a past-the-end iterator is returned.
- */
- template<typename Other>
- [[nodiscard]] std::enable_if_t<is_transparent_v<hasher> && is_transparent_v<key_equal>, std::conditional_t<false, Other, iterator>>
- find(const Other &key) {
- return constrained_find(key, key_to_bucket(key));
- }
- /*! @copydoc find */
- template<typename Other>
- [[nodiscard]] std::enable_if_t<is_transparent_v<hasher> && is_transparent_v<key_equal>, std::conditional_t<false, Other, const_iterator>>
- find(const Other &key) const {
- return constrained_find(key, key_to_bucket(key));
- }
- /**
- * @brief Returns a range containing all elements with a given key.
- * @param key Key value of an element to search for.
- * @return A pair of iterators pointing to the first element and past the
- * last element of the range.
- */
- [[nodiscard]] std::pair<iterator, iterator> equal_range(const key_type &key) {
- const auto it = find(key);
- return {it, it + !(it == end())};
- }
- /*! @copydoc equal_range */
- [[nodiscard]] std::pair<const_iterator, const_iterator> equal_range(const key_type &key) const {
- const auto it = find(key);
- return {it, it + !(it == cend())};
- }
- /**
- * @brief Returns a range containing all elements that compare _equivalent_
- * to a given key.
- * @tparam Other Type of an element to search for.
- * @param key Key value of an element to search for.
- * @return A pair of iterators pointing to the first element and past the
- * last element of the range.
- */
- template<typename Other>
- [[nodiscard]] std::enable_if_t<is_transparent_v<hasher> && is_transparent_v<key_equal>, std::conditional_t<false, Other, std::pair<iterator, iterator>>>
- equal_range(const Other &key) {
- const auto it = find(key);
- return {it, it + !(it == end())};
- }
- /*! @copydoc equal_range */
- template<typename Other>
- [[nodiscard]] std::enable_if_t<is_transparent_v<hasher> && is_transparent_v<key_equal>, std::conditional_t<false, Other, std::pair<const_iterator, const_iterator>>>
- equal_range(const Other &key) const {
- const auto it = find(key);
- return {it, it + !(it == cend())};
- }
- /**
- * @brief Checks if the container contains an element with a given key.
- * @param key Key value of an element to search for.
- * @return True if there is such an element, false otherwise.
- */
- [[nodiscard]] bool contains(const key_type &key) const {
- return (find(key) != cend());
- }
- /**
- * @brief Checks if the container contains an element with a key that
- * compares _equivalent_ to a given value.
- * @tparam Other Type of the key value of an element to search for.
- * @param key Key value of an element to search for.
- * @return True if there is such an element, false otherwise.
- */
- template<typename Other>
- [[nodiscard]] std::enable_if_t<is_transparent_v<hasher> && is_transparent_v<key_equal>, std::conditional_t<false, Other, bool>>
- contains(const Other &key) const {
- return (find(key) != cend());
- }
- /**
- * @brief Returns an iterator to the beginning of a given bucket.
- * @param index An index of a bucket to access.
- * @return An iterator to the beginning of the given bucket.
- */
- [[nodiscard]] const_local_iterator cbegin(const size_type index) const {
- return {packed.first().begin(), sparse.first()[index]};
- }
- /**
- * @brief Returns an iterator to the beginning of a given bucket.
- * @param index An index of a bucket to access.
- * @return An iterator to the beginning of the given bucket.
- */
- [[nodiscard]] const_local_iterator begin(const size_type index) const {
- return cbegin(index);
- }
- /**
- * @brief Returns an iterator to the beginning of a given bucket.
- * @param index An index of a bucket to access.
- * @return An iterator to the beginning of the given bucket.
- */
- [[nodiscard]] local_iterator begin(const size_type index) {
- return {packed.first().begin(), sparse.first()[index]};
- }
- /**
- * @brief Returns an iterator to the end of a given bucket.
- * @param index An index of a bucket to access.
- * @return An iterator to the end of the given bucket.
- */
- [[nodiscard]] const_local_iterator cend([[maybe_unused]] const size_type index) const {
- return {};
- }
- /**
- * @brief Returns an iterator to the end of a given bucket.
- * @param index An index of a bucket to access.
- * @return An iterator to the end of the given bucket.
- */
- [[nodiscard]] const_local_iterator end(const size_type index) const {
- return cend(index);
- }
- /**
- * @brief Returns an iterator to the end of a given bucket.
- * @param index An index of a bucket to access.
- * @return An iterator to the end of the given bucket.
- */
- [[nodiscard]] local_iterator end([[maybe_unused]] const size_type index) {
- return {};
- }
- /**
- * @brief Returns the number of buckets.
- * @return The number of buckets.
- */
- [[nodiscard]] size_type bucket_count() const {
- return sparse.first().size();
- }
- /**
- * @brief Returns the maximum number of buckets.
- * @return The maximum number of buckets.
- */
- [[nodiscard]] size_type max_bucket_count() const {
- return sparse.first().max_size();
- }
- /**
- * @brief Returns the number of elements in a given bucket.
- * @param index The index of the bucket to examine.
- * @return The number of elements in the given bucket.
- */
- [[nodiscard]] size_type bucket_size(const size_type index) const {
- return static_cast<size_type>(std::distance(begin(index), end(index)));
- }
- /**
- * @brief Returns the bucket for a given key.
- * @param key The value of the key to examine.
- * @return The bucket for the given key.
- */
- [[nodiscard]] size_type bucket(const key_type &key) const {
- return key_to_bucket(key);
- }
- /**
- * @brief Returns the average number of elements per bucket.
- * @return The average number of elements per bucket.
- */
- [[nodiscard]] float load_factor() const {
- return static_cast<float>(size()) / static_cast<float>(bucket_count());
- }
- /**
- * @brief Returns the maximum average number of elements per bucket.
- * @return The maximum average number of elements per bucket.
- */
- [[nodiscard]] float max_load_factor() const {
- return threshold;
- }
- /**
- * @brief Sets the desired maximum average number of elements per bucket.
- * @param value A desired maximum average number of elements per bucket.
- */
- void max_load_factor(const float value) {
- ENTT_ASSERT(value > 0.f, "Invalid load factor");
- threshold = value;
- rehash(0u);
- }
- /**
- * @brief Reserves at least the specified number of buckets and regenerates
- * the hash table.
- * @param cnt New number of buckets.
- */
- void rehash(const size_type cnt) {
- auto value = cnt > minimum_capacity ? cnt : minimum_capacity;
- const auto cap = static_cast<size_type>(static_cast<float>(size()) / max_load_factor());
- value = value > cap ? value : cap;
- if(const auto sz = next_power_of_two(value); sz != bucket_count()) {
- sparse.first().resize(sz);
- for(auto &&elem: sparse.first()) {
- elem = placeholder_position;
- }
- for(size_type pos{}, last = size(); pos < last; ++pos) {
- const auto index = key_to_bucket(packed.first()[pos].element.first);
- packed.first()[pos].next = std::exchange(sparse.first()[index], pos);
- }
- }
- }
- /**
- * @brief Reserves space for at least the specified number of elements and
- * regenerates the hash table.
- * @param cnt New number of elements.
- */
- void reserve(const size_type cnt) {
- packed.first().reserve(cnt);
- rehash(static_cast<size_type>(std::ceil(static_cast<float>(cnt) / max_load_factor())));
- }
- /**
- * @brief Returns the function used to hash the keys.
- * @return The function used to hash the keys.
- */
- [[nodiscard]] hasher hash_function() const {
- return sparse.second();
- }
- /**
- * @brief Returns the function used to compare keys for equality.
- * @return The function used to compare keys for equality.
- */
- [[nodiscard]] key_equal key_eq() const {
- return packed.second();
- }
- private:
- compressed_pair<sparse_container_type, hasher> sparse;
- compressed_pair<packed_container_type, key_equal> packed;
- float threshold{default_threshold};
- };
- } // namespace entt
- /*! @cond TURN_OFF_DOXYGEN */
- namespace std {
- template<typename Key, typename Value, typename Allocator>
- struct uses_allocator<entt::internal::dense_map_node<Key, Value>, Allocator>
- : std::true_type {};
- } // namespace std
- /*! @endcond */
- #endif
- // #include "../core/algorithm.hpp"
- // #include "../core/any.hpp"
- // #include "../core/fwd.hpp"
- // #include "../core/iterator.hpp"
- // #include "../core/memory.hpp"
- // #include "../core/type_info.hpp"
- // #include "../core/type_traits.hpp"
- // #include "../core/utility.hpp"
- // #include "entity.hpp"
- // #include "fwd.hpp"
- // #include "group.hpp"
- // #include "mixin.hpp"
- #ifndef ENTT_ENTITY_MIXIN_HPP
- #define ENTT_ENTITY_MIXIN_HPP
- #include <type_traits>
- #include <utility>
- // #include "../config/config.h"
- // #include "../core/any.hpp"
- // #include "../core/type_info.hpp"
- // #include "../signal/sigh.hpp"
- // #include "entity.hpp"
- // #include "fwd.hpp"
- namespace entt {
- /*! @cond TURN_OFF_DOXYGEN */
- namespace internal {
- template<typename, typename, typename = void>
- struct has_on_construct final: std::false_type {};
- template<typename Type, typename Registry>
- struct has_on_construct<Type, Registry, std::void_t<decltype(Type::on_construct(std::declval<Registry &>(), std::declval<Registry>().create()))>>
- : std::true_type {};
- template<typename, typename, typename = void>
- struct has_on_update final: std::false_type {};
- template<typename Type, typename Registry>
- struct has_on_update<Type, Registry, std::void_t<decltype(Type::on_update(std::declval<Registry &>(), std::declval<Registry>().create()))>>
- : std::true_type {};
- template<typename, typename, typename = void>
- struct has_on_destroy final: std::false_type {};
- template<typename Type, typename Registry>
- struct has_on_destroy<Type, Registry, std::void_t<decltype(Type::on_destroy(std::declval<Registry &>(), std::declval<Registry>().create()))>>
- : std::true_type {};
- } // namespace internal
- /*! @endcond */
- /**
- * @brief Mixin type used to add signal support to storage types.
- *
- * The function type of a listener is equivalent to:
- *
- * @code{.cpp}
- * void(basic_registry<entity_type> &, entity_type);
- * @endcode
- *
- * This applies to all signals made available.
- *
- * @tparam Type Underlying storage type.
- * @tparam Registry Basic registry type.
- */
- template<typename Type, typename Registry>
- class basic_sigh_mixin final: public Type {
- using underlying_type = Type;
- using owner_type = Registry;
- using basic_registry_type = basic_registry<typename owner_type::entity_type, typename owner_type::allocator_type>;
- using sigh_type = sigh<void(owner_type &, const typename underlying_type::entity_type), typename underlying_type::allocator_type>;
- using underlying_iterator = typename underlying_type::base_type::basic_iterator;
- static_assert(std::is_base_of_v<basic_registry_type, owner_type>, "Invalid registry type");
- [[nodiscard]] auto &owner_or_assert() const noexcept {
- ENTT_ASSERT(owner != nullptr, "Invalid pointer to registry");
- return static_cast<owner_type &>(*owner);
- }
- private:
- void pop(underlying_iterator first, underlying_iterator last) final {
- if(auto ® = owner_or_assert(); destruction.empty()) {
- underlying_type::pop(first, last);
- } else {
- for(; first != last; ++first) {
- const auto entt = *first;
- destruction.publish(reg, entt);
- const auto it = underlying_type::find(entt);
- underlying_type::pop(it, it + 1u);
- }
- }
- }
- void pop_all() final {
- if(auto ® = owner_or_assert(); !destruction.empty()) {
- if constexpr(std::is_same_v<typename underlying_type::element_type, entity_type>) {
- for(typename underlying_type::size_type pos{}, last = underlying_type::free_list(); pos < last; ++pos) {
- destruction.publish(reg, underlying_type::base_type::operator[](pos));
- }
- } else {
- for(auto entt: static_cast<typename underlying_type::base_type &>(*this)) {
- if constexpr(underlying_type::storage_policy == deletion_policy::in_place) {
- if(entt != tombstone) {
- destruction.publish(reg, entt);
- }
- } else {
- destruction.publish(reg, entt);
- }
- }
- }
- }
- underlying_type::pop_all();
- }
- underlying_iterator try_emplace(const typename underlying_type::entity_type entt, const bool force_back, const void *value) final {
- const auto it = underlying_type::try_emplace(entt, force_back, value);
- if(auto ® = owner_or_assert(); it != underlying_type::base_type::end()) {
- construction.publish(reg, *it);
- }
- return it;
- }
- void bind_any(any value) noexcept final {
- owner = any_cast<basic_registry_type>(&value);
- if constexpr(!std::is_same_v<registry_type, basic_registry_type>) {
- if(owner == nullptr) {
- owner = any_cast<registry_type>(&value);
- }
- }
- underlying_type::bind_any(std::move(value));
- }
- public:
- /*! @brief Allocator type. */
- using allocator_type = typename underlying_type::allocator_type;
- /*! @brief Underlying entity identifier. */
- using entity_type = typename underlying_type::entity_type;
- /*! @brief Expected registry type. */
- using registry_type = owner_type;
- /*! @brief Default constructor. */
- basic_sigh_mixin()
- : basic_sigh_mixin{allocator_type{}} {}
- /**
- * @brief Constructs an empty storage with a given allocator.
- * @param allocator The allocator to use.
- */
- explicit basic_sigh_mixin(const allocator_type &allocator)
- : underlying_type{allocator},
- owner{},
- construction{allocator},
- destruction{allocator},
- update{allocator} {
- if constexpr(internal::has_on_construct<typename underlying_type::element_type, Registry>::value) {
- sink{construction}.template connect<&underlying_type::element_type::on_construct>();
- }
- if constexpr(internal::has_on_update<typename underlying_type::element_type, Registry>::value) {
- sink{update}.template connect<&underlying_type::element_type::on_update>();
- }
- if constexpr(internal::has_on_destroy<typename underlying_type::element_type, Registry>::value) {
- sink{destruction}.template connect<&underlying_type::element_type::on_destroy>();
- }
- }
- /*! @brief Default copy constructor, deleted on purpose. */
- basic_sigh_mixin(const basic_sigh_mixin &) = delete;
- /**
- * @brief Move constructor.
- * @param other The instance to move from.
- */
- basic_sigh_mixin(basic_sigh_mixin &&other) noexcept
- : underlying_type{static_cast<underlying_type &&>(other)},
- owner{other.owner},
- construction{std::move(other.construction)},
- destruction{std::move(other.destruction)},
- update{std::move(other.update)} {}
- /**
- * @brief Allocator-extended move constructor.
- * @param other The instance to move from.
- * @param allocator The allocator to use.
- */
- basic_sigh_mixin(basic_sigh_mixin &&other, const allocator_type &allocator)
- : underlying_type{static_cast<underlying_type &&>(other), allocator},
- owner{other.owner},
- construction{std::move(other.construction), allocator},
- destruction{std::move(other.destruction), allocator},
- update{std::move(other.update), allocator} {}
- /*! @brief Default destructor. */
- ~basic_sigh_mixin() override = default;
- /**
- * @brief Default copy assignment operator, deleted on purpose.
- * @return This mixin.
- */
- basic_sigh_mixin &operator=(const basic_sigh_mixin &) = delete;
- /**
- * @brief Move assignment operator.
- * @param other The instance to move from.
- * @return This mixin.
- */
- basic_sigh_mixin &operator=(basic_sigh_mixin &&other) noexcept {
- swap(other);
- return *this;
- }
- /**
- * @brief Exchanges the contents with those of a given storage.
- * @param other Storage to exchange the content with.
- */
- void swap(basic_sigh_mixin &other) noexcept {
- using std::swap;
- swap(owner, other.owner);
- swap(construction, other.construction);
- swap(destruction, other.destruction);
- swap(update, other.update);
- underlying_type::swap(other);
- }
- /**
- * @brief Returns a sink object.
- *
- * The sink returned by this function can be used to receive notifications
- * whenever a new instance is created and assigned to an entity.<br/>
- * Listeners are invoked after the object has been assigned to the entity.
- *
- * @sa sink
- *
- * @return A temporary sink object.
- */
- [[nodiscard]] auto on_construct() noexcept {
- return sink{construction};
- }
- /**
- * @brief Returns a sink object.
- *
- * The sink returned by this function can be used to receive notifications
- * whenever an instance is explicitly updated.<br/>
- * Listeners are invoked after the object has been updated.
- *
- * @sa sink
- *
- * @return A temporary sink object.
- */
- [[nodiscard]] auto on_update() noexcept {
- return sink{update};
- }
- /**
- * @brief Returns a sink object.
- *
- * The sink returned by this function can be used to receive notifications
- * whenever an instance is removed from an entity and thus destroyed.<br/>
- * Listeners are invoked before the object has been removed from the entity.
- *
- * @sa sink
- *
- * @return A temporary sink object.
- */
- [[nodiscard]] auto on_destroy() noexcept {
- return sink{destruction};
- }
- /**
- * @brief Checks if a mixin refers to a valid registry.
- * @return True if the mixin refers to a valid registry, false otherwise.
- */
- [[nodiscard]] explicit operator bool() const noexcept {
- return (owner != nullptr);
- }
- /**
- * @brief Returns a pointer to the underlying registry, if any.
- * @return A pointer to the underlying registry, if any.
- */
- [[nodiscard]] const registry_type ®istry() const noexcept {
- return owner_or_assert();
- }
- /*! @copydoc registry */
- [[nodiscard]] registry_type ®istry() noexcept {
- return owner_or_assert();
- }
- /**
- * @brief Creates a new identifier or recycles a destroyed one.
- * @return A valid identifier.
- */
- auto generate() {
- const auto entt = underlying_type::generate();
- construction.publish(owner_or_assert(), entt);
- return entt;
- }
- /**
- * @brief Creates a new identifier or recycles a destroyed one.
- * @param hint Required identifier.
- * @return A valid identifier.
- */
- entity_type generate(const entity_type hint) {
- const auto entt = underlying_type::generate(hint);
- construction.publish(owner_or_assert(), entt);
- return entt;
- }
- /**
- * @brief Assigns each element in a range an identifier.
- * @tparam It Type of mutable forward iterator.
- * @param first An iterator to the first element of the range to generate.
- * @param last An iterator past the last element of the range to generate.
- */
- template<typename It>
- void generate(It first, It last) {
- underlying_type::generate(first, last);
- if(auto ® = owner_or_assert(); !construction.empty()) {
- for(; first != last; ++first) {
- construction.publish(reg, *first);
- }
- }
- }
- /**
- * @brief Assigns an entity to a storage and constructs its object.
- * @tparam Args Types of arguments to forward to the underlying storage.
- * @param entt A valid identifier.
- * @param args Parameters to forward to the underlying storage.
- * @return A reference to the newly created object.
- */
- template<typename... Args>
- decltype(auto) emplace(const entity_type entt, Args &&...args) {
- underlying_type::emplace(entt, std::forward<Args>(args)...);
- construction.publish(owner_or_assert(), entt);
- return this->get(entt);
- }
- /**
- * @brief Updates the instance assigned to a given entity in-place.
- * @tparam Func Types of the function objects to invoke.
- * @param entt A valid identifier.
- * @param func Valid function objects.
- * @return A reference to the patched instance.
- */
- template<typename... Func>
- decltype(auto) patch(const entity_type entt, Func &&...func) {
- underlying_type::patch(entt, std::forward<Func>(func)...);
- update.publish(owner_or_assert(), entt);
- return this->get(entt);
- }
- /**
- * @brief Assigns one or more entities to a storage and constructs their
- * objects from a given instance.
- * @tparam It Type of input iterator.
- * @tparam Args Types of arguments to forward to the underlying storage.
- * @param first An iterator to the first element of the range of entities.
- * @param last An iterator past the last element of the range of entities.
- * @param args Parameters to use to forward to the underlying storage.
- */
- template<typename It, typename... Args>
- void insert(It first, It last, Args &&...args) {
- auto from = underlying_type::size();
- underlying_type::insert(first, last, std::forward<Args>(args)...);
- if(auto ® = owner_or_assert(); !construction.empty()) {
- // fine as long as insert passes force_back true to try_emplace
- for(const auto to = underlying_type::size(); from != to; ++from) {
- construction.publish(reg, underlying_type::operator[](from));
- }
- }
- }
- private:
- basic_registry_type *owner;
- sigh_type construction;
- sigh_type destruction;
- sigh_type update;
- };
- /**
- * @brief Mixin type used to add _reactive_ support to storage types.
- * @tparam Type Underlying storage type.
- * @tparam Registry Basic registry type.
- */
- template<typename Type, typename Registry>
- class basic_reactive_mixin final: public Type {
- using underlying_type = Type;
- using owner_type = Registry;
- using alloc_traits = std::allocator_traits<typename underlying_type::allocator_type>;
- using basic_registry_type = basic_registry<typename owner_type::entity_type, typename owner_type::allocator_type>;
- using container_type = std::vector<connection, typename alloc_traits::template rebind_alloc<connection>>;
- static_assert(std::is_base_of_v<basic_registry_type, owner_type>, "Invalid registry type");
- [[nodiscard]] auto &owner_or_assert() const noexcept {
- ENTT_ASSERT(owner != nullptr, "Invalid pointer to registry");
- return static_cast<owner_type &>(*owner);
- }
- void emplace_element(const Registry &, typename underlying_type::entity_type entity) {
- if(!underlying_type::contains(entity)) {
- underlying_type::emplace(entity);
- }
- }
- private:
- void bind_any(any value) noexcept final {
- owner = any_cast<basic_registry_type>(&value);
- if constexpr(!std::is_same_v<registry_type, basic_registry_type>) {
- if(owner == nullptr) {
- owner = any_cast<registry_type>(&value);
- }
- }
- underlying_type::bind_any(std::move(value));
- }
- public:
- /*! @brief Allocator type. */
- using allocator_type = typename underlying_type::allocator_type;
- /*! @brief Underlying entity identifier. */
- using entity_type = typename underlying_type::entity_type;
- /*! @brief Expected registry type. */
- using registry_type = owner_type;
- /*! @brief Default constructor. */
- basic_reactive_mixin()
- : basic_reactive_mixin{allocator_type{}} {}
- /**
- * @brief Constructs an empty storage with a given allocator.
- * @param allocator The allocator to use.
- */
- explicit basic_reactive_mixin(const allocator_type &allocator)
- : underlying_type{allocator},
- owner{},
- conn{allocator} {
- }
- /*! @brief Default copy constructor, deleted on purpose. */
- basic_reactive_mixin(const basic_reactive_mixin &) = delete;
- /**
- * @brief Move constructor.
- * @param other The instance to move from.
- */
- basic_reactive_mixin(basic_reactive_mixin &&other) noexcept
- : underlying_type{static_cast<underlying_type &&>(other)},
- owner{other.owner},
- conn{std::move(other.conn)} {
- }
- /**
- * @brief Allocator-extended move constructor.
- * @param other The instance to move from.
- * @param allocator The allocator to use.
- */
- basic_reactive_mixin(basic_reactive_mixin &&other, const allocator_type &allocator)
- : underlying_type{static_cast<underlying_type &&>(other), allocator},
- owner{other.owner},
- conn{std::move(other.conn), allocator} {
- }
- /*! @brief Default destructor. */
- ~basic_reactive_mixin() override = default;
- /**
- * @brief Default copy assignment operator, deleted on purpose.
- * @return This mixin.
- */
- basic_reactive_mixin &operator=(const basic_reactive_mixin &) = delete;
- /**
- * @brief Move assignment operator.
- * @param other The instance to move from.
- * @return This mixin.
- */
- basic_reactive_mixin &operator=(basic_reactive_mixin &&other) noexcept {
- underlying_type::swap(other);
- return *this;
- }
- /**
- * @brief Makes storage _react_ to creation of objects of the given type.
- * @tparam Clazz Type of element to _react_ to.
- * @tparam Candidate Function to use to _react_ to the event.
- * @param id Optional name used to map the storage within the registry.
- * @return This mixin.
- */
- template<typename Clazz, auto Candidate = &basic_reactive_mixin::emplace_element>
- basic_reactive_mixin &on_construct(const id_type id = type_hash<Clazz>::value()) {
- auto curr = owner_or_assert().template storage<Clazz>(id).on_construct().template connect<Candidate>(*this);
- conn.push_back(std::move(curr));
- return *this;
- }
- /**
- * @brief Makes storage _react_ to update of objects of the given type.
- * @tparam Clazz Type of element to _react_ to.
- * @tparam Candidate Function to use to _react_ to the event.
- * @param id Optional name used to map the storage within the registry.
- * @return This mixin.
- */
- template<typename Clazz, auto Candidate = &basic_reactive_mixin::emplace_element>
- basic_reactive_mixin &on_update(const id_type id = type_hash<Clazz>::value()) {
- auto curr = owner_or_assert().template storage<Clazz>(id).on_update().template connect<Candidate>(*this);
- conn.push_back(std::move(curr));
- return *this;
- }
- /**
- * @brief Makes storage _react_ to destruction of objects of the given type.
- * @tparam Clazz Type of element to _react_ to.
- * @tparam Candidate Function to use to _react_ to the event.
- * @param id Optional name used to map the storage within the registry.
- * @return This mixin.
- */
- template<typename Clazz, auto Candidate = &basic_reactive_mixin::emplace_element>
- basic_reactive_mixin &on_destroy(const id_type id = type_hash<Clazz>::value()) {
- auto curr = owner_or_assert().template storage<Clazz>(id).on_destroy().template connect<Candidate>(*this);
- conn.push_back(std::move(curr));
- return *this;
- }
- /**
- * @brief Checks if a mixin refers to a valid registry.
- * @return True if the mixin refers to a valid registry, false otherwise.
- */
- [[nodiscard]] explicit operator bool() const noexcept {
- return (owner != nullptr);
- }
- /**
- * @brief Returns a pointer to the underlying registry, if any.
- * @return A pointer to the underlying registry, if any.
- */
- [[nodiscard]] const registry_type ®istry() const noexcept {
- return owner_or_assert();
- }
- /*! @copydoc registry */
- [[nodiscard]] registry_type ®istry() noexcept {
- return owner_or_assert();
- }
- /**
- * @brief Returns a view that is filtered by the underlying storage.
- * @tparam Get Types of elements used to construct the view.
- * @tparam Exclude Types of elements used to filter the view.
- * @return A newly created view.
- */
- template<typename... Get, typename... Exclude>
- [[nodiscard]] basic_view<get_t<const basic_reactive_mixin, typename basic_registry_type::template storage_for_type<const Get>...>, exclude_t<typename basic_registry_type::template storage_for_type<const Exclude>...>>
- view(exclude_t<Exclude...> = exclude_t{}) const {
- const owner_type &parent = owner_or_assert();
- basic_view<get_t<const basic_reactive_mixin, typename basic_registry_type::template storage_for_type<const Get>...>, exclude_t<typename basic_registry_type::template storage_for_type<const Exclude>...>> elem{};
- [&elem](const auto *...curr) { ((curr ? elem.storage(*curr) : void()), ...); }(parent.template storage<std::remove_const_t<Exclude>>()..., parent.template storage<std::remove_const_t<Get>>()..., this);
- return elem;
- }
- /*! @copydoc view */
- template<typename... Get, typename... Exclude>
- [[nodiscard]] basic_view<get_t<const basic_reactive_mixin, typename basic_registry_type::template storage_for_type<Get>...>, exclude_t<typename basic_registry_type::template storage_for_type<Exclude>...>>
- view(exclude_t<Exclude...> = exclude_t{}) {
- std::conditional_t<((std::is_const_v<Get> && ...) && (std::is_const_v<Exclude> && ...)), const owner_type, owner_type> &parent = owner_or_assert();
- return {*this, parent.template storage<std::remove_const_t<Get>>()..., parent.template storage<std::remove_const_t<Exclude>>()...};
- }
- /*! @brief Releases all connections to the underlying registry, if any. */
- void reset() {
- for(auto &&curr: conn) {
- curr.release();
- }
- conn.clear();
- }
- private:
- basic_registry_type *owner;
- container_type conn;
- };
- } // namespace entt
- #endif
- // #include "sparse_set.hpp"
- // #include "storage.hpp"
- // #include "view.hpp"
- namespace entt {
- /*! @cond TURN_OFF_DOXYGEN */
- namespace internal {
- template<typename It>
- class registry_storage_iterator final {
- template<typename Other>
- friend class registry_storage_iterator;
- using mapped_type = std::remove_reference_t<decltype(std::declval<It>()->second)>;
- public:
- using value_type = std::pair<id_type, constness_as_t<typename mapped_type::element_type, mapped_type> &>;
- using pointer = input_iterator_pointer<value_type>;
- using reference = value_type;
- using difference_type = std::ptrdiff_t;
- using iterator_category = std::input_iterator_tag;
- using iterator_concept = std::random_access_iterator_tag;
- constexpr registry_storage_iterator() noexcept
- : it{} {}
- constexpr registry_storage_iterator(It iter) noexcept
- : it{iter} {}
- template<typename Other, typename = std::enable_if_t<!std::is_same_v<It, Other> && std::is_constructible_v<It, Other>>>
- constexpr registry_storage_iterator(const registry_storage_iterator<Other> &other) noexcept
- : registry_storage_iterator{other.it} {}
- constexpr registry_storage_iterator &operator++() noexcept {
- return ++it, *this;
- }
- constexpr registry_storage_iterator operator++(int) noexcept {
- const registry_storage_iterator orig = *this;
- return ++(*this), orig;
- }
- constexpr registry_storage_iterator &operator--() noexcept {
- return --it, *this;
- }
- constexpr registry_storage_iterator operator--(int) noexcept {
- const registry_storage_iterator orig = *this;
- return operator--(), orig;
- }
- constexpr registry_storage_iterator &operator+=(const difference_type value) noexcept {
- it += value;
- return *this;
- }
- constexpr registry_storage_iterator operator+(const difference_type value) const noexcept {
- registry_storage_iterator copy = *this;
- return (copy += value);
- }
- constexpr registry_storage_iterator &operator-=(const difference_type value) noexcept {
- return (*this += -value);
- }
- constexpr registry_storage_iterator operator-(const difference_type value) const noexcept {
- return (*this + -value);
- }
- [[nodiscard]] constexpr reference operator[](const difference_type value) const noexcept {
- return {it[value].first, *it[value].second};
- }
- [[nodiscard]] constexpr reference operator*() const noexcept {
- return operator[](0);
- }
- [[nodiscard]] constexpr pointer operator->() const noexcept {
- return operator*();
- }
- template<typename Lhs, typename Rhs>
- friend constexpr std::ptrdiff_t operator-(const registry_storage_iterator<Lhs> &, const registry_storage_iterator<Rhs> &) noexcept;
- template<typename Lhs, typename Rhs>
- friend constexpr bool operator==(const registry_storage_iterator<Lhs> &, const registry_storage_iterator<Rhs> &) noexcept;
- template<typename Lhs, typename Rhs>
- friend constexpr bool operator<(const registry_storage_iterator<Lhs> &, const registry_storage_iterator<Rhs> &) noexcept;
- private:
- It it;
- };
- template<typename Lhs, typename Rhs>
- [[nodiscard]] constexpr std::ptrdiff_t operator-(const registry_storage_iterator<Lhs> &lhs, const registry_storage_iterator<Rhs> &rhs) noexcept {
- return lhs.it - rhs.it;
- }
- template<typename Lhs, typename Rhs>
- [[nodiscard]] constexpr bool operator==(const registry_storage_iterator<Lhs> &lhs, const registry_storage_iterator<Rhs> &rhs) noexcept {
- return lhs.it == rhs.it;
- }
- template<typename Lhs, typename Rhs>
- [[nodiscard]] constexpr bool operator!=(const registry_storage_iterator<Lhs> &lhs, const registry_storage_iterator<Rhs> &rhs) noexcept {
- return !(lhs == rhs);
- }
- template<typename Lhs, typename Rhs>
- [[nodiscard]] constexpr bool operator<(const registry_storage_iterator<Lhs> &lhs, const registry_storage_iterator<Rhs> &rhs) noexcept {
- return lhs.it < rhs.it;
- }
- template<typename Lhs, typename Rhs>
- [[nodiscard]] constexpr bool operator>(const registry_storage_iterator<Lhs> &lhs, const registry_storage_iterator<Rhs> &rhs) noexcept {
- return rhs < lhs;
- }
- template<typename Lhs, typename Rhs>
- [[nodiscard]] constexpr bool operator<=(const registry_storage_iterator<Lhs> &lhs, const registry_storage_iterator<Rhs> &rhs) noexcept {
- return !(lhs > rhs);
- }
- template<typename Lhs, typename Rhs>
- [[nodiscard]] constexpr bool operator>=(const registry_storage_iterator<Lhs> &lhs, const registry_storage_iterator<Rhs> &rhs) noexcept {
- return !(lhs < rhs);
- }
- template<typename Allocator>
- class registry_context {
- using alloc_traits = std::allocator_traits<Allocator>;
- using allocator_type = typename alloc_traits::template rebind_alloc<std::pair<const id_type, basic_any<0u>>>;
- public:
- explicit registry_context(const allocator_type &allocator)
- : ctx{allocator} {}
- void clear() noexcept {
- ctx.clear();
- }
- template<typename Type, typename... Args>
- Type &emplace_as(const id_type id, Args &&...args) {
- return any_cast<Type &>(ctx.try_emplace(id, std::in_place_type<Type>, std::forward<Args>(args)...).first->second);
- }
- template<typename Type, typename... Args>
- Type &emplace(Args &&...args) {
- return emplace_as<Type>(type_id<Type>().hash(), std::forward<Args>(args)...);
- }
- template<typename Type>
- Type &insert_or_assign(const id_type id, Type &&value) {
- return any_cast<std::remove_const_t<std::remove_reference_t<Type>> &>(ctx.insert_or_assign(id, std::forward<Type>(value)).first->second);
- }
- template<typename Type>
- Type &insert_or_assign(Type &&value) {
- return insert_or_assign(type_id<Type>().hash(), std::forward<Type>(value));
- }
- template<typename Type>
- bool erase(const id_type id = type_id<Type>().hash()) {
- const auto it = ctx.find(id);
- return it != ctx.end() && it->second.info() == type_id<Type>() ? (ctx.erase(it), true) : false;
- }
- template<typename Type>
- [[nodiscard]] const Type &get(const id_type id = type_id<Type>().hash()) const {
- return any_cast<const Type &>(ctx.at(id));
- }
- template<typename Type>
- [[nodiscard]] Type &get(const id_type id = type_id<Type>().hash()) {
- return any_cast<Type &>(ctx.at(id));
- }
- template<typename Type>
- [[nodiscard]] const Type *find(const id_type id = type_id<Type>().hash()) const {
- const auto it = ctx.find(id);
- return it != ctx.cend() ? any_cast<const Type>(&it->second) : nullptr;
- }
- template<typename Type>
- [[nodiscard]] Type *find(const id_type id = type_id<Type>().hash()) {
- const auto it = ctx.find(id);
- return it != ctx.end() ? any_cast<Type>(&it->second) : nullptr;
- }
- template<typename Type>
- [[nodiscard]] bool contains(const id_type id = type_id<Type>().hash()) const {
- const auto it = ctx.find(id);
- return it != ctx.cend() && it->second.info() == type_id<Type>();
- }
- private:
- dense_map<id_type, basic_any<0u>, identity, std::equal_to<>, allocator_type> ctx;
- };
- } // namespace internal
- /*! @endcond */
- /**
- * @brief Fast and reliable entity-component system.
- * @tparam Entity A valid entity type.
- * @tparam Allocator Type of allocator used to manage memory and elements.
- */
- template<typename Entity, typename Allocator>
- class basic_registry {
- using base_type = basic_sparse_set<Entity, Allocator>;
- using alloc_traits = std::allocator_traits<Allocator>;
- static_assert(std::is_same_v<typename alloc_traits::value_type, Entity>, "Invalid value type");
- // std::shared_ptr because of its type erased allocator which is useful here
- using pool_container_type = dense_map<id_type, std::shared_ptr<base_type>, identity, std::equal_to<>, typename alloc_traits::template rebind_alloc<std::pair<const id_type, std::shared_ptr<base_type>>>>;
- using group_container_type = dense_map<id_type, std::shared_ptr<internal::group_descriptor>, identity, std::equal_to<>, typename alloc_traits::template rebind_alloc<std::pair<const id_type, std::shared_ptr<internal::group_descriptor>>>>;
- using traits_type = entt_traits<Entity>;
- template<typename Type>
- [[nodiscard]] auto &assure([[maybe_unused]] const id_type id = type_hash<Type>::value()) {
- static_assert(std::is_same_v<Type, std::decay_t<Type>>, "Non-decayed types not allowed");
- if constexpr(std::is_same_v<Type, entity_type>) {
- ENTT_ASSERT(id == type_hash<Type>::value(), "User entity storage not allowed");
- return entities;
- } else {
- using storage_type = storage_for_type<Type>;
- if(auto it = pools.find(id); it != pools.cend()) {
- ENTT_ASSERT(it->second->info() == type_id<Type>(), "Unexpected type");
- return static_cast<storage_type &>(*it->second);
- }
- using alloc_type = typename storage_type::allocator_type;
- typename pool_container_type::mapped_type cpool{};
- if constexpr(std::is_void_v<Type> && !std::is_constructible_v<alloc_type, allocator_type>) {
- // std::allocator<void> has no cross constructors (waiting for C++20)
- cpool = std::allocate_shared<storage_type>(get_allocator(), alloc_type{});
- } else {
- cpool = std::allocate_shared<storage_type>(get_allocator(), get_allocator());
- }
- pools.emplace(id, cpool);
- cpool->bind(*this);
- return static_cast<storage_type &>(*cpool);
- }
- }
- template<typename Type>
- [[nodiscard]] const auto *assure([[maybe_unused]] const id_type id = type_hash<Type>::value()) const {
- static_assert(std::is_same_v<Type, std::decay_t<Type>>, "Non-decayed types not allowed");
- if constexpr(std::is_same_v<Type, entity_type>) {
- ENTT_ASSERT(id == type_hash<Type>::value(), "User entity storage not allowed");
- return &entities;
- } else {
- if(const auto it = pools.find(id); it != pools.cend()) {
- ENTT_ASSERT(it->second->info() == type_id<Type>(), "Unexpected type");
- return static_cast<const storage_for_type<Type> *>(it->second.get());
- }
- return static_cast<const storage_for_type<Type> *>(nullptr);
- }
- }
- void rebind() {
- entities.bind(*this);
- for(auto &&curr: pools) {
- curr.second->bind(*this);
- }
- }
- public:
- /*! @brief Allocator type. */
- using allocator_type = Allocator;
- /*! @brief Underlying entity identifier. */
- using entity_type = typename traits_type::value_type;
- /*! @brief Underlying version type. */
- using version_type = typename traits_type::version_type;
- /*! @brief Unsigned integer type. */
- using size_type = std::size_t;
- /*! @brief Common type among all storage types. */
- using common_type = base_type;
- /*! @brief Context type. */
- using context = internal::registry_context<allocator_type>;
- /*! @brief Iterable registry type. */
- using iterable = iterable_adaptor<internal::registry_storage_iterator<typename pool_container_type::iterator>>;
- /*! @brief Constant iterable registry type. */
- using const_iterable = iterable_adaptor<internal::registry_storage_iterator<typename pool_container_type::const_iterator>>;
- /**
- * @copybrief storage_for
- * @tparam Type Storage value type, eventually const.
- */
- template<typename Type>
- using storage_for_type = typename storage_for<Type, Entity, typename alloc_traits::template rebind_alloc<std::remove_const_t<Type>>>::type;
- /*! @brief Default constructor. */
- basic_registry()
- : basic_registry{allocator_type{}} {}
- /**
- * @brief Constructs an empty registry with a given allocator.
- * @param allocator The allocator to use.
- */
- explicit basic_registry(const allocator_type &allocator)
- : basic_registry{0u, allocator} {}
- /**
- * @brief Allocates enough memory upon construction to store `count` pools.
- * @param count The number of pools to allocate memory for.
- * @param allocator The allocator to use.
- */
- basic_registry(const size_type count, const allocator_type &allocator = allocator_type{})
- : vars{allocator},
- pools{allocator},
- groups{allocator},
- entities{allocator} {
- pools.reserve(count);
- rebind();
- }
- /*! @brief Default copy constructor, deleted on purpose. */
- basic_registry(const basic_registry &) = delete;
- /**
- * @brief Move constructor.
- * @param other The instance to move from.
- */
- basic_registry(basic_registry &&other) noexcept
- : vars{std::move(other.vars)},
- pools{std::move(other.pools)},
- groups{std::move(other.groups)},
- entities{std::move(other.entities)} {
- rebind();
- }
- /*! @brief Default destructor. */
- ~basic_registry() = default;
- /**
- * @brief Default copy assignment operator, deleted on purpose.
- * @return This mixin.
- */
- basic_registry &operator=(const basic_registry &) = delete;
- /**
- * @brief Move assignment operator.
- * @param other The instance to move from.
- * @return This registry.
- */
- basic_registry &operator=(basic_registry &&other) noexcept {
- swap(other);
- return *this;
- }
- /**
- * @brief Exchanges the contents with those of a given registry.
- * @param other Registry to exchange the content with.
- */
- void swap(basic_registry &other) noexcept {
- using std::swap;
- swap(vars, other.vars);
- swap(pools, other.pools);
- swap(groups, other.groups);
- swap(entities, other.entities);
- rebind();
- other.rebind();
- }
- /**
- * @brief Returns the associated allocator.
- * @return The associated allocator.
- */
- [[nodiscard]] constexpr allocator_type get_allocator() const noexcept {
- return entities.get_allocator();
- }
- /**
- * @brief Returns an iterable object to use to _visit_ a registry.
- *
- * The iterable object returns a pair that contains the name and a reference
- * to the current storage.
- *
- * @return An iterable object to use to _visit_ the registry.
- */
- [[nodiscard]] iterable storage() noexcept {
- return iterable{pools.begin(), pools.end()};
- }
- /*! @copydoc storage */
- [[nodiscard]] const_iterable storage() const noexcept {
- return const_iterable{pools.cbegin(), pools.cend()};
- }
- /**
- * @brief Finds the storage associated with a given name, if any.
- * @param id Name used to map the storage within the registry.
- * @return A pointer to the storage if it exists, a null pointer otherwise.
- */
- [[nodiscard]] common_type *storage(const id_type id) {
- return const_cast<common_type *>(std::as_const(*this).storage(id));
- }
- /**
- * @brief Finds the storage associated with a given name, if any.
- * @param id Name used to map the storage within the registry.
- * @return A pointer to the storage if it exists, a null pointer otherwise.
- */
- [[nodiscard]] const common_type *storage(const id_type id) const {
- const auto it = pools.find(id);
- return it == pools.cend() ? nullptr : it->second.get();
- }
- /**
- * @brief Returns the storage for a given element type.
- * @tparam Type Type of element of which to return the storage.
- * @param id Optional name used to map the storage within the registry.
- * @return The storage for the given element type.
- */
- template<typename Type>
- storage_for_type<Type> &storage(const id_type id = type_hash<Type>::value()) {
- return assure<std::remove_const_t<Type>>(id);
- }
- /**
- * @brief Returns the storage for a given element type, if any.
- * @tparam Type Type of element of which to return the storage.
- * @param id Optional name used to map the storage within the registry.
- * @return The storage for the given element type.
- */
- template<typename Type>
- [[nodiscard]] const storage_for_type<Type> *storage(const id_type id = type_hash<Type>::value()) const {
- return assure<std::remove_const_t<Type>>(id);
- }
- /**
- * @brief Discards the storage associated with a given name, if any.
- * @param id Name used to map the storage within the registry.
- * @return True in case of success, false otherwise.
- */
- bool reset(const id_type id) {
- ENTT_ASSERT(id != type_hash<entity_type>::value(), "Cannot reset entity storage");
- return !(pools.erase(id) == 0u);
- }
- /**
- * @brief Checks if an identifier refers to a valid entity.
- * @param entt An identifier, either valid or not.
- * @return True if the identifier is valid, false otherwise.
- */
- [[nodiscard]] bool valid(const entity_type entt) const {
- return static_cast<size_type>(entities.find(entt).index()) < entities.free_list();
- }
- /**
- * @brief Returns the actual version for an identifier.
- * @param entt A valid identifier.
- * @return The version for the given identifier if valid, the tombstone
- * version otherwise.
- */
- [[nodiscard]] version_type current(const entity_type entt) const {
- return entities.current(entt);
- }
- /**
- * @brief Creates a new entity or recycles a destroyed one.
- * @return A valid identifier.
- */
- [[nodiscard]] entity_type create() {
- return entities.generate();
- }
- /**
- * @copybrief create
- *
- * If the requested entity isn't in use, the suggested identifier is used.
- * Otherwise, a new identifier is generated.
- *
- * @param hint Required identifier.
- * @return A valid identifier.
- */
- [[nodiscard]] entity_type create(const entity_type hint) {
- return entities.generate(hint);
- }
- /**
- * @brief Assigns each element in a range an identifier.
- *
- * @sa create
- *
- * @tparam It Type of forward iterator.
- * @param first An iterator to the first element of the range to generate.
- * @param last An iterator past the last element of the range to generate.
- */
- template<typename It>
- void create(It first, It last) {
- entities.generate(std::move(first), std::move(last));
- }
- /**
- * @brief Destroys an entity and releases its identifier.
- *
- * @warning
- * Adding or removing elements to an entity that is being destroyed can
- * result in undefined behavior.
- *
- * @param entt A valid identifier.
- * @return The version of the recycled entity.
- */
- version_type destroy(const entity_type entt) {
- for(size_type pos = pools.size(); pos != 0u; --pos) {
- pools.begin()[static_cast<typename pool_container_type::difference_type>(pos - 1u)].second->remove(entt);
- }
- entities.erase(entt);
- return entities.current(entt);
- }
- /**
- * @brief Destroys an entity and releases its identifier.
- *
- * The suggested version or the valid version closest to the suggested one
- * is used instead of the implicitly generated version.
- *
- * @sa destroy
- *
- * @param entt A valid identifier.
- * @param version A desired version upon destruction.
- * @return The version actually assigned to the entity.
- */
- version_type destroy(const entity_type entt, const version_type version) {
- destroy(entt);
- const auto elem = traits_type::construct(traits_type::to_entity(entt), version);
- return entities.bump((elem == tombstone) ? traits_type::next(elem) : elem);
- }
- /**
- * @brief Destroys all entities in a range and releases their identifiers.
- *
- * @sa destroy
- *
- * @tparam It Type of input iterator.
- * @param first An iterator to the first element of the range of entities.
- * @param last An iterator past the last element of the range of entities.
- */
- template<typename It>
- void destroy(It first, It last) {
- const auto to = entities.sort_as(first, last);
- const auto from = entities.cend() - static_cast<typename common_type::difference_type>(entities.free_list());
- for(auto &&curr: pools) {
- curr.second->remove(from, to);
- }
- entities.erase(from, to);
- }
- /**
- * @brief Assigns the given element to an entity.
- *
- * The element must have a proper constructor or be of aggregate type.
- *
- * @warning
- * Attempting to assign an element to an entity that already owns it results
- * in undefined behavior.
- *
- * @tparam Type Type of element to create.
- * @tparam Args Types of arguments to use to construct the element.
- * @param entt A valid identifier.
- * @param args Parameters to use to initialize the element.
- * @return A reference to the newly created element.
- */
- template<typename Type, typename... Args>
- decltype(auto) emplace(const entity_type entt, Args &&...args) {
- ENTT_ASSERT(valid(entt), "Invalid entity");
- return assure<Type>().emplace(entt, std::forward<Args>(args)...);
- }
- /**
- * @brief Assigns each entity in a range the given element.
- *
- * @sa emplace
- *
- * @tparam Type Type of element to create.
- * @tparam It Type of input iterator.
- * @param first An iterator to the first element of the range of entities.
- * @param last An iterator past the last element of the range of entities.
- */
- template<typename Type, typename It>
- void insert(It first, It last) {
- ENTT_ASSERT(std::all_of(first, last, [this](const auto entt) { return valid(entt); }), "Invalid entity");
- assure<Type>().insert(std::move(first), std::move(last));
- }
- /**
- * @brief Assigns each entity in a range the given element.
- *
- * @sa emplace
- *
- * @tparam Type Type of element to create.
- * @tparam It Type of input iterator.
- * @param first An iterator to the first element of the range of entities.
- * @param last An iterator past the last element of the range of entities.
- * @param value An instance of the element to assign.
- */
- template<typename Type, typename It>
- void insert(It first, It last, const Type &value) {
- ENTT_ASSERT(std::all_of(first, last, [this](const auto entt) { return valid(entt); }), "Invalid entity");
- assure<Type>().insert(std::move(first), std::move(last), value);
- }
- /**
- * @brief Assigns each entity in a range the given elements.
- *
- * @sa emplace
- *
- * @tparam Type Type of element to create.
- * @tparam EIt Type of input iterator.
- * @tparam CIt Type of input iterator.
- * @param first An iterator to the first element of the range of entities.
- * @param last An iterator past the last element of the range of entities.
- * @param from An iterator to the first element of the range of elements.
- */
- template<typename Type, typename EIt, typename CIt, typename = std::enable_if_t<std::is_same_v<typename std::iterator_traits<CIt>::value_type, Type>>>
- void insert(EIt first, EIt last, CIt from) {
- ENTT_ASSERT(std::all_of(first, last, [this](const auto entt) { return valid(entt); }), "Invalid entity");
- assure<Type>().insert(first, last, from);
- }
- /**
- * @brief Assigns or replaces the given element for an entity.
- *
- * @sa emplace
- * @sa replace
- *
- * @tparam Type Type of element to assign or replace.
- * @tparam Args Types of arguments to use to construct the element.
- * @param entt A valid identifier.
- * @param args Parameters to use to initialize the element.
- * @return A reference to the newly created element.
- */
- template<typename Type, typename... Args>
- decltype(auto) emplace_or_replace(const entity_type entt, Args &&...args) {
- auto &cpool = assure<Type>();
- ENTT_ASSERT(valid(entt), "Invalid entity");
- return cpool.contains(entt) ? cpool.patch(entt, [&args...](auto &...curr) { ((curr = Type{std::forward<Args>(args)...}), ...); }) : cpool.emplace(entt, std::forward<Args>(args)...);
- }
- /**
- * @brief Patches the given element for an entity.
- *
- * The signature of the function should be equivalent to the following:
- *
- * @code{.cpp}
- * void(Type &);
- * @endcode
- *
- * @warning
- * Attempting to patch an element of an entity that doesn't own it results
- * in undefined behavior.
- *
- * @tparam Type Type of element to patch.
- * @tparam Func Types of the function objects to invoke.
- * @param entt A valid identifier.
- * @param func Valid function objects.
- * @return A reference to the patched element.
- */
- template<typename Type, typename... Func>
- decltype(auto) patch(const entity_type entt, Func &&...func) {
- return assure<Type>().patch(entt, std::forward<Func>(func)...);
- }
- /**
- * @brief Replaces the given element for an entity.
- *
- * The element must have a proper constructor or be of aggregate type.
- *
- * @warning
- * Attempting to replace an element of an entity that doesn't own it results
- * in undefined behavior.
- *
- * @tparam Type Type of element to replace.
- * @tparam Args Types of arguments to use to construct the element.
- * @param entt A valid identifier.
- * @param args Parameters to use to initialize the element.
- * @return A reference to the element being replaced.
- */
- template<typename Type, typename... Args>
- decltype(auto) replace(const entity_type entt, Args &&...args) {
- return patch<Type>(entt, [&args...](auto &...curr) { ((curr = Type{std::forward<Args>(args)...}), ...); });
- }
- /**
- * @brief Removes the given elements from an entity.
- * @tparam Type Type of element to remove.
- * @tparam Other Other types of elements to remove.
- * @param entt A valid identifier.
- * @return The number of elements actually removed.
- */
- template<typename Type, typename... Other>
- size_type remove(const entity_type entt) {
- return (assure<Type>().remove(entt) + ... + assure<Other>().remove(entt));
- }
- /**
- * @brief Removes the given elements from all the entities in a range.
- *
- * @sa remove
- *
- * @tparam Type Type of element to remove.
- * @tparam Other Other types of elements to remove.
- * @tparam It Type of input iterator.
- * @param first An iterator to the first element of the range of entities.
- * @param last An iterator past the last element of the range of entities.
- * @return The number of elements actually removed.
- */
- template<typename Type, typename... Other, typename It>
- size_type remove(It first, It last) {
- size_type count{};
- if constexpr(std::is_same_v<It, typename common_type::iterator>) {
- std::array cpools{static_cast<common_type *>(&assure<Type>()), static_cast<common_type *>(&assure<Other>())...};
- for(auto from = cpools.begin(), to = cpools.end(); from != to; ++from) {
- if constexpr(sizeof...(Other) != 0u) {
- if((*from)->data() == first.data()) {
- std::swap((*from), cpools.back());
- }
- }
- count += (*from)->remove(first, last);
- }
- } else {
- for(auto cpools = std::forward_as_tuple(assure<Type>(), assure<Other>()...); first != last; ++first) {
- count += std::apply([entt = *first](auto &...curr) { return (curr.remove(entt) + ... + 0u); }, cpools);
- }
- }
- return count;
- }
- /**
- * @brief Erases the given elements from an entity.
- *
- * @warning
- * Attempting to erase an element from an entity that doesn't own it results
- * in undefined behavior.
- *
- * @tparam Type Types of elements to erase.
- * @tparam Other Other types of elements to erase.
- * @param entt A valid identifier.
- */
- template<typename Type, typename... Other>
- void erase(const entity_type entt) {
- (assure<Type>().erase(entt), (assure<Other>().erase(entt), ...));
- }
- /**
- * @brief Erases the given elements from all the entities in a range.
- *
- * @sa erase
- *
- * @tparam Type Types of elements to erase.
- * @tparam Other Other types of elements to erase.
- * @tparam It Type of input iterator.
- * @param first An iterator to the first element of the range of entities.
- * @param last An iterator past the last element of the range of entities.
- */
- template<typename Type, typename... Other, typename It>
- void erase(It first, It last) {
- if constexpr(std::is_same_v<It, typename common_type::iterator>) {
- std::array cpools{static_cast<common_type *>(&assure<Type>()), static_cast<common_type *>(&assure<Other>())...};
- for(auto from = cpools.begin(), to = cpools.end(); from != to; ++from) {
- if constexpr(sizeof...(Other) != 0u) {
- if((*from)->data() == first.data()) {
- std::swap(*from, cpools.back());
- }
- }
- (*from)->erase(first, last);
- }
- } else {
- for(auto cpools = std::forward_as_tuple(assure<Type>(), assure<Other>()...); first != last; ++first) {
- std::apply([entt = *first](auto &...curr) { (curr.erase(entt), ...); }, cpools);
- }
- }
- }
- /**
- * @brief Erases elements satisfying specific criteria from an entity.
- *
- * The function type is equivalent to:
- *
- * @code{.cpp}
- * void(const id_type, typename basic_registry<Entity>::common_type &);
- * @endcode
- *
- * Only storage where the entity exists are passed to the function.
- *
- * @tparam Func Type of the function object to invoke.
- * @param entt A valid identifier.
- * @param func A valid function object.
- */
- template<typename Func>
- void erase_if(const entity_type entt, Func func) {
- for(auto [id, cpool]: storage()) {
- if(cpool.contains(entt) && func(id, std::as_const(cpool))) {
- cpool.erase(entt);
- }
- }
- }
- /**
- * @brief Removes all tombstones from a registry or only the pools for the
- * given elements.
- * @tparam Type Types of elements for which to clear all tombstones.
- */
- template<typename... Type>
- void compact() {
- if constexpr(sizeof...(Type) == 0u) {
- for(auto &&curr: pools) {
- curr.second->compact();
- }
- } else {
- (assure<Type>().compact(), ...);
- }
- }
- /**
- * @brief Check if an entity is part of all the given storage.
- * @tparam Type Type of storage to check for.
- * @param entt A valid identifier.
- * @return True if the entity is part of all the storage, false otherwise.
- */
- template<typename... Type>
- [[nodiscard]] bool all_of([[maybe_unused]] const entity_type entt) const {
- if constexpr(sizeof...(Type) == 1u) {
- auto *cpool = assure<std::remove_const_t<Type>...>();
- return cpool && cpool->contains(entt);
- } else {
- return (all_of<Type>(entt) && ...);
- }
- }
- /**
- * @brief Check if an entity is part of at least one given storage.
- * @tparam Type Type of storage to check for.
- * @param entt A valid identifier.
- * @return True if the entity is part of at least one storage, false
- * otherwise.
- */
- template<typename... Type>
- [[nodiscard]] bool any_of([[maybe_unused]] const entity_type entt) const {
- return (all_of<Type>(entt) || ...);
- }
- /**
- * @brief Returns references to the given elements for an entity.
- *
- * @warning
- * Attempting to get an element from an entity that doesn't own it results
- * in undefined behavior.
- *
- * @tparam Type Types of elements to get.
- * @param entt A valid identifier.
- * @return References to the elements owned by the entity.
- */
- template<typename... Type>
- [[nodiscard]] decltype(auto) get([[maybe_unused]] const entity_type entt) const {
- if constexpr(sizeof...(Type) == 1u) {
- return (assure<std::remove_const_t<Type>>()->get(entt), ...);
- } else {
- return std::forward_as_tuple(get<Type>(entt)...);
- }
- }
- /*! @copydoc get */
- template<typename... Type>
- [[nodiscard]] decltype(auto) get([[maybe_unused]] const entity_type entt) {
- if constexpr(sizeof...(Type) == 1u) {
- return (static_cast<storage_for_type<Type> &>(assure<std::remove_const_t<Type>>()).get(entt), ...);
- } else {
- return std::forward_as_tuple(get<Type>(entt)...);
- }
- }
- /**
- * @brief Returns a reference to the given element for an entity.
- *
- * In case the entity doesn't own the element, the parameters provided are
- * used to construct it.
- *
- * @sa get
- * @sa emplace
- *
- * @tparam Type Type of element to get.
- * @tparam Args Types of arguments to use to construct the element.
- * @param entt A valid identifier.
- * @param args Parameters to use to initialize the element.
- * @return Reference to the element owned by the entity.
- */
- template<typename Type, typename... Args>
- [[nodiscard]] decltype(auto) get_or_emplace(const entity_type entt, Args &&...args) {
- auto &cpool = assure<Type>();
- ENTT_ASSERT(valid(entt), "Invalid entity");
- return cpool.contains(entt) ? cpool.get(entt) : cpool.emplace(entt, std::forward<Args>(args)...);
- }
- /**
- * @brief Returns pointers to the given elements for an entity.
- *
- * @note
- * The registry retains ownership of the pointed-to elements.
- *
- * @tparam Type Types of elements to get.
- * @param entt A valid identifier.
- * @return Pointers to the elements owned by the entity.
- */
- template<typename... Type>
- [[nodiscard]] auto try_get([[maybe_unused]] const entity_type entt) const {
- if constexpr(sizeof...(Type) == 1u) {
- const auto *cpool = assure<std::remove_const_t<Type>...>();
- return (cpool && cpool->contains(entt)) ? std::addressof(cpool->get(entt)) : nullptr;
- } else {
- return std::make_tuple(try_get<Type>(entt)...);
- }
- }
- /*! @copydoc try_get */
- template<typename... Type>
- [[nodiscard]] auto try_get([[maybe_unused]] const entity_type entt) {
- if constexpr(sizeof...(Type) == 1u) {
- return (const_cast<Type *>(std::as_const(*this).template try_get<Type>(entt)), ...);
- } else {
- return std::make_tuple(try_get<Type>(entt)...);
- }
- }
- /**
- * @brief Clears a whole registry or the pools for the given elements.
- * @tparam Type Types of elements to remove from their entities.
- */
- template<typename... Type>
- void clear() {
- if constexpr(sizeof...(Type) == 0u) {
- for(size_type pos = pools.size(); pos; --pos) {
- pools.begin()[static_cast<typename pool_container_type::difference_type>(pos - 1u)].second->clear();
- }
- const auto elem = entities.each();
- entities.erase(elem.begin().base(), elem.end().base());
- } else {
- (assure<Type>().clear(), ...);
- }
- }
- /**
- * @brief Checks if an entity has elements assigned.
- * @param entt A valid identifier.
- * @return True if the entity has no elements assigned, false otherwise.
- */
- [[nodiscard]] bool orphan(const entity_type entt) const {
- return std::none_of(pools.cbegin(), pools.cend(), [entt](auto &&curr) { return curr.second->contains(entt); });
- }
- /**
- * @brief Returns a sink object for the given element.
- *
- * Use this function to receive notifications whenever a new instance of the
- * given element is created and assigned to an entity.<br/>
- * The function type for a listener is equivalent to:
- *
- * @code{.cpp}
- * void(basic_registry<Entity> &, Entity);
- * @endcode
- *
- * Listeners are invoked **after** assigning the element to the entity.
- *
- * @sa sink
- *
- * @tparam Type Type of element of which to get the sink.
- * @param id Optional name used to map the storage within the registry.
- * @return A temporary sink object.
- */
- template<typename Type>
- [[nodiscard]] auto on_construct(const id_type id = type_hash<Type>::value()) {
- return assure<Type>(id).on_construct();
- }
- /**
- * @brief Returns a sink object for the given element.
- *
- * Use this function to receive notifications whenever an instance of the
- * given element is explicitly updated.<br/>
- * The function type for a listener is equivalent to:
- *
- * @code{.cpp}
- * void(basic_registry<Entity> &, Entity);
- * @endcode
- *
- * Listeners are invoked **after** updating the element.
- *
- * @sa sink
- *
- * @tparam Type Type of element of which to get the sink.
- * @param id Optional name used to map the storage within the registry.
- * @return A temporary sink object.
- */
- template<typename Type>
- [[nodiscard]] auto on_update(const id_type id = type_hash<Type>::value()) {
- return assure<Type>(id).on_update();
- }
- /**
- * @brief Returns a sink object for the given element.
- *
- * Use this function to receive notifications whenever an instance of the
- * given element is removed from an entity and thus destroyed.<br/>
- * The function type for a listener is equivalent to:
- *
- * @code{.cpp}
- * void(basic_registry<Entity> &, Entity);
- * @endcode
- *
- * Listeners are invoked **before** removing the element from the entity.
- *
- * @sa sink
- *
- * @tparam Type Type of element of which to get the sink.
- * @param id Optional name used to map the storage within the registry.
- * @return A temporary sink object.
- */
- template<typename Type>
- [[nodiscard]] auto on_destroy(const id_type id = type_hash<Type>::value()) {
- return assure<Type>(id).on_destroy();
- }
- /**
- * @brief Returns a view for the given elements.
- * @tparam Type Type of element used to construct the view.
- * @tparam Other Other types of elements used to construct the view.
- * @tparam Exclude Types of elements used to filter the view.
- * @return A newly created view.
- */
- template<typename Type, typename... Other, typename... Exclude>
- [[nodiscard]] basic_view<get_t<storage_for_type<const Type>, storage_for_type<const Other>...>, exclude_t<storage_for_type<const Exclude>...>>
- view(exclude_t<Exclude...> = exclude_t{}) const {
- basic_view<get_t<storage_for_type<const Type>, storage_for_type<const Other>...>, exclude_t<storage_for_type<const Exclude>...>> elem{};
- [&elem](const auto *...curr) { ((curr ? elem.storage(*curr) : void()), ...); }(assure<std::remove_const_t<Exclude>>()..., assure<std::remove_const_t<Other>>()..., assure<std::remove_const_t<Type>>());
- return elem;
- }
- /*! @copydoc view */
- template<typename Type, typename... Other, typename... Exclude>
- [[nodiscard]] basic_view<get_t<storage_for_type<Type>, storage_for_type<Other>...>, exclude_t<storage_for_type<Exclude>...>>
- view(exclude_t<Exclude...> = exclude_t{}) {
- return {assure<std::remove_const_t<Type>>(), assure<std::remove_const_t<Other>>()..., assure<std::remove_const_t<Exclude>>()...};
- }
- /**
- * @brief Returns a group for the given elements.
- * @tparam Owned Types of storage _owned_ by the group.
- * @tparam Get Types of storage _observed_ by the group, if any.
- * @tparam Exclude Types of storage used to filter the group, if any.
- * @return A newly created group.
- */
- template<typename... Owned, typename... Get, typename... Exclude>
- basic_group<owned_t<storage_for_type<Owned>...>, get_t<storage_for_type<Get>...>, exclude_t<storage_for_type<Exclude>...>>
- group(get_t<Get...> = get_t{}, exclude_t<Exclude...> = exclude_t{}) {
- using group_type = basic_group<owned_t<storage_for_type<Owned>...>, get_t<storage_for_type<Get>...>, exclude_t<storage_for_type<Exclude>...>>;
- using handler_type = typename group_type::handler;
- if(auto it = groups.find(group_type::group_id()); it != groups.cend()) {
- return {*std::static_pointer_cast<handler_type>(it->second)};
- }
- std::shared_ptr<handler_type> handler{};
- if constexpr(sizeof...(Owned) == 0u) {
- handler = std::allocate_shared<handler_type>(get_allocator(), get_allocator(), std::forward_as_tuple(assure<std::remove_const_t<Get>>()...), std::forward_as_tuple(assure<std::remove_const_t<Exclude>>()...));
- } else {
- handler = std::allocate_shared<handler_type>(get_allocator(), std::forward_as_tuple(assure<std::remove_const_t<Owned>>()..., assure<std::remove_const_t<Get>>()...), std::forward_as_tuple(assure<std::remove_const_t<Exclude>>()...));
- ENTT_ASSERT(std::all_of(groups.cbegin(), groups.cend(), [](const auto &data) { return !(data.second->owned(type_id<Owned>().hash()) || ...); }), "Conflicting groups");
- }
- groups.emplace(group_type::group_id(), handler);
- return {*handler};
- }
- /*! @copydoc group */
- template<typename... Owned, typename... Get, typename... Exclude>
- [[nodiscard]] basic_group<owned_t<storage_for_type<const Owned>...>, get_t<storage_for_type<const Get>...>, exclude_t<storage_for_type<const Exclude>...>>
- group_if_exists(get_t<Get...> = get_t{}, exclude_t<Exclude...> = exclude_t{}) const {
- using group_type = basic_group<owned_t<storage_for_type<const Owned>...>, get_t<storage_for_type<const Get>...>, exclude_t<storage_for_type<const Exclude>...>>;
- using handler_type = typename group_type::handler;
- if(auto it = groups.find(group_type::group_id()); it != groups.cend()) {
- return {*std::static_pointer_cast<handler_type>(it->second)};
- }
- return {};
- }
- /**
- * @brief Checks whether the given elements belong to any group.
- * @tparam Type Types of elements in which one is interested.
- * @return True if the pools of the given elements are _free_, false
- * otherwise.
- */
- template<typename... Type>
- [[nodiscard]] bool owned() const {
- return std::any_of(groups.cbegin(), groups.cend(), [](auto &&data) { return (data.second->owned(type_id<Type>().hash()) || ...); });
- }
- /**
- * @brief Sorts the elements of a given element.
- *
- * The comparison function object returns `true` if the first element is
- * _less_ than the second one, `false` otherwise. Its signature is also
- * equivalent to one of the following:
- *
- * @code{.cpp}
- * bool(const Entity, const Entity);
- * bool(const Type &, const Type &);
- * @endcode
- *
- * Moreover, it shall induce a _strict weak ordering_ on the values.<br/>
- * The sort function object offers an `operator()` that accepts:
- *
- * * An iterator to the first element of the range to sort.
- * * An iterator past the last element of the range to sort.
- * * A comparison function object to use to compare the elements.
- *
- * The comparison function object hasn't necessarily the type of the one
- * passed along with the other parameters to this member function.
- *
- * @warning
- * Pools of elements owned by a group cannot be sorted.
- *
- * @tparam Type Type of elements to sort.
- * @tparam Compare Type of comparison function object.
- * @tparam Sort Type of sort function object.
- * @tparam Args Types of arguments to forward to the sort function object.
- * @param compare A valid comparison function object.
- * @param algo A valid sort function object.
- * @param args Arguments to forward to the sort function object, if any.
- */
- template<typename Type, typename Compare, typename Sort = std_sort, typename... Args>
- void sort(Compare compare, Sort algo = Sort{}, Args &&...args) {
- ENTT_ASSERT(!owned<Type>(), "Cannot sort owned storage");
- auto &cpool = assure<Type>();
- if constexpr(std::is_invocable_v<Compare, decltype(cpool.get({})), decltype(cpool.get({}))>) {
- auto comp = [&cpool, compare = std::move(compare)](const auto lhs, const auto rhs) { return compare(std::as_const(cpool.get(lhs)), std::as_const(cpool.get(rhs))); };
- cpool.sort(std::move(comp), std::move(algo), std::forward<Args>(args)...);
- } else {
- cpool.sort(std::move(compare), std::move(algo), std::forward<Args>(args)...);
- }
- }
- /**
- * @brief Sorts two pools of elements in the same way.
- *
- * Entities and elements in `To` which are part of both storage are sorted
- * internally with the order they have in `From`. The others follow in no
- * particular order.
- *
- * @warning
- * Pools of elements owned by a group cannot be sorted.
- *
- * @tparam To Type of elements to sort.
- * @tparam From Type of elements to use to sort.
- */
- template<typename To, typename From>
- void sort() {
- ENTT_ASSERT(!owned<To>(), "Cannot sort owned storage");
- const base_type &cpool = assure<From>();
- assure<To>().sort_as(cpool.begin(), cpool.end());
- }
- /**
- * @brief Returns the context object, that is, a general purpose container.
- * @return The context object, that is, a general purpose container.
- */
- [[nodiscard]] context &ctx() noexcept {
- return vars;
- }
- /*! @copydoc ctx */
- [[nodiscard]] const context &ctx() const noexcept {
- return vars;
- }
- private:
- context vars;
- pool_container_type pools;
- group_container_type groups;
- storage_for_type<entity_type> entities;
- };
- } // namespace entt
- #endif
- // #include "entity/runtime_view.hpp"
- #ifndef ENTT_ENTITY_RUNTIME_VIEW_HPP
- #define ENTT_ENTITY_RUNTIME_VIEW_HPP
- #include <algorithm>
- #include <cstddef>
- #include <iterator>
- #include <utility>
- #include <vector>
- // #include "entity.hpp"
- // #include "fwd.hpp"
- namespace entt {
- /*! @cond TURN_OFF_DOXYGEN */
- namespace internal {
- template<typename Set>
- class runtime_view_iterator final {
- using iterator_type = typename Set::iterator;
- using iterator_traits = std::iterator_traits<iterator_type>;
- [[nodiscard]] bool valid() const {
- return (!tombstone_check || *it != tombstone)
- && std::all_of(++pools->begin(), pools->end(), [entt = *it](const auto *curr) { return curr->contains(entt); })
- && std::none_of(filter->cbegin(), filter->cend(), [entt = *it](const auto *curr) { return curr && curr->contains(entt); });
- }
- public:
- using value_type = typename iterator_traits::value_type;
- using pointer = typename iterator_traits::pointer;
- using reference = typename iterator_traits::reference;
- using difference_type = typename iterator_traits::difference_type;
- using iterator_category = std::bidirectional_iterator_tag;
- constexpr runtime_view_iterator() noexcept
- : pools{},
- filter{},
- it{},
- tombstone_check{} {}
- runtime_view_iterator(const std::vector<Set *> &cpools, iterator_type curr, const std::vector<Set *> &ignore) noexcept
- : pools{&cpools},
- filter{&ignore},
- it{curr},
- tombstone_check{pools->size() == 1u && (*pools)[0u]->policy() == deletion_policy::in_place} {
- if(it != (*pools)[0]->end() && !valid()) {
- ++(*this);
- }
- }
- runtime_view_iterator &operator++() {
- ++it;
- for(const auto last = (*pools)[0]->end(); it != last && !valid(); ++it) {}
- return *this;
- }
- runtime_view_iterator operator++(int) {
- const runtime_view_iterator orig = *this;
- return ++(*this), orig;
- }
- runtime_view_iterator &operator--() {
- --it;
- for(const auto first = (*pools)[0]->begin(); it != first && !valid(); --it) {}
- return *this;
- }
- runtime_view_iterator operator--(int) {
- const runtime_view_iterator orig = *this;
- return operator--(), orig;
- }
- [[nodiscard]] pointer operator->() const noexcept {
- return it.operator->();
- }
- [[nodiscard]] reference operator*() const noexcept {
- return *operator->();
- }
- [[nodiscard]] constexpr bool operator==(const runtime_view_iterator &other) const noexcept {
- return it == other.it;
- }
- [[nodiscard]] constexpr bool operator!=(const runtime_view_iterator &other) const noexcept {
- return !(*this == other);
- }
- private:
- const std::vector<Set *> *pools;
- const std::vector<Set *> *filter;
- iterator_type it;
- bool tombstone_check;
- };
- } // namespace internal
- /*! @endcond */
- /**
- * @brief Generic runtime view.
- *
- * Runtime views iterate over those entities that are at least in the given
- * storage. During initialization, a runtime view looks at the number of
- * entities available for each element and uses the smallest set in order to get
- * a performance boost when iterating.
- *
- * @b Important
- *
- * Iterators aren't invalidated if:
- *
- * * New elements are added to the storage.
- * * The entity currently pointed is modified (for example, elements are added
- * or removed from it).
- * * The entity currently pointed is destroyed.
- *
- * In all other cases, modifying the storage iterated by the view in any way
- * invalidates all the iterators.
- *
- * @tparam Type Common base type.
- * @tparam Allocator Type of allocator used to manage memory and elements.
- */
- template<typename Type, typename Allocator>
- class basic_runtime_view {
- using alloc_traits = std::allocator_traits<Allocator>;
- static_assert(std::is_same_v<typename alloc_traits::value_type, Type *>, "Invalid value type");
- using container_type = std::vector<Type *, Allocator>;
- [[nodiscard]] auto offset() const noexcept {
- ENTT_ASSERT(!pools.empty(), "Invalid view");
- const auto &leading = *pools.front();
- return (leading.policy() == deletion_policy::swap_only) ? leading.free_list() : leading.size();
- }
- public:
- /*! @brief Allocator type. */
- using allocator_type = Allocator;
- /*! @brief Underlying entity identifier. */
- using entity_type = typename Type::entity_type;
- /*! @brief Unsigned integer type. */
- using size_type = std::size_t;
- /*! @brief Signed integer type. */
- using difference_type = std::ptrdiff_t;
- /*! @brief Common type among all storage types. */
- using common_type = Type;
- /*! @brief Bidirectional iterator type. */
- using iterator = internal::runtime_view_iterator<common_type>;
- /*! @brief Default constructor to use to create empty, invalid views. */
- basic_runtime_view() noexcept
- : basic_runtime_view{allocator_type{}} {}
- /**
- * @brief Constructs an empty, invalid view with a given allocator.
- * @param allocator The allocator to use.
- */
- explicit basic_runtime_view(const allocator_type &allocator)
- : pools{allocator},
- filter{allocator} {}
- /*! @brief Default copy constructor. */
- basic_runtime_view(const basic_runtime_view &) = default;
- /**
- * @brief Allocator-extended copy constructor.
- * @param other The instance to copy from.
- * @param allocator The allocator to use.
- */
- basic_runtime_view(const basic_runtime_view &other, const allocator_type &allocator)
- : pools{other.pools, allocator},
- filter{other.filter, allocator} {}
- /*! @brief Default move constructor. */
- basic_runtime_view(basic_runtime_view &&) noexcept = default;
- /**
- * @brief Allocator-extended move constructor.
- * @param other The instance to move from.
- * @param allocator The allocator to use.
- */
- basic_runtime_view(basic_runtime_view &&other, const allocator_type &allocator)
- : pools{std::move(other.pools), allocator},
- filter{std::move(other.filter), allocator} {}
- /*! @brief Default destructor. */
- ~basic_runtime_view() = default;
- /**
- * @brief Default copy assignment operator.
- * @return This runtime view.
- */
- basic_runtime_view &operator=(const basic_runtime_view &) = default;
- /**
- * @brief Default move assignment operator.
- * @return This runtime view.
- */
- basic_runtime_view &operator=(basic_runtime_view &&) noexcept = default;
- /**
- * @brief Exchanges the contents with those of a given view.
- * @param other View to exchange the content with.
- */
- void swap(basic_runtime_view &other) noexcept {
- using std::swap;
- swap(pools, other.pools);
- swap(filter, other.filter);
- }
- /**
- * @brief Returns the associated allocator.
- * @return The associated allocator.
- */
- [[nodiscard]] constexpr allocator_type get_allocator() const noexcept {
- return pools.get_allocator();
- }
- /*! @brief Clears the view. */
- void clear() {
- pools.clear();
- filter.clear();
- }
- /**
- * @brief Appends an opaque storage object to a runtime view.
- * @param base An opaque reference to a storage object.
- * @return This runtime view.
- */
- basic_runtime_view &iterate(common_type &base) {
- if(pools.empty() || !(base.size() < pools.front()->size())) {
- pools.push_back(&base);
- } else {
- pools.push_back(std::exchange(pools.front(), &base));
- }
- return *this;
- }
- /**
- * @brief Adds an opaque storage object as a filter of a runtime view.
- * @param base An opaque reference to a storage object.
- * @return This runtime view.
- */
- basic_runtime_view &exclude(common_type &base) {
- filter.push_back(&base);
- return *this;
- }
- /**
- * @brief Estimates the number of entities iterated by the view.
- * @return Estimated number of entities iterated by the view.
- */
- [[nodiscard]] size_type size_hint() const {
- return pools.empty() ? size_type{} : offset();
- }
- /**
- * @brief Returns an iterator to the first entity that has the given
- * elements.
- *
- * If the view is empty, the returned iterator will be equal to `end()`.
- *
- * @return An iterator to the first entity that has the given elements.
- */
- [[nodiscard]] iterator begin() const {
- return pools.empty() ? iterator{} : iterator{pools, pools.front()->end() - static_cast<difference_type>(offset()), filter};
- }
- /**
- * @brief Returns an iterator that is past the last entity that has the
- * given elements.
- * @return An iterator to the entity following the last entity that has the
- * given elements.
- */
- [[nodiscard]] iterator end() const {
- return pools.empty() ? iterator{} : iterator{pools, pools.front()->end(), filter};
- }
- /**
- * @brief Checks whether a view is initialized or not.
- * @return True if the view is initialized, false otherwise.
- */
- [[nodiscard]] explicit operator bool() const noexcept {
- return !(pools.empty() && filter.empty());
- }
- /**
- * @brief Checks if a view contains an entity.
- * @param entt A valid identifier.
- * @return True if the view contains the given entity, false otherwise.
- */
- [[nodiscard]] bool contains(const entity_type entt) const {
- return !pools.empty()
- && std::all_of(pools.cbegin(), pools.cend(), [entt](const auto *curr) { return curr->contains(entt); })
- && std::none_of(filter.cbegin(), filter.cend(), [entt](const auto *curr) { return curr && curr->contains(entt); })
- && pools.front()->index(entt) < offset();
- }
- /**
- * @brief Iterates entities and applies the given function object to them.
- *
- * The function object is invoked for each entity. It is provided only with
- * the entity itself.<br/>
- * The signature of the function should be equivalent to the following:
- *
- * @code{.cpp}
- * void(const entity_type);
- * @endcode
- *
- * @tparam Func Type of the function object to invoke.
- * @param func A valid function object.
- */
- template<typename Func>
- void each(Func func) const {
- for(const auto entity: *this) {
- func(entity);
- }
- }
- private:
- container_type pools;
- container_type filter;
- };
- } // namespace entt
- #endif
- // #include "entity/snapshot.hpp"
- #ifndef ENTT_ENTITY_SNAPSHOT_HPP
- #define ENTT_ENTITY_SNAPSHOT_HPP
- #include <cstddef>
- #include <iterator>
- #include <tuple>
- #include <type_traits>
- #include <utility>
- #include <vector>
- // #include "../config/config.h"
- // #include "../container/dense_map.hpp"
- // #include "../core/type_traits.hpp"
- // #include "entity.hpp"
- // #include "fwd.hpp"
- // #include "view.hpp"
- namespace entt {
- /*! @cond TURN_OFF_DOXYGEN */
- namespace internal {
- template<typename Registry>
- void orphans(Registry ®istry) {
- auto &storage = registry.template storage<typename Registry::entity_type>();
- for(auto entt: storage) {
- if(registry.orphan(entt)) {
- storage.erase(entt);
- }
- }
- }
- } // namespace internal
- /*! @endcond */
- /**
- * @brief Utility class to create snapshots from a registry.
- *
- * A _snapshot_ can be either a dump of the entire registry or a narrower
- * selection of elements of interest.<br/>
- * This type can be used in both cases if provided with a correctly configured
- * output archive.
- *
- * @tparam Registry Basic registry type.
- */
- template<typename Registry>
- class basic_snapshot {
- static_assert(!std::is_const_v<Registry>, "Non-const registry type required");
- using traits_type = entt_traits<typename Registry::entity_type>;
- public:
- /*! Basic registry type. */
- using registry_type = Registry;
- /*! @brief Underlying entity identifier. */
- using entity_type = typename registry_type::entity_type;
- /**
- * @brief Constructs an instance that is bound to a given registry.
- * @param source A valid reference to a registry.
- */
- basic_snapshot(const registry_type &source) noexcept
- : reg{&source} {}
- /*! @brief Default copy constructor, deleted on purpose. */
- basic_snapshot(const basic_snapshot &) = delete;
- /*! @brief Default move constructor. */
- basic_snapshot(basic_snapshot &&) noexcept = default;
- /*! @brief Default destructor. */
- ~basic_snapshot() = default;
- /**
- * @brief Default copy assignment operator, deleted on purpose.
- * @return This snapshot.
- */
- basic_snapshot &operator=(const basic_snapshot &) = delete;
- /**
- * @brief Default move assignment operator.
- * @return This snapshot.
- */
- basic_snapshot &operator=(basic_snapshot &&) noexcept = default;
- /**
- * @brief Serializes all elements of a type with associated identifiers.
- * @tparam Type Type of elements to serialize.
- * @tparam Archive Type of output archive.
- * @param archive A valid reference to an output archive.
- * @param id Optional name used to map the storage within the registry.
- * @return An object of this type to continue creating the snapshot.
- */
- template<typename Type, typename Archive>
- const basic_snapshot &get(Archive &archive, const id_type id = type_hash<Type>::value()) const {
- if(const auto *storage = reg->template storage<Type>(id); storage) {
- const typename registry_type::common_type &base = *storage;
- archive(static_cast<typename traits_type::entity_type>(storage->size()));
- if constexpr(std::is_same_v<Type, entity_type>) {
- archive(static_cast<typename traits_type::entity_type>(storage->free_list()));
- for(auto first = base.rbegin(), last = base.rend(); first != last; ++first) {
- archive(*first);
- }
- } else if constexpr(registry_type::template storage_for_type<Type>::storage_policy == deletion_policy::in_place) {
- for(auto it = base.rbegin(), last = base.rend(); it != last; ++it) {
- if(const auto entt = *it; entt == tombstone) {
- archive(static_cast<entity_type>(null));
- } else {
- archive(entt);
- std::apply([&archive](auto &&...args) { (archive(std::forward<decltype(args)>(args)), ...); }, storage->get_as_tuple(entt));
- }
- }
- } else {
- for(auto elem: storage->reach()) {
- std::apply([&archive](auto &&...args) { (archive(std::forward<decltype(args)>(args)), ...); }, elem);
- }
- }
- } else {
- archive(typename traits_type::entity_type{});
- }
- return *this;
- }
- /**
- * @brief Serializes all elements of a type with associated identifiers for
- * the entities in a range.
- * @tparam Type Type of elements to serialize.
- * @tparam Archive Type of output archive.
- * @tparam It Type of input iterator.
- * @param archive A valid reference to an output archive.
- * @param first An iterator to the first element of the range to serialize.
- * @param last An iterator past the last element of the range to serialize.
- * @param id Optional name used to map the storage within the registry.
- * @return An object of this type to continue creating the snapshot.
- */
- template<typename Type, typename Archive, typename It>
- const basic_snapshot &get(Archive &archive, It first, It last, const id_type id = type_hash<Type>::value()) const {
- static_assert(!std::is_same_v<Type, entity_type>, "Entity types not supported");
- if(const auto *storage = reg->template storage<Type>(id); storage && !storage->empty()) {
- archive(static_cast<typename traits_type::entity_type>(std::distance(first, last)));
- for(; first != last; ++first) {
- if(const auto entt = *first; storage->contains(entt)) {
- archive(entt);
- std::apply([&archive](auto &&...args) { (archive(std::forward<decltype(args)>(args)), ...); }, storage->get_as_tuple(entt));
- } else {
- archive(static_cast<entity_type>(null));
- }
- }
- } else {
- archive(typename traits_type::entity_type{});
- }
- return *this;
- }
- private:
- const registry_type *reg;
- };
- /**
- * @brief Utility class to restore a snapshot as a whole.
- *
- * A snapshot loader requires that the destination registry be empty and loads
- * all the data at once while keeping intact the identifiers that the entities
- * originally had.<br/>
- * An example of use is the implementation of a save/restore utility.
- *
- * @tparam Registry Basic registry type.
- */
- template<typename Registry>
- class basic_snapshot_loader {
- static_assert(!std::is_const_v<Registry>, "Non-const registry type required");
- using traits_type = entt_traits<typename Registry::entity_type>;
- public:
- /*! Basic registry type. */
- using registry_type = Registry;
- /*! @brief Underlying entity identifier. */
- using entity_type = typename registry_type::entity_type;
- /**
- * @brief Constructs an instance that is bound to a given registry.
- * @param source A valid reference to a registry.
- */
- basic_snapshot_loader(registry_type &source) noexcept
- : reg{&source} {
- // restoring a snapshot as a whole requires a clean registry
- ENTT_ASSERT(reg->template storage<entity_type>().free_list() == 0u, "Registry must be empty");
- }
- /*! @brief Default copy constructor, deleted on purpose. */
- basic_snapshot_loader(const basic_snapshot_loader &) = delete;
- /*! @brief Default move constructor. */
- basic_snapshot_loader(basic_snapshot_loader &&) noexcept = default;
- /*! @brief Default destructor. */
- ~basic_snapshot_loader() = default;
- /**
- * @brief Default copy assignment operator, deleted on purpose.
- * @return This loader.
- */
- basic_snapshot_loader &operator=(const basic_snapshot_loader &) = delete;
- /**
- * @brief Default move assignment operator.
- * @return This loader.
- */
- basic_snapshot_loader &operator=(basic_snapshot_loader &&) noexcept = default;
- /**
- * @brief Restores all elements of a type with associated identifiers.
- * @tparam Type Type of elements to restore.
- * @tparam Archive Type of input archive.
- * @param archive A valid reference to an input archive.
- * @param id Optional name used to map the storage within the registry.
- * @return A valid loader to continue restoring data.
- */
- template<typename Type, typename Archive>
- basic_snapshot_loader &get(Archive &archive, const id_type id = type_hash<Type>::value()) {
- auto &storage = reg->template storage<Type>(id);
- typename traits_type::entity_type length{};
- archive(length);
- if constexpr(std::is_same_v<Type, entity_type>) {
- typename traits_type::entity_type count{};
- entity_type placeholder{};
- storage.reserve(length);
- archive(count);
- for(entity_type entity = null; length; --length) {
- archive(entity);
- storage.generate(entity);
- placeholder = (entity > placeholder) ? entity : placeholder;
- }
- storage.start_from(traits_type::next(placeholder));
- storage.free_list(count);
- } else {
- auto &other = reg->template storage<entity_type>();
- entity_type entt{null};
- while(length--) {
- if(archive(entt); entt != null) {
- const auto entity = other.contains(entt) ? entt : other.generate(entt);
- ENTT_ASSERT(entity == entt, "Entity not available for use");
- if constexpr(std::tuple_size_v<decltype(storage.get_as_tuple({}))> == 0u) {
- storage.emplace(entity);
- } else {
- Type elem{};
- archive(elem);
- storage.emplace(entity, std::move(elem));
- }
- }
- }
- }
- return *this;
- }
- /**
- * @brief Destroys those entities that have no elements.
- *
- * In case all the entities were serialized but only part of the elements
- * was saved, it could happen that some of the entities have no elements
- * once restored.<br/>
- * This function helps to identify and destroy those entities.
- *
- * @return A valid loader to continue restoring data.
- */
- basic_snapshot_loader &orphans() {
- internal::orphans(*reg);
- return *this;
- }
- private:
- registry_type *reg;
- };
- /**
- * @brief Utility class for _continuous loading_.
- *
- * A _continuous loader_ is designed to load data from a source registry to a
- * (possibly) non-empty destination. The loader can accommodate in a registry
- * more than one snapshot in a sort of _continuous loading_ that updates the
- * destination one step at a time.<br/>
- * Identifiers that entities originally had are not transferred to the target.
- * Instead, the loader maps remote identifiers to local ones while restoring a
- * snapshot.<br/>
- * An example of use is the implementation of a client-server application with
- * the requirement of transferring somehow parts of the representation side to
- * side.
- *
- * @tparam Registry Basic registry type.
- */
- template<typename Registry>
- class basic_continuous_loader {
- static_assert(!std::is_const_v<Registry>, "Non-const registry type required");
- using traits_type = entt_traits<typename Registry::entity_type>;
- void restore(typename Registry::entity_type entt) {
- if(const auto entity = to_entity(entt); remloc.contains(entity) && remloc[entity].first == entt) {
- if(!reg->valid(remloc[entity].second)) {
- remloc[entity].second = reg->create();
- }
- } else {
- remloc.insert_or_assign(entity, std::make_pair(entt, reg->create()));
- }
- }
- template<typename Container>
- auto update(int, Container &container) -> decltype(typename Container::mapped_type{}, void()) {
- // map like container
- Container other;
- for(auto &&pair: container) {
- using first_type = std::remove_const_t<typename std::decay_t<decltype(pair)>::first_type>;
- using second_type = typename std::decay_t<decltype(pair)>::second_type;
- if constexpr(std::is_same_v<first_type, entity_type> && std::is_same_v<second_type, entity_type>) {
- other.emplace(map(pair.first), map(pair.second));
- } else if constexpr(std::is_same_v<first_type, entity_type>) {
- other.emplace(map(pair.first), std::move(pair.second));
- } else {
- static_assert(std::is_same_v<second_type, entity_type>, "Neither the key nor the value are of entity type");
- other.emplace(std::move(pair.first), map(pair.second));
- }
- }
- using std::swap;
- swap(container, other);
- }
- template<typename Container>
- auto update(char, Container &container) -> decltype(typename Container::value_type{}, void()) {
- // vector like container
- static_assert(std::is_same_v<typename Container::value_type, entity_type>, "Invalid value type");
- for(auto &&entt: container) {
- entt = map(entt);
- }
- }
- template<typename Component, typename Other, typename Member>
- void update([[maybe_unused]] Component &instance, [[maybe_unused]] Member Other::*member) {
- if constexpr(!std::is_same_v<Component, Other>) {
- return;
- } else if constexpr(std::is_same_v<Member, entity_type>) {
- instance.*member = map(instance.*member);
- } else {
- // maybe a container? let's try...
- update(0, instance.*member);
- }
- }
- public:
- /*! Basic registry type. */
- using registry_type = Registry;
- /*! @brief Underlying entity identifier. */
- using entity_type = typename registry_type::entity_type;
- /**
- * @brief Constructs an instance that is bound to a given registry.
- * @param source A valid reference to a registry.
- */
- basic_continuous_loader(registry_type &source) noexcept
- : remloc{source.get_allocator()},
- reg{&source} {}
- /*! @brief Default copy constructor, deleted on purpose. */
- basic_continuous_loader(const basic_continuous_loader &) = delete;
- /*! @brief Default move constructor. */
- basic_continuous_loader(basic_continuous_loader &&) noexcept = default;
- /*! @brief Default destructor. */
- ~basic_continuous_loader() = default;
- /**
- * @brief Default copy assignment operator, deleted on purpose.
- * @return This loader.
- */
- basic_continuous_loader &operator=(const basic_continuous_loader &) = delete;
- /**
- * @brief Default move assignment operator.
- * @return This loader.
- */
- basic_continuous_loader &operator=(basic_continuous_loader &&) noexcept = default;
- /**
- * @brief Restores all elements of a type with associated identifiers.
- *
- * It creates local counterparts for remote elements as needed.<br/>
- * Members are either data members of type entity_type or containers of
- * entities. In both cases, a loader visits them and replaces entities with
- * their local counterpart.
- *
- * @tparam Type Type of elements to restore.
- * @tparam Archive Type of input archive.
- * @param archive A valid reference to an input archive.
- * @param id Optional name used to map the storage within the registry.
- * @return A valid loader to continue restoring data.
- */
- template<typename Type, typename Archive>
- basic_continuous_loader &get(Archive &archive, const id_type id = type_hash<Type>::value()) {
- auto &storage = reg->template storage<Type>(id);
- typename traits_type::entity_type length{};
- entity_type entt{null};
- archive(length);
- if constexpr(std::is_same_v<Type, entity_type>) {
- typename traits_type::entity_type in_use{};
- storage.reserve(length);
- archive(in_use);
- for(std::size_t pos{}; pos < in_use; ++pos) {
- archive(entt);
- restore(entt);
- }
- for(std::size_t pos = in_use; pos < length; ++pos) {
- archive(entt);
- if(const auto entity = to_entity(entt); remloc.contains(entity)) {
- if(reg->valid(remloc[entity].second)) {
- reg->destroy(remloc[entity].second);
- }
- remloc.erase(entity);
- }
- }
- } else {
- for(auto &&ref: remloc) {
- storage.remove(ref.second.second);
- }
- while(length--) {
- if(archive(entt); entt != null) {
- restore(entt);
- if constexpr(std::tuple_size_v<decltype(storage.get_as_tuple({}))> == 0u) {
- storage.emplace(map(entt));
- } else {
- Type elem{};
- archive(elem);
- storage.emplace(map(entt), std::move(elem));
- }
- }
- }
- }
- return *this;
- }
- /**
- * @brief Destroys those entities that have no elements.
- *
- * In case all the entities were serialized but only part of the elements
- * was saved, it could happen that some of the entities have no elements
- * once restored.<br/>
- * This function helps to identify and destroy those entities.
- *
- * @return A non-const reference to this loader.
- */
- basic_continuous_loader &orphans() {
- internal::orphans(*reg);
- return *this;
- }
- /**
- * @brief Tests if a loader knows about a given entity.
- * @param entt A valid identifier.
- * @return True if `entity` is managed by the loader, false otherwise.
- */
- [[nodiscard]] bool contains(entity_type entt) const noexcept {
- const auto it = remloc.find(to_entity(entt));
- return it != remloc.cend() && it->second.first == entt;
- }
- /**
- * @brief Returns the identifier to which an entity refers.
- * @param entt A valid identifier.
- * @return The local identifier if any, the null entity otherwise.
- */
- [[nodiscard]] entity_type map(entity_type entt) const noexcept {
- if(const auto it = remloc.find(to_entity(entt)); it != remloc.cend() && it->second.first == entt) {
- return it->second.second;
- }
- return null;
- }
- private:
- dense_map<typename traits_type::entity_type, std::pair<entity_type, entity_type>> remloc;
- registry_type *reg;
- };
- } // namespace entt
- #endif
- // #include "entity/sparse_set.hpp"
- #ifndef ENTT_ENTITY_SPARSE_SET_HPP
- #define ENTT_ENTITY_SPARSE_SET_HPP
- #include <cstddef>
- #include <iterator>
- #include <memory>
- #include <type_traits>
- #include <utility>
- #include <vector>
- // #include "../config/config.h"
- // #include "../core/algorithm.hpp"
- // #include "../core/any.hpp"
- // #include "../core/bit.hpp"
- // #include "../core/type_info.hpp"
- // #include "entity.hpp"
- // #include "fwd.hpp"
- namespace entt {
- /*! @cond TURN_OFF_DOXYGEN */
- namespace internal {
- template<typename Container>
- struct sparse_set_iterator final {
- using value_type = typename Container::value_type;
- using pointer = typename Container::const_pointer;
- using reference = typename Container::const_reference;
- using difference_type = typename Container::difference_type;
- using iterator_category = std::random_access_iterator_tag;
- constexpr sparse_set_iterator() noexcept
- : packed{},
- offset{} {}
- constexpr sparse_set_iterator(const Container &ref, const difference_type idx) noexcept
- : packed{&ref},
- offset{idx} {}
- constexpr sparse_set_iterator &operator++() noexcept {
- return --offset, *this;
- }
- constexpr sparse_set_iterator operator++(int) noexcept {
- const sparse_set_iterator orig = *this;
- return ++(*this), orig;
- }
- constexpr sparse_set_iterator &operator--() noexcept {
- return ++offset, *this;
- }
- constexpr sparse_set_iterator operator--(int) noexcept {
- const sparse_set_iterator orig = *this;
- return operator--(), orig;
- }
- constexpr sparse_set_iterator &operator+=(const difference_type value) noexcept {
- offset -= value;
- return *this;
- }
- constexpr sparse_set_iterator operator+(const difference_type value) const noexcept {
- sparse_set_iterator copy = *this;
- return (copy += value);
- }
- constexpr sparse_set_iterator &operator-=(const difference_type value) noexcept {
- return (*this += -value);
- }
- constexpr sparse_set_iterator operator-(const difference_type value) const noexcept {
- return (*this + -value);
- }
- [[nodiscard]] constexpr reference operator[](const difference_type value) const noexcept {
- return (*packed)[static_cast<typename Container::size_type>(index() - value)];
- }
- [[nodiscard]] constexpr pointer operator->() const noexcept {
- return std::addressof(operator[](0));
- }
- [[nodiscard]] constexpr reference operator*() const noexcept {
- return operator[](0);
- }
- [[nodiscard]] constexpr pointer data() const noexcept {
- return packed ? packed->data() : nullptr;
- }
- [[nodiscard]] constexpr difference_type index() const noexcept {
- return offset - 1;
- }
- private:
- const Container *packed;
- difference_type offset;
- };
- template<typename Container>
- [[nodiscard]] constexpr std::ptrdiff_t operator-(const sparse_set_iterator<Container> &lhs, const sparse_set_iterator<Container> &rhs) noexcept {
- return rhs.index() - lhs.index();
- }
- template<typename Container>
- [[nodiscard]] constexpr bool operator==(const sparse_set_iterator<Container> &lhs, const sparse_set_iterator<Container> &rhs) noexcept {
- return lhs.index() == rhs.index();
- }
- template<typename Container>
- [[nodiscard]] constexpr bool operator!=(const sparse_set_iterator<Container> &lhs, const sparse_set_iterator<Container> &rhs) noexcept {
- return !(lhs == rhs);
- }
- template<typename Container>
- [[nodiscard]] constexpr bool operator<(const sparse_set_iterator<Container> &lhs, const sparse_set_iterator<Container> &rhs) noexcept {
- return lhs.index() > rhs.index();
- }
- template<typename Container>
- [[nodiscard]] constexpr bool operator>(const sparse_set_iterator<Container> &lhs, const sparse_set_iterator<Container> &rhs) noexcept {
- return rhs < lhs;
- }
- template<typename Container>
- [[nodiscard]] constexpr bool operator<=(const sparse_set_iterator<Container> &lhs, const sparse_set_iterator<Container> &rhs) noexcept {
- return !(lhs > rhs);
- }
- template<typename Container>
- [[nodiscard]] constexpr bool operator>=(const sparse_set_iterator<Container> &lhs, const sparse_set_iterator<Container> &rhs) noexcept {
- return !(lhs < rhs);
- }
- } // namespace internal
- /*! @endcond */
- /**
- * @brief Sparse set implementation.
- *
- * Sparse set or packed array or whatever is the name users give it.<br/>
- * Two arrays: an _external_ one and an _internal_ one; a _sparse_ one and a
- * _packed_ one; one used for direct access through contiguous memory, the other
- * one used to get the data through an extra level of indirection.<br/>
- * This type of data structure is widely documented in the literature and on the
- * web. This is nothing more than a customized implementation suitable for the
- * purpose of the framework.
- *
- * @note
- * Internal data structures arrange elements to maximize performance. There are
- * no guarantees that entities are returned in the insertion order when iterate
- * a sparse set. Do not make assumption on the order in any case.
- *
- * @tparam Entity A valid entity type.
- * @tparam Allocator Type of allocator used to manage memory and elements.
- */
- template<typename Entity, typename Allocator>
- class basic_sparse_set {
- using alloc_traits = std::allocator_traits<Allocator>;
- static_assert(std::is_same_v<typename alloc_traits::value_type, Entity>, "Invalid value type");
- using sparse_container_type = std::vector<typename alloc_traits::pointer, typename alloc_traits::template rebind_alloc<typename alloc_traits::pointer>>;
- using packed_container_type = std::vector<Entity, Allocator>;
- using traits_type = entt_traits<Entity>;
- static constexpr auto max_size = static_cast<std::size_t>(traits_type::to_entity(null));
- // it could be auto but gcc complains and emits a warning due to a false positive
- [[nodiscard]] std::size_t policy_to_head() const noexcept {
- return static_cast<size_type>(max_size * static_cast<std::remove_const_t<decltype(max_size)>>(mode != deletion_policy::swap_only));
- }
- [[nodiscard]] auto entity_to_pos(const Entity entt) const noexcept {
- return static_cast<size_type>(traits_type::to_entity(entt));
- }
- [[nodiscard]] auto pos_to_page(const std::size_t pos) const noexcept {
- return static_cast<size_type>(pos / traits_type::page_size);
- }
- [[nodiscard]] auto sparse_ptr(const Entity entt) const {
- const auto pos = entity_to_pos(entt);
- const auto page = pos_to_page(pos);
- return (page < sparse.size() && sparse[page]) ? (sparse[page] + fast_mod(pos, traits_type::page_size)) : nullptr;
- }
- [[nodiscard]] auto &sparse_ref(const Entity entt) const {
- ENTT_ASSERT(sparse_ptr(entt), "Invalid element");
- const auto pos = entity_to_pos(entt);
- return sparse[pos_to_page(pos)][fast_mod(pos, traits_type::page_size)];
- }
- [[nodiscard]] auto to_iterator(const Entity entt) const {
- return --(end() - static_cast<difference_type>(index(entt)));
- }
- [[nodiscard]] auto &assure_at_least(const Entity entt) {
- const auto pos = entity_to_pos(entt);
- const auto page = pos_to_page(pos);
- if(!(page < sparse.size())) {
- sparse.resize(page + 1u, nullptr);
- }
- if(!sparse[page]) {
- constexpr entity_type init = null;
- auto page_allocator{packed.get_allocator()};
- sparse[page] = alloc_traits::allocate(page_allocator, traits_type::page_size);
- std::uninitialized_fill(sparse[page], sparse[page] + traits_type::page_size, init);
- }
- return sparse[page][fast_mod(pos, traits_type::page_size)];
- }
- void release_sparse_pages() {
- auto page_allocator{packed.get_allocator()};
- for(auto &&page: sparse) {
- if(page != nullptr) {
- std::destroy(page, page + traits_type::page_size);
- alloc_traits::deallocate(page_allocator, page, traits_type::page_size);
- page = nullptr;
- }
- }
- }
- void swap_at(const std::size_t lhs, const std::size_t rhs) {
- auto &from = packed[lhs];
- auto &to = packed[rhs];
- sparse_ref(from) = traits_type::combine(static_cast<typename traits_type::entity_type>(rhs), traits_type::to_integral(from));
- sparse_ref(to) = traits_type::combine(static_cast<typename traits_type::entity_type>(lhs), traits_type::to_integral(to));
- std::swap(from, to);
- }
- private:
- [[nodiscard]] virtual const void *get_at(const std::size_t) const {
- return nullptr;
- }
- virtual void swap_or_move([[maybe_unused]] const std::size_t lhs, [[maybe_unused]] const std::size_t rhs) {
- ENTT_ASSERT((mode != deletion_policy::swap_only) || ((lhs < head) == (rhs < head)), "Cross swapping is not supported");
- }
- protected:
- /*! @brief Random access iterator type. */
- using basic_iterator = internal::sparse_set_iterator<packed_container_type>;
- /**
- * @brief Erases an entity from a sparse set.
- * @param it An iterator to the element to pop.
- */
- void swap_only(const basic_iterator it) {
- ENTT_ASSERT(mode == deletion_policy::swap_only, "Deletion policy mismatch");
- const auto pos = index(*it);
- bump(traits_type::next(*it));
- swap_at(pos, head -= (pos < head));
- }
- /**
- * @brief Erases an entity from a sparse set.
- * @param it An iterator to the element to pop.
- */
- void swap_and_pop(const basic_iterator it) {
- ENTT_ASSERT(mode == deletion_policy::swap_and_pop, "Deletion policy mismatch");
- auto &self = sparse_ref(*it);
- const auto entt = traits_type::to_entity(self);
- sparse_ref(packed.back()) = traits_type::combine(entt, traits_type::to_integral(packed.back()));
- packed[static_cast<size_type>(entt)] = packed.back();
- // unnecessary but it helps to detect nasty bugs
- // NOLINTNEXTLINE(bugprone-assert-side-effect)
- ENTT_ASSERT((packed.back() = null, true), "");
- // lazy self-assignment guard
- self = null;
- packed.pop_back();
- }
- /**
- * @brief Erases an entity from a sparse set.
- * @param it An iterator to the element to pop.
- */
- void in_place_pop(const basic_iterator it) {
- ENTT_ASSERT(mode == deletion_policy::in_place, "Deletion policy mismatch");
- const auto pos = entity_to_pos(std::exchange(sparse_ref(*it), null));
- packed[pos] = traits_type::combine(static_cast<typename traits_type::entity_type>(std::exchange(head, pos)), tombstone);
- }
- /**
- * @brief Erases entities from a sparse set.
- * @param first An iterator to the first element of the range of entities.
- * @param last An iterator past the last element of the range of entities.
- */
- virtual void pop(basic_iterator first, basic_iterator last) {
- switch(mode) {
- case deletion_policy::swap_and_pop:
- for(; first != last; ++first) {
- swap_and_pop(first);
- }
- break;
- case deletion_policy::in_place:
- for(; first != last; ++first) {
- in_place_pop(first);
- }
- break;
- case deletion_policy::swap_only:
- for(; first != last; ++first) {
- swap_only(first);
- }
- break;
- }
- }
- /*! @brief Erases all entities of a sparse set. */
- virtual void pop_all() {
- switch(mode) {
- case deletion_policy::in_place:
- if(head != max_size) {
- for(auto &&elem: packed) {
- if(elem != tombstone) {
- sparse_ref(elem) = null;
- }
- }
- break;
- }
- [[fallthrough]];
- case deletion_policy::swap_only:
- case deletion_policy::swap_and_pop:
- for(auto &&elem: packed) {
- sparse_ref(elem) = null;
- }
- break;
- }
- head = policy_to_head();
- packed.clear();
- }
- /**
- * @brief Assigns an entity to a sparse set.
- * @param entt A valid identifier.
- * @param force_back Force back insertion.
- * @return Iterator pointing to the emplaced element.
- */
- virtual basic_iterator try_emplace(const Entity entt, const bool force_back, const void * = nullptr) {
- ENTT_ASSERT(entt != null && entt != tombstone, "Invalid element");
- auto &elem = assure_at_least(entt);
- auto pos = size();
- switch(mode) {
- case deletion_policy::in_place:
- if(head != max_size && !force_back) {
- pos = head;
- ENTT_ASSERT(elem == null, "Slot not available");
- elem = traits_type::combine(static_cast<typename traits_type::entity_type>(head), traits_type::to_integral(entt));
- head = entity_to_pos(std::exchange(packed[pos], entt));
- break;
- }
- [[fallthrough]];
- case deletion_policy::swap_and_pop:
- packed.push_back(entt);
- ENTT_ASSERT(elem == null, "Slot not available");
- elem = traits_type::combine(static_cast<typename traits_type::entity_type>(packed.size() - 1u), traits_type::to_integral(entt));
- break;
- case deletion_policy::swap_only:
- if(elem == null) {
- packed.push_back(entt);
- elem = traits_type::combine(static_cast<typename traits_type::entity_type>(packed.size() - 1u), traits_type::to_integral(entt));
- } else {
- ENTT_ASSERT(!(entity_to_pos(elem) < head), "Slot not available");
- bump(entt);
- }
- pos = head++;
- swap_at(entity_to_pos(elem), pos);
- break;
- }
- return iterator{packed, static_cast<difference_type>(++pos)};
- }
- /*! @brief Forwards variables to derived classes, if any. */
- // NOLINTNEXTLINE(performance-unnecessary-value-param)
- virtual void bind_any(any) noexcept {}
- public:
- /*! @brief Allocator type. */
- using allocator_type = Allocator;
- /*! @brief Underlying entity identifier. */
- using entity_type = typename traits_type::value_type;
- /*! @brief Underlying version type. */
- using version_type = typename traits_type::version_type;
- /*! @brief Unsigned integer type. */
- using size_type = std::size_t;
- /*! @brief Signed integer type. */
- using difference_type = std::ptrdiff_t;
- /*! @brief Pointer type to contained entities. */
- using pointer = typename packed_container_type::const_pointer;
- /*! @brief Random access iterator type. */
- using iterator = basic_iterator;
- /*! @brief Constant random access iterator type. */
- using const_iterator = iterator;
- /*! @brief Reverse iterator type. */
- using reverse_iterator = std::reverse_iterator<iterator>;
- /*! @brief Constant reverse iterator type. */
- using const_reverse_iterator = std::reverse_iterator<const_iterator>;
- /*! @brief Default constructor. */
- basic_sparse_set()
- : basic_sparse_set{type_id<void>()} {}
- /**
- * @brief Constructs an empty container with a given allocator.
- * @param allocator The allocator to use.
- */
- explicit basic_sparse_set(const allocator_type &allocator)
- : basic_sparse_set{deletion_policy::swap_and_pop, allocator} {}
- /**
- * @brief Constructs an empty container with the given policy and allocator.
- * @param pol Type of deletion policy.
- * @param allocator The allocator to use (possibly default-constructed).
- */
- explicit basic_sparse_set(deletion_policy pol, const allocator_type &allocator = {})
- : basic_sparse_set{type_id<void>(), pol, allocator} {}
- /**
- * @brief Constructs an empty container with the given value type, policy
- * and allocator.
- * @param elem Returned value type, if any.
- * @param pol Type of deletion policy.
- * @param allocator The allocator to use (possibly default-constructed).
- */
- explicit basic_sparse_set(const type_info &elem, deletion_policy pol = deletion_policy::swap_and_pop, const allocator_type &allocator = {})
- : sparse{allocator},
- packed{allocator},
- descriptor{&elem},
- mode{pol},
- head{policy_to_head()} {
- ENTT_ASSERT(traits_type::version_mask || mode != deletion_policy::in_place, "Policy does not support zero-sized versions");
- }
- /*! @brief Default copy constructor, deleted on purpose. */
- basic_sparse_set(const basic_sparse_set &) = delete;
- /**
- * @brief Move constructor.
- * @param other The instance to move from.
- */
- basic_sparse_set(basic_sparse_set &&other) noexcept
- : sparse{std::move(other.sparse)},
- packed{std::move(other.packed)},
- descriptor{other.descriptor},
- mode{other.mode},
- head{std::exchange(other.head, policy_to_head())} {}
- /**
- * @brief Allocator-extended move constructor.
- * @param other The instance to move from.
- * @param allocator The allocator to use.
- */
- basic_sparse_set(basic_sparse_set &&other, const allocator_type &allocator)
- : sparse{std::move(other.sparse), allocator},
- packed{std::move(other.packed), allocator},
- descriptor{other.descriptor},
- mode{other.mode},
- head{std::exchange(other.head, policy_to_head())} {
- ENTT_ASSERT(alloc_traits::is_always_equal::value || get_allocator() == other.get_allocator(), "Copying a sparse set is not allowed");
- }
- /*! @brief Default destructor. */
- virtual ~basic_sparse_set() {
- release_sparse_pages();
- }
- /**
- * @brief Default copy assignment operator, deleted on purpose.
- * @return This sparse set.
- */
- basic_sparse_set &operator=(const basic_sparse_set &) = delete;
- /**
- * @brief Move assignment operator.
- * @param other The instance to move from.
- * @return This sparse set.
- */
- basic_sparse_set &operator=(basic_sparse_set &&other) noexcept {
- ENTT_ASSERT(alloc_traits::is_always_equal::value || get_allocator() == other.get_allocator(), "Copying a sparse set is not allowed");
- swap(other);
- return *this;
- }
- /**
- * @brief Exchanges the contents with those of a given sparse set.
- * @param other Sparse set to exchange the content with.
- */
- void swap(basic_sparse_set &other) noexcept {
- using std::swap;
- swap(sparse, other.sparse);
- swap(packed, other.packed);
- swap(descriptor, other.descriptor);
- swap(mode, other.mode);
- swap(head, other.head);
- }
- /**
- * @brief Returns the associated allocator.
- * @return The associated allocator.
- */
- [[nodiscard]] constexpr allocator_type get_allocator() const noexcept {
- return packed.get_allocator();
- }
- /**
- * @brief Returns the deletion policy of a sparse set.
- * @return The deletion policy of the sparse set.
- */
- [[nodiscard]] deletion_policy policy() const noexcept {
- return mode;
- }
- /**
- * @brief Returns data on the free list whose meaning depends on the mode.
- * @return Free list information that is mode dependent.
- */
- [[nodiscard]] size_type free_list() const noexcept {
- return head;
- }
- /**
- * @brief Sets data on the free list whose meaning depends on the mode.
- * @param value Free list information that is mode dependent.
- */
- void free_list(const size_type value) noexcept {
- ENTT_ASSERT((mode == deletion_policy::swap_only) && !(value > packed.size()), "Invalid value");
- head = value;
- }
- /**
- * @brief Increases the capacity of a sparse set.
- *
- * If the new capacity is greater than the current capacity, new storage is
- * allocated, otherwise the method does nothing.
- *
- * @param cap Desired capacity.
- */
- virtual void reserve(const size_type cap) {
- packed.reserve(cap);
- }
- /**
- * @brief Returns the number of elements that a sparse set has currently
- * allocated space for.
- * @return Capacity of the sparse set.
- */
- [[nodiscard]] virtual size_type capacity() const noexcept {
- return packed.capacity();
- }
- /*! @brief Requests the removal of unused capacity. */
- virtual void shrink_to_fit() {
- sparse_container_type other{sparse.get_allocator()};
- const auto len = sparse.size();
- size_type cnt{};
- other.reserve(len);
- for(auto &&elem: std::as_const(packed)) {
- if(elem != tombstone) {
- if(const auto page = pos_to_page(entity_to_pos(elem)); sparse[page] != nullptr) {
- if(const auto sz = page + 1u; sz > other.size()) {
- other.resize(sz, nullptr);
- }
- other[page] = std::exchange(sparse[page], nullptr);
- if(++cnt == len) {
- // early exit due to lack of pages
- break;
- }
- }
- }
- }
- release_sparse_pages();
- sparse.swap(other);
- sparse.shrink_to_fit();
- packed.shrink_to_fit();
- }
- /**
- * @brief Returns the extent of a sparse set.
- *
- * The extent of a sparse set is also the size of the internal sparse array.
- * There is no guarantee that all pages have been allocated, nor that the
- * internal packed array is be the same size.
- *
- * @return Extent of the sparse set.
- */
- [[nodiscard]] size_type extent() const noexcept {
- return sparse.size() * traits_type::page_size;
- }
- /**
- * @brief Returns the number of elements in a sparse set.
- *
- * The number of elements is also the size of the internal packed array.
- * There is no guarantee that the internal sparse array has the same size.
- * Usually the size of the internal sparse array is equal or greater than
- * the one of the internal packed array.
- *
- * @return Number of elements.
- */
- [[nodiscard]] size_type size() const noexcept {
- return packed.size();
- }
- /**
- * @brief Checks whether a sparse set is empty.
- * @return True if the sparse set is empty, false otherwise.
- */
- [[nodiscard]] bool empty() const noexcept {
- return packed.empty();
- }
- /**
- * @brief Checks whether a sparse set is fully packed.
- * @return True if the sparse set is fully packed, false otherwise.
- */
- [[nodiscard]] bool contiguous() const noexcept {
- return (mode != deletion_policy::in_place) || (head == max_size);
- }
- /**
- * @brief Direct access to the internal packed array.
- * @return A pointer to the internal packed array.
- */
- [[nodiscard]] pointer data() const noexcept {
- return packed.data();
- }
- /**
- * @brief Returns an iterator to the beginning.
- *
- * If the sparse set is empty, the returned iterator will be equal to
- * `end()`.
- *
- * @return An iterator to the first entity of the sparse set.
- */
- [[nodiscard]] iterator begin() const noexcept {
- const auto pos = static_cast<difference_type>(packed.size());
- return iterator{packed, pos};
- }
- /*! @copydoc begin */
- [[nodiscard]] const_iterator cbegin() const noexcept {
- return begin();
- }
- /**
- * @brief Returns an iterator to the end.
- * @return An iterator to the element following the last entity of a sparse
- * set.
- */
- [[nodiscard]] iterator end() const noexcept {
- return iterator{packed, {}};
- }
- /*! @copydoc end */
- [[nodiscard]] const_iterator cend() const noexcept {
- return end();
- }
- /**
- * @brief Returns a reverse iterator to the beginning.
- *
- * If the sparse set is empty, the returned iterator will be equal to
- * `rend()`.
- *
- * @return An iterator to the first entity of the reversed internal packed
- * array.
- */
- [[nodiscard]] reverse_iterator rbegin() const noexcept {
- return std::make_reverse_iterator(end());
- }
- /*! @copydoc rbegin */
- [[nodiscard]] const_reverse_iterator crbegin() const noexcept {
- return rbegin();
- }
- /**
- * @brief Returns a reverse iterator to the end.
- * @return An iterator to the element following the last entity of the
- * reversed sparse set.
- */
- [[nodiscard]] reverse_iterator rend() const noexcept {
- return std::make_reverse_iterator(begin());
- }
- /*! @copydoc rend */
- [[nodiscard]] const_reverse_iterator crend() const noexcept {
- return rend();
- }
- /**
- * @brief Finds an entity.
- * @param entt A valid identifier.
- * @return An iterator to the given entity if it's found, past the end
- * iterator otherwise.
- */
- [[nodiscard]] const_iterator find(const entity_type entt) const noexcept {
- return contains(entt) ? to_iterator(entt) : end();
- }
- /**
- * @brief Checks if a sparse set contains an entity.
- * @param entt A valid identifier.
- * @return True if the sparse set contains the entity, false otherwise.
- */
- [[nodiscard]] bool contains(const entity_type entt) const noexcept {
- const auto *elem = sparse_ptr(entt);
- constexpr auto cap = traits_type::entity_mask;
- constexpr auto mask = traits_type::to_integral(null) & ~cap;
- // testing versions permits to avoid accessing the packed array
- return elem && (((mask & traits_type::to_integral(entt)) ^ traits_type::to_integral(*elem)) < cap);
- }
- /**
- * @brief Returns the contained version for an identifier.
- * @param entt A valid identifier.
- * @return The version for the given identifier if present, the tombstone
- * version otherwise.
- */
- [[nodiscard]] version_type current(const entity_type entt) const noexcept {
- const auto *elem = sparse_ptr(entt);
- constexpr auto fallback = traits_type::to_version(tombstone);
- return elem ? traits_type::to_version(*elem) : fallback;
- }
- /**
- * @brief Returns the position of an entity in a sparse set.
- *
- * @warning
- * Attempting to get the position of an entity that doesn't belong to the
- * sparse set results in undefined behavior.
- *
- * @param entt A valid identifier.
- * @return The position of the entity in the sparse set.
- */
- [[nodiscard]] size_type index(const entity_type entt) const noexcept {
- ENTT_ASSERT(contains(entt), "Set does not contain entity");
- return entity_to_pos(sparse_ref(entt));
- }
- /**
- * @brief Returns the entity at specified location.
- * @param pos The position for which to return the entity.
- * @return The entity at specified location.
- */
- [[nodiscard]] entity_type operator[](const size_type pos) const noexcept {
- ENTT_ASSERT(pos < packed.size(), "Index out of bounds");
- return packed[pos];
- }
- /**
- * @brief Returns the element assigned to an entity, if any.
- *
- * @warning
- * Attempting to use an entity that doesn't belong to the sparse set results
- * in undefined behavior.
- *
- * @param entt A valid identifier.
- * @return An opaque pointer to the element assigned to the entity, if any.
- */
- [[nodiscard]] const void *value(const entity_type entt) const noexcept {
- return get_at(index(entt));
- }
- /*! @copydoc value */
- [[nodiscard]] void *value(const entity_type entt) noexcept {
- return const_cast<void *>(std::as_const(*this).value(entt));
- }
- /**
- * @brief Assigns an entity to a sparse set.
- *
- * @warning
- * Attempting to assign an entity that already belongs to the sparse set
- * results in undefined behavior.
- *
- * @param entt A valid identifier.
- * @param elem Optional opaque element to forward to mixins, if any.
- * @return Iterator pointing to the emplaced element in case of success, the
- * `end()` iterator otherwise.
- */
- iterator push(const entity_type entt, const void *elem = nullptr) {
- return try_emplace(entt, false, elem);
- }
- /**
- * @brief Assigns one or more entities to a sparse set.
- *
- * @warning
- * Attempting to assign an entity that already belongs to the sparse set
- * results in undefined behavior.
- *
- * @tparam It Type of input iterator.
- * @param first An iterator to the first element of the range of entities.
- * @param last An iterator past the last element of the range of entities.
- * @return Iterator pointing to the first element inserted in case of
- * success, the `end()` iterator otherwise.
- */
- template<typename It>
- iterator push(It first, It last) {
- auto curr = end();
- for(; first != last; ++first) {
- curr = try_emplace(*first, true);
- }
- return curr;
- }
- /**
- * @brief Bump the version number of an entity.
- *
- * @warning
- * Attempting to bump the version of an entity that doesn't belong to the
- * sparse set results in undefined behavior.
- *
- * @param entt A valid identifier.
- * @return The version of the given identifier.
- */
- version_type bump(const entity_type entt) {
- auto &elem = sparse_ref(entt);
- ENTT_ASSERT(entt != null && elem != tombstone, "Cannot set the required version");
- elem = traits_type::combine(traits_type::to_integral(elem), traits_type::to_integral(entt));
- packed[entity_to_pos(elem)] = entt;
- return traits_type::to_version(entt);
- }
- /**
- * @brief Erases an entity from a sparse set.
- *
- * @warning
- * Attempting to erase an entity that doesn't belong to the sparse set
- * results in undefined behavior.
- *
- * @param entt A valid identifier.
- */
- void erase(const entity_type entt) {
- const auto it = to_iterator(entt);
- pop(it, it + 1u);
- }
- /**
- * @brief Erases entities from a set.
- *
- * @sa erase
- *
- * @tparam It Type of input iterator.
- * @param first An iterator to the first element of the range of entities.
- * @param last An iterator past the last element of the range of entities.
- */
- template<typename It>
- void erase(It first, It last) {
- if constexpr(std::is_same_v<It, basic_iterator>) {
- pop(first, last);
- } else {
- for(; first != last; ++first) {
- erase(*first);
- }
- }
- }
- /**
- * @brief Removes an entity from a sparse set if it exists.
- * @param entt A valid identifier.
- * @return True if the entity is actually removed, false otherwise.
- */
- bool remove(const entity_type entt) {
- return contains(entt) && (erase(entt), true);
- }
- /**
- * @brief Removes entities from a sparse set if they exist.
- * @tparam It Type of input iterator.
- * @param first An iterator to the first element of the range of entities.
- * @param last An iterator past the last element of the range of entities.
- * @return The number of entities actually removed.
- */
- template<typename It>
- size_type remove(It first, It last) {
- size_type count{};
- if constexpr(std::is_same_v<It, basic_iterator>) {
- while(first != last) {
- while(first != last && !contains(*first)) {
- ++first;
- }
- const auto it = first;
- while(first != last && contains(*first)) {
- ++first;
- }
- count += static_cast<size_type>(std::distance(it, first));
- erase(it, first);
- }
- } else {
- for(; first != last; ++first) {
- count += remove(*first);
- }
- }
- return count;
- }
- /*! @brief Removes all tombstones from a sparse set. */
- void compact() {
- if(mode == deletion_policy::in_place) {
- size_type from = packed.size();
- size_type pos = std::exchange(head, max_size);
- for(; from && packed[from - 1u] == tombstone; --from) {}
- while(pos != max_size) {
- if(const auto to = std::exchange(pos, entity_to_pos(packed[pos])); to < from) {
- --from;
- swap_or_move(from, to);
- packed[to] = packed[from];
- const auto elem = static_cast<typename traits_type::entity_type>(to);
- sparse_ref(packed[to]) = traits_type::combine(elem, traits_type::to_integral(packed[to]));
- for(; from && packed[from - 1u] == tombstone; --from) {}
- }
- }
- packed.erase(packed.begin() + static_cast<difference_type>(from), packed.end());
- }
- }
- /**
- * @brief Swaps two entities in a sparse set.
- *
- * For what it's worth, this function affects both the internal sparse array
- * and the internal packed array. Users should not care of that anyway.
- *
- * @warning
- * Attempting to swap entities that don't belong to the sparse set results
- * in undefined behavior.
- *
- * @param lhs A valid identifier.
- * @param rhs A valid identifier.
- */
- void swap_elements(const entity_type lhs, const entity_type rhs) {
- const auto from = index(lhs);
- const auto to = index(rhs);
- // basic no-leak guarantee if swapping throws
- swap_or_move(from, to);
- swap_at(from, to);
- }
- /**
- * @brief Sort the first count elements according to the given comparison
- * function.
- *
- * The comparison function object must return `true` if the first element
- * is _less_ than the second one, `false` otherwise. The signature of the
- * comparison function should be equivalent to the following:
- *
- * @code{.cpp}
- * bool(const Entity, const Entity);
- * @endcode
- *
- * Moreover, the comparison function object shall induce a
- * _strict weak ordering_ on the values.
- *
- * The sort function object must offer a member function template
- * `operator()` that accepts three arguments:
- *
- * * An iterator to the first element of the range to sort.
- * * An iterator past the last element of the range to sort.
- * * A comparison function to use to compare the elements.
- *
- * @tparam Compare Type of comparison function object.
- * @tparam Sort Type of sort function object.
- * @tparam Args Types of arguments to forward to the sort function object.
- * @param length Number of elements to sort.
- * @param compare A valid comparison function object.
- * @param algo A valid sort function object.
- * @param args Arguments to forward to the sort function object, if any.
- */
- template<typename Compare, typename Sort = std_sort, typename... Args>
- void sort_n(const size_type length, Compare compare, Sort algo = Sort{}, Args &&...args) {
- ENTT_ASSERT((mode != deletion_policy::in_place) || (head == max_size), "Sorting with tombstones not allowed");
- ENTT_ASSERT(!(length > packed.size()), "Length exceeds the number of elements");
- algo(packed.rend() - static_cast<difference_type>(length), packed.rend(), std::move(compare), std::forward<Args>(args)...);
- for(size_type pos{}; pos < length; ++pos) {
- auto curr = pos;
- auto next = index(packed[curr]);
- while(curr != next) {
- const auto idx = index(packed[next]);
- const auto entt = packed[curr];
- swap_or_move(next, idx);
- const auto elem = static_cast<typename traits_type::entity_type>(curr);
- sparse_ref(entt) = traits_type::combine(elem, traits_type::to_integral(packed[curr]));
- curr = std::exchange(next, idx);
- }
- }
- }
- /**
- * @brief Sort all elements according to the given comparison function.
- *
- * @sa sort_n
- *
- * @tparam Compare Type of comparison function object.
- * @tparam Sort Type of sort function object.
- * @tparam Args Types of arguments to forward to the sort function object.
- * @param compare A valid comparison function object.
- * @param algo A valid sort function object.
- * @param args Arguments to forward to the sort function object, if any.
- */
- template<typename Compare, typename Sort = std_sort, typename... Args>
- void sort(Compare compare, Sort algo = Sort{}, Args &&...args) {
- const size_type len = (mode == deletion_policy::swap_only) ? head : packed.size();
- sort_n(len, std::move(compare), std::move(algo), std::forward<Args>(args)...);
- }
- /**
- * @brief Sort entities according to their order in a range.
- *
- * Entities that are part of both the sparse set and the range are ordered
- * internally according to the order they have in the range.<br/>
- * All other entities goes to the end of the sparse set and there are no
- * guarantees on their order.
- *
- * @tparam It Type of input iterator.
- * @param first An iterator to the first element of the range of entities.
- * @param last An iterator past the last element of the range of entities.
- * @return An iterator past the last of the elements actually shared.
- */
- template<typename It>
- iterator sort_as(It first, It last) {
- ENTT_ASSERT((mode != deletion_policy::in_place) || (head == max_size), "Sorting with tombstones not allowed");
- const size_type len = (mode == deletion_policy::swap_only) ? head : packed.size();
- auto it = end() - static_cast<difference_type>(len);
- for(const auto other = end(); (it != other) && (first != last); ++first) {
- if(const auto curr = *first; contains(curr)) {
- if(const auto entt = *it; entt != curr) {
- // basic no-leak guarantee (with invalid state) if swapping throws
- swap_elements(entt, curr);
- }
- ++it;
- }
- }
- return it;
- }
- /*! @brief Clears a sparse set. */
- void clear() {
- pop_all();
- // sanity check to avoid subtle issues due to storage classes
- ENTT_ASSERT((compact(), size()) == 0u, "Non-empty set");
- head = policy_to_head();
- packed.clear();
- }
- /**
- * @brief Returns a type info object for the value type, if any.
- * @return A type info object for the value type, if any.
- */
- [[nodiscard]] const type_info &info() const noexcept {
- return *descriptor;
- }
- /*! @copydoc info */
- [[deprecated("use ::info instead")]] [[nodiscard]] const type_info &type() const noexcept {
- return info();
- }
- /**
- * @brief Forwards variables to derived classes, if any.
- * @tparam Type Type of the element to forward.
- * @param value The element to forward.
- */
- template<typename Type>
- void bind(Type &&value) noexcept {
- bind_any(forward_as_any(std::forward<Type>(value)));
- }
- private:
- sparse_container_type sparse;
- packed_container_type packed;
- const type_info *descriptor;
- deletion_policy mode;
- size_type head;
- };
- } // namespace entt
- #endif
- // #include "entity/storage.hpp"
- #ifndef ENTT_ENTITY_STORAGE_HPP
- #define ENTT_ENTITY_STORAGE_HPP
- #include <cstddef>
- #include <iterator>
- #include <memory>
- #include <tuple>
- #include <type_traits>
- #include <utility>
- #include <vector>
- // #include "../config/config.h"
- // #include "../core/bit.hpp"
- // #include "../core/iterator.hpp"
- // #include "../core/memory.hpp"
- // #include "../core/type_info.hpp"
- // #include "component.hpp"
- // #include "entity.hpp"
- // #include "fwd.hpp"
- // #include "sparse_set.hpp"
- namespace entt {
- /*! @cond TURN_OFF_DOXYGEN */
- namespace internal {
- template<typename Container, auto Page>
- class storage_iterator final {
- friend storage_iterator<const Container, Page>;
- using container_type = std::remove_const_t<Container>;
- using alloc_traits = std::allocator_traits<typename container_type::allocator_type>;
- using iterator_traits = std::iterator_traits<std::conditional_t<
- std::is_const_v<Container>,
- typename alloc_traits::template rebind_traits<typename std::pointer_traits<typename container_type::value_type>::element_type>::const_pointer,
- typename alloc_traits::template rebind_traits<typename std::pointer_traits<typename container_type::value_type>::element_type>::pointer>>;
- public:
- using value_type = typename iterator_traits::value_type;
- using pointer = typename iterator_traits::pointer;
- using reference = typename iterator_traits::reference;
- using difference_type = typename iterator_traits::difference_type;
- using iterator_category = std::random_access_iterator_tag;
- constexpr storage_iterator() noexcept = default;
- constexpr storage_iterator(Container *ref, const difference_type idx) noexcept
- : payload{ref},
- offset{idx} {}
- template<bool Const = std::is_const_v<Container>, typename = std::enable_if_t<Const>>
- constexpr storage_iterator(const storage_iterator<std::remove_const_t<Container>, Page> &other) noexcept
- : storage_iterator{other.payload, other.offset} {}
- constexpr storage_iterator &operator++() noexcept {
- return --offset, *this;
- }
- constexpr storage_iterator operator++(int) noexcept {
- const storage_iterator orig = *this;
- return ++(*this), orig;
- }
- constexpr storage_iterator &operator--() noexcept {
- return ++offset, *this;
- }
- constexpr storage_iterator operator--(int) noexcept {
- const storage_iterator orig = *this;
- return operator--(), orig;
- }
- constexpr storage_iterator &operator+=(const difference_type value) noexcept {
- offset -= value;
- return *this;
- }
- constexpr storage_iterator operator+(const difference_type value) const noexcept {
- storage_iterator copy = *this;
- return (copy += value);
- }
- constexpr storage_iterator &operator-=(const difference_type value) noexcept {
- return (*this += -value);
- }
- constexpr storage_iterator operator-(const difference_type value) const noexcept {
- return (*this + -value);
- }
- [[nodiscard]] constexpr reference operator[](const difference_type value) const noexcept {
- const auto pos = static_cast<typename Container::size_type>(index() - value);
- return (*payload)[pos / Page][fast_mod(static_cast<std::size_t>(pos), Page)];
- }
- [[nodiscard]] constexpr pointer operator->() const noexcept {
- return std::addressof(operator[](0));
- }
- [[nodiscard]] constexpr reference operator*() const noexcept {
- return operator[](0);
- }
- [[nodiscard]] constexpr difference_type index() const noexcept {
- return offset - 1;
- }
- private:
- Container *payload;
- difference_type offset;
- };
- template<typename Lhs, typename Rhs, auto Page>
- [[nodiscard]] constexpr std::ptrdiff_t operator-(const storage_iterator<Lhs, Page> &lhs, const storage_iterator<Rhs, Page> &rhs) noexcept {
- return rhs.index() - lhs.index();
- }
- template<typename Lhs, typename Rhs, auto Page>
- [[nodiscard]] constexpr bool operator==(const storage_iterator<Lhs, Page> &lhs, const storage_iterator<Rhs, Page> &rhs) noexcept {
- return lhs.index() == rhs.index();
- }
- template<typename Lhs, typename Rhs, auto Page>
- [[nodiscard]] constexpr bool operator!=(const storage_iterator<Lhs, Page> &lhs, const storage_iterator<Rhs, Page> &rhs) noexcept {
- return !(lhs == rhs);
- }
- template<typename Lhs, typename Rhs, auto Page>
- [[nodiscard]] constexpr bool operator<(const storage_iterator<Lhs, Page> &lhs, const storage_iterator<Rhs, Page> &rhs) noexcept {
- return lhs.index() > rhs.index();
- }
- template<typename Lhs, typename Rhs, auto Page>
- [[nodiscard]] constexpr bool operator>(const storage_iterator<Lhs, Page> &lhs, const storage_iterator<Rhs, Page> &rhs) noexcept {
- return rhs < lhs;
- }
- template<typename Lhs, typename Rhs, auto Page>
- [[nodiscard]] constexpr bool operator<=(const storage_iterator<Lhs, Page> &lhs, const storage_iterator<Rhs, Page> &rhs) noexcept {
- return !(lhs > rhs);
- }
- template<typename Lhs, typename Rhs, auto Page>
- [[nodiscard]] constexpr bool operator>=(const storage_iterator<Lhs, Page> &lhs, const storage_iterator<Rhs, Page> &rhs) noexcept {
- return !(lhs < rhs);
- }
- template<typename It, typename... Other>
- class extended_storage_iterator final {
- template<typename Iter, typename... Args>
- friend class extended_storage_iterator;
- public:
- using iterator_type = It;
- using value_type = decltype(std::tuple_cat(std::make_tuple(*std::declval<It>()), std::forward_as_tuple(*std::declval<Other>()...)));
- using pointer = input_iterator_pointer<value_type>;
- using reference = value_type;
- using difference_type = std::ptrdiff_t;
- using iterator_category = std::input_iterator_tag;
- using iterator_concept = std::forward_iterator_tag;
- constexpr extended_storage_iterator()
- : it{} {}
- constexpr extended_storage_iterator(iterator_type base, Other... other)
- : it{base, other...} {}
- template<typename... Args, typename = std::enable_if_t<(!std::is_same_v<Other, Args> && ...) && (std::is_constructible_v<Other, Args> && ...)>>
- constexpr extended_storage_iterator(const extended_storage_iterator<It, Args...> &other)
- : it{other.it} {}
- constexpr extended_storage_iterator &operator++() noexcept {
- return ++std::get<It>(it), (++std::get<Other>(it), ...), *this;
- }
- constexpr extended_storage_iterator operator++(int) noexcept {
- const extended_storage_iterator orig = *this;
- return ++(*this), orig;
- }
- [[nodiscard]] constexpr pointer operator->() const noexcept {
- return operator*();
- }
- [[nodiscard]] constexpr reference operator*() const noexcept {
- return {*std::get<It>(it), *std::get<Other>(it)...};
- }
- [[nodiscard]] constexpr iterator_type base() const noexcept {
- return std::get<It>(it);
- }
- template<typename... Lhs, typename... Rhs>
- friend constexpr bool operator==(const extended_storage_iterator<Lhs...> &, const extended_storage_iterator<Rhs...> &) noexcept;
- private:
- std::tuple<It, Other...> it;
- };
- template<typename... Lhs, typename... Rhs>
- [[nodiscard]] constexpr bool operator==(const extended_storage_iterator<Lhs...> &lhs, const extended_storage_iterator<Rhs...> &rhs) noexcept {
- return std::get<0>(lhs.it) == std::get<0>(rhs.it);
- }
- template<typename... Lhs, typename... Rhs>
- [[nodiscard]] constexpr bool operator!=(const extended_storage_iterator<Lhs...> &lhs, const extended_storage_iterator<Rhs...> &rhs) noexcept {
- return !(lhs == rhs);
- }
- } // namespace internal
- /*! @endcond */
- /**
- * @brief Storage implementation.
- *
- * Internal data structures arrange elements to maximize performance. There are
- * no guarantees that objects are returned in the insertion order when iterate
- * a storage. Do not make assumption on the order in any case.
- *
- * @warning
- * Empty types aren't explicitly instantiated. Therefore, many of the functions
- * normally available for non-empty types will not be available for empty ones.
- *
- * @tparam Type Element type.
- * @tparam Entity A valid entity type.
- * @tparam Allocator Type of allocator used to manage memory and elements.
- */
- template<typename Type, typename Entity, typename Allocator, typename>
- class basic_storage: public basic_sparse_set<Entity, typename std::allocator_traits<Allocator>::template rebind_alloc<Entity>> {
- using alloc_traits = std::allocator_traits<Allocator>;
- static_assert(std::is_same_v<typename alloc_traits::value_type, Type>, "Invalid value type");
- using container_type = std::vector<typename alloc_traits::pointer, typename alloc_traits::template rebind_alloc<typename alloc_traits::pointer>>;
- using underlying_type = basic_sparse_set<Entity, typename alloc_traits::template rebind_alloc<Entity>>;
- using underlying_iterator = typename underlying_type::basic_iterator;
- using traits_type = component_traits<Type, Entity>;
- [[nodiscard]] auto &element_at(const std::size_t pos) const {
- return payload[pos / traits_type::page_size][fast_mod(pos, traits_type::page_size)];
- }
- auto assure_at_least(const std::size_t pos) {
- const auto idx = pos / traits_type::page_size;
- if(!(idx < payload.size())) {
- auto curr = payload.size();
- allocator_type allocator{get_allocator()};
- payload.resize(idx + 1u, nullptr);
- ENTT_TRY {
- for(const auto last = payload.size(); curr < last; ++curr) {
- payload[curr] = alloc_traits::allocate(allocator, traits_type::page_size);
- }
- }
- ENTT_CATCH {
- payload.resize(curr);
- ENTT_THROW;
- }
- }
- return payload[idx] + fast_mod(pos, traits_type::page_size);
- }
- template<typename... Args>
- auto emplace_element(const Entity entt, const bool force_back, Args &&...args) {
- const auto it = base_type::try_emplace(entt, force_back);
- ENTT_TRY {
- auto *elem = to_address(assure_at_least(static_cast<size_type>(it.index())));
- entt::uninitialized_construct_using_allocator(elem, get_allocator(), std::forward<Args>(args)...);
- }
- ENTT_CATCH {
- base_type::pop(it, it + 1u);
- ENTT_THROW;
- }
- return it;
- }
- void shrink_to_size(const std::size_t sz) {
- const auto from = (sz + traits_type::page_size - 1u) / traits_type::page_size;
- allocator_type allocator{get_allocator()};
- for(auto pos = sz, length = base_type::size(); pos < length; ++pos) {
- if constexpr(traits_type::in_place_delete) {
- if(base_type::data()[pos] != tombstone) {
- alloc_traits::destroy(allocator, std::addressof(element_at(pos)));
- }
- } else {
- alloc_traits::destroy(allocator, std::addressof(element_at(pos)));
- }
- }
- for(auto pos = from, last = payload.size(); pos < last; ++pos) {
- alloc_traits::deallocate(allocator, payload[pos], traits_type::page_size);
- }
- payload.resize(from);
- payload.shrink_to_fit();
- }
- void swap_at(const std::size_t lhs, const std::size_t rhs) {
- using std::swap;
- swap(element_at(lhs), element_at(rhs));
- }
- void move_to(const std::size_t lhs, const std::size_t rhs) {
- auto &elem = element_at(lhs);
- allocator_type allocator{get_allocator()};
- entt::uninitialized_construct_using_allocator(to_address(assure_at_least(rhs)), allocator, std::move(elem));
- alloc_traits::destroy(allocator, std::addressof(elem));
- }
- private:
- [[nodiscard]] const void *get_at(const std::size_t pos) const final {
- return std::addressof(element_at(pos));
- }
- void swap_or_move([[maybe_unused]] const std::size_t from, [[maybe_unused]] const std::size_t to) override {
- static constexpr bool is_pinned_type = !(std::is_move_constructible_v<Type> && std::is_move_assignable_v<Type>);
- // use a runtime value to avoid compile-time suppression that drives the code coverage tool crazy
- ENTT_ASSERT((from + 1u) && !is_pinned_type, "Pinned type");
- if constexpr(!is_pinned_type) {
- if constexpr(traits_type::in_place_delete) {
- (base_type::operator[](to) == tombstone) ? move_to(from, to) : swap_at(from, to);
- } else {
- swap_at(from, to);
- }
- }
- }
- protected:
- /**
- * @brief Erases entities from a storage.
- * @param first An iterator to the first element of the range of entities.
- * @param last An iterator past the last element of the range of entities.
- */
- void pop(underlying_iterator first, underlying_iterator last) override {
- for(allocator_type allocator{get_allocator()}; first != last; ++first) {
- // cannot use first.index() because it would break with cross iterators
- auto &elem = element_at(base_type::index(*first));
- if constexpr(traits_type::in_place_delete) {
- base_type::in_place_pop(first);
- alloc_traits::destroy(allocator, std::addressof(elem));
- } else {
- auto &other = element_at(base_type::size() - 1u);
- // destroying on exit allows reentrant destructors
- [[maybe_unused]] auto unused = std::exchange(elem, std::move(other));
- alloc_traits::destroy(allocator, std::addressof(other));
- base_type::swap_and_pop(first);
- }
- }
- }
- /*! @brief Erases all entities of a storage. */
- void pop_all() override {
- allocator_type allocator{get_allocator()};
- for(auto first = base_type::begin(); !(first.index() < 0); ++first) {
- if constexpr(traits_type::in_place_delete) {
- if(*first != tombstone) {
- base_type::in_place_pop(first);
- alloc_traits::destroy(allocator, std::addressof(element_at(static_cast<size_type>(first.index()))));
- }
- } else {
- base_type::swap_and_pop(first);
- alloc_traits::destroy(allocator, std::addressof(element_at(static_cast<size_type>(first.index()))));
- }
- }
- }
- /**
- * @brief Assigns an entity to a storage.
- * @param entt A valid identifier.
- * @param value Optional opaque value.
- * @param force_back Force back insertion.
- * @return Iterator pointing to the emplaced element.
- */
- underlying_iterator try_emplace([[maybe_unused]] const Entity entt, [[maybe_unused]] const bool force_back, const void *value) override {
- if(value != nullptr) {
- if constexpr(std::is_copy_constructible_v<element_type>) {
- return emplace_element(entt, force_back, *static_cast<const element_type *>(value));
- } else {
- return base_type::end();
- }
- } else {
- if constexpr(std::is_default_constructible_v<element_type>) {
- return emplace_element(entt, force_back);
- } else {
- return base_type::end();
- }
- }
- }
- public:
- /*! @brief Allocator type. */
- using allocator_type = Allocator;
- /*! @brief Base type. */
- using base_type = underlying_type;
- /*! @brief Element type. */
- using element_type = Type;
- /*! @brief Type of the objects assigned to entities. */
- using value_type = element_type;
- /*! @brief Underlying entity identifier. */
- using entity_type = Entity;
- /*! @brief Unsigned integer type. */
- using size_type = std::size_t;
- /*! @brief Signed integer type. */
- using difference_type = std::ptrdiff_t;
- /*! @brief Pointer type to contained elements. */
- using pointer = typename container_type::pointer;
- /*! @brief Constant pointer type to contained elements. */
- using const_pointer = typename alloc_traits::template rebind_traits<typename alloc_traits::const_pointer>::const_pointer;
- /*! @brief Random access iterator type. */
- using iterator = internal::storage_iterator<container_type, traits_type::page_size>;
- /*! @brief Constant random access iterator type. */
- using const_iterator = internal::storage_iterator<const container_type, traits_type::page_size>;
- /*! @brief Reverse iterator type. */
- using reverse_iterator = std::reverse_iterator<iterator>;
- /*! @brief Constant reverse iterator type. */
- using const_reverse_iterator = std::reverse_iterator<const_iterator>;
- /*! @brief Extended iterable storage proxy. */
- using iterable = iterable_adaptor<internal::extended_storage_iterator<typename base_type::iterator, iterator>>;
- /*! @brief Constant extended iterable storage proxy. */
- using const_iterable = iterable_adaptor<internal::extended_storage_iterator<typename base_type::const_iterator, const_iterator>>;
- /*! @brief Extended reverse iterable storage proxy. */
- using reverse_iterable = iterable_adaptor<internal::extended_storage_iterator<typename base_type::reverse_iterator, reverse_iterator>>;
- /*! @brief Constant extended reverse iterable storage proxy. */
- using const_reverse_iterable = iterable_adaptor<internal::extended_storage_iterator<typename base_type::const_reverse_iterator, const_reverse_iterator>>;
- /*! @brief Storage deletion policy. */
- static constexpr deletion_policy storage_policy{traits_type::in_place_delete};
- /*! @brief Default constructor. */
- basic_storage()
- : basic_storage{allocator_type{}} {}
- /**
- * @brief Constructs an empty storage with a given allocator.
- * @param allocator The allocator to use.
- */
- explicit basic_storage(const allocator_type &allocator)
- : base_type{type_id<element_type>(), storage_policy, allocator},
- payload{allocator} {}
- /*! @brief Default copy constructor, deleted on purpose. */
- basic_storage(const basic_storage &) = delete;
- /**
- * @brief Move constructor.
- * @param other The instance to move from.
- */
- basic_storage(basic_storage &&other) noexcept
- : base_type{static_cast<base_type &&>(other)},
- payload{std::move(other.payload)} {}
- /**
- * @brief Allocator-extended move constructor.
- * @param other The instance to move from.
- * @param allocator The allocator to use.
- */
- basic_storage(basic_storage &&other, const allocator_type &allocator)
- : base_type{static_cast<base_type &&>(other), allocator},
- payload{std::move(other.payload), allocator} {
- ENTT_ASSERT(alloc_traits::is_always_equal::value || get_allocator() == other.get_allocator(), "Copying a storage is not allowed");
- }
- /*! @brief Default destructor. */
- // NOLINTNEXTLINE(bugprone-exception-escape)
- ~basic_storage() override {
- shrink_to_size(0u);
- }
- /**
- * @brief Default copy assignment operator, deleted on purpose.
- * @return This storage.
- */
- basic_storage &operator=(const basic_storage &) = delete;
- /**
- * @brief Move assignment operator.
- * @param other The instance to move from.
- * @return This storage.
- */
- basic_storage &operator=(basic_storage &&other) noexcept {
- ENTT_ASSERT(alloc_traits::is_always_equal::value || get_allocator() == other.get_allocator(), "Copying a storage is not allowed");
- swap(other);
- return *this;
- }
- /**
- * @brief Exchanges the contents with those of a given storage.
- * @param other Storage to exchange the content with.
- */
- void swap(basic_storage &other) noexcept {
- using std::swap;
- swap(payload, other.payload);
- base_type::swap(other);
- }
- /**
- * @brief Returns the associated allocator.
- * @return The associated allocator.
- */
- [[nodiscard]] constexpr allocator_type get_allocator() const noexcept {
- return payload.get_allocator();
- }
- /**
- * @brief Increases the capacity of a storage.
- *
- * If the new capacity is greater than the current capacity, new storage is
- * allocated, otherwise the method does nothing.
- *
- * @param cap Desired capacity.
- */
- void reserve(const size_type cap) override {
- if(cap != 0u) {
- base_type::reserve(cap);
- assure_at_least(cap - 1u);
- }
- }
- /**
- * @brief Returns the number of elements that a storage has currently
- * allocated space for.
- * @return Capacity of the storage.
- */
- [[nodiscard]] size_type capacity() const noexcept override {
- return payload.size() * traits_type::page_size;
- }
- /*! @brief Requests the removal of unused capacity. */
- void shrink_to_fit() override {
- base_type::shrink_to_fit();
- shrink_to_size(base_type::size());
- }
- /**
- * @brief Direct access to the array of objects.
- * @return A pointer to the array of objects.
- */
- [[nodiscard]] const_pointer raw() const noexcept {
- return payload.data();
- }
- /*! @copydoc raw */
- [[nodiscard]] pointer raw() noexcept {
- return payload.data();
- }
- /**
- * @brief Returns an iterator to the beginning.
- *
- * If the storage is empty, the returned iterator will be equal to `end()`.
- *
- * @return An iterator to the first instance of the internal array.
- */
- [[nodiscard]] const_iterator cbegin() const noexcept {
- const auto pos = static_cast<difference_type>(base_type::size());
- return const_iterator{&payload, pos};
- }
- /*! @copydoc cbegin */
- [[nodiscard]] const_iterator begin() const noexcept {
- return cbegin();
- }
- /*! @copydoc begin */
- [[nodiscard]] iterator begin() noexcept {
- const auto pos = static_cast<difference_type>(base_type::size());
- return iterator{&payload, pos};
- }
- /**
- * @brief Returns an iterator to the end.
- * @return An iterator to the element following the last instance of the
- * internal array.
- */
- [[nodiscard]] const_iterator cend() const noexcept {
- return const_iterator{&payload, {}};
- }
- /*! @copydoc cend */
- [[nodiscard]] const_iterator end() const noexcept {
- return cend();
- }
- /*! @copydoc end */
- [[nodiscard]] iterator end() noexcept {
- return iterator{&payload, {}};
- }
- /**
- * @brief Returns a reverse iterator to the beginning.
- *
- * If the storage is empty, the returned iterator will be equal to `rend()`.
- *
- * @return An iterator to the first instance of the reversed internal array.
- */
- [[nodiscard]] const_reverse_iterator crbegin() const noexcept {
- return std::make_reverse_iterator(cend());
- }
- /*! @copydoc crbegin */
- [[nodiscard]] const_reverse_iterator rbegin() const noexcept {
- return crbegin();
- }
- /*! @copydoc rbegin */
- [[nodiscard]] reverse_iterator rbegin() noexcept {
- return std::make_reverse_iterator(end());
- }
- /**
- * @brief Returns a reverse iterator to the end.
- * @return An iterator to the element following the last instance of the
- * reversed internal array.
- */
- [[nodiscard]] const_reverse_iterator crend() const noexcept {
- return std::make_reverse_iterator(cbegin());
- }
- /*! @copydoc crend */
- [[nodiscard]] const_reverse_iterator rend() const noexcept {
- return crend();
- }
- /*! @copydoc rend */
- [[nodiscard]] reverse_iterator rend() noexcept {
- return std::make_reverse_iterator(begin());
- }
- /**
- * @brief Returns the object assigned to an entity.
- *
- * @warning
- * Attempting to use an entity that doesn't belong to the storage results in
- * undefined behavior.
- *
- * @param entt A valid identifier.
- * @return The object assigned to the entity.
- */
- [[nodiscard]] const value_type &get(const entity_type entt) const noexcept {
- return element_at(base_type::index(entt));
- }
- /*! @copydoc get */
- [[nodiscard]] value_type &get(const entity_type entt) noexcept {
- return const_cast<value_type &>(std::as_const(*this).get(entt));
- }
- /**
- * @brief Returns the object assigned to an entity as a tuple.
- * @param entt A valid identifier.
- * @return The object assigned to the entity as a tuple.
- */
- [[nodiscard]] std::tuple<const value_type &> get_as_tuple(const entity_type entt) const noexcept {
- return std::forward_as_tuple(get(entt));
- }
- /*! @copydoc get_as_tuple */
- [[nodiscard]] std::tuple<value_type &> get_as_tuple(const entity_type entt) noexcept {
- return std::forward_as_tuple(get(entt));
- }
- /**
- * @brief Assigns an entity to a storage and constructs its object.
- *
- * @warning
- * Attempting to use an entity that already belongs to the storage results
- * in undefined behavior.
- *
- * @tparam Args Types of arguments to use to construct the object.
- * @param entt A valid identifier.
- * @param args Parameters to use to construct an object for the entity.
- * @return A reference to the newly created object.
- */
- template<typename... Args>
- value_type &emplace(const entity_type entt, Args &&...args) {
- if constexpr(std::is_aggregate_v<value_type> && (sizeof...(Args) != 0u || !std::is_default_constructible_v<value_type>)) {
- const auto it = emplace_element(entt, false, Type{std::forward<Args>(args)...});
- return element_at(static_cast<size_type>(it.index()));
- } else {
- const auto it = emplace_element(entt, false, std::forward<Args>(args)...);
- return element_at(static_cast<size_type>(it.index()));
- }
- }
- /**
- * @brief Updates the instance assigned to a given entity in-place.
- * @tparam Func Types of the function objects to invoke.
- * @param entt A valid identifier.
- * @param func Valid function objects.
- * @return A reference to the updated instance.
- */
- template<typename... Func>
- value_type &patch(const entity_type entt, Func &&...func) {
- const auto idx = base_type::index(entt);
- auto &elem = element_at(idx);
- (std::forward<Func>(func)(elem), ...);
- return elem;
- }
- /**
- * @brief Assigns one or more entities to a storage and constructs their
- * objects from a given instance.
- *
- * @warning
- * Attempting to assign an entity that already belongs to the storage
- * results in undefined behavior.
- *
- * @tparam It Type of input iterator.
- * @param first An iterator to the first element of the range of entities.
- * @param last An iterator past the last element of the range of entities.
- * @param value An instance of the object to construct.
- * @return Iterator pointing to the first element inserted, if any.
- */
- template<typename It>
- iterator insert(It first, It last, const value_type &value = {}) {
- for(; first != last; ++first) {
- emplace_element(*first, true, value);
- }
- return begin();
- }
- /**
- * @brief Assigns one or more entities to a storage and constructs their
- * objects from a given range.
- *
- * @sa construct
- *
- * @tparam EIt Type of input iterator.
- * @tparam CIt Type of input iterator.
- * @param first An iterator to the first element of the range of entities.
- * @param last An iterator past the last element of the range of entities.
- * @param from An iterator to the first element of the range of objects.
- * @return Iterator pointing to the first element inserted, if any.
- */
- template<typename EIt, typename CIt, typename = std::enable_if_t<std::is_same_v<typename std::iterator_traits<CIt>::value_type, value_type>>>
- iterator insert(EIt first, EIt last, CIt from) {
- for(; first != last; ++first, ++from) {
- emplace_element(*first, true, *from);
- }
- return begin();
- }
- /**
- * @brief Returns an iterable object to use to _visit_ a storage.
- *
- * The iterable object returns a tuple that contains the current entity and
- * a reference to its element.
- *
- * @return An iterable object to use to _visit_ the storage.
- */
- [[nodiscard]] iterable each() noexcept {
- return iterable{{base_type::begin(), begin()}, {base_type::end(), end()}};
- }
- /*! @copydoc each */
- [[nodiscard]] const_iterable each() const noexcept {
- return const_iterable{{base_type::cbegin(), cbegin()}, {base_type::cend(), cend()}};
- }
- /**
- * @brief Returns a reverse iterable object to use to _visit_ a storage.
- *
- * @sa each
- *
- * @return A reverse iterable object to use to _visit_ the storage.
- */
- [[nodiscard]] reverse_iterable reach() noexcept {
- return reverse_iterable{{base_type::rbegin(), rbegin()}, {base_type::rend(), rend()}};
- }
- /*! @copydoc reach */
- [[nodiscard]] const_reverse_iterable reach() const noexcept {
- return const_reverse_iterable{{base_type::crbegin(), crbegin()}, {base_type::crend(), crend()}};
- }
- private:
- container_type payload;
- };
- /*! @copydoc basic_storage */
- template<typename Type, typename Entity, typename Allocator>
- class basic_storage<Type, Entity, Allocator, std::enable_if_t<component_traits<Type, Entity>::page_size == 0u>>
- : public basic_sparse_set<Entity, typename std::allocator_traits<Allocator>::template rebind_alloc<Entity>> {
- using alloc_traits = std::allocator_traits<Allocator>;
- static_assert(std::is_same_v<typename alloc_traits::value_type, Type>, "Invalid value type");
- using traits_type = component_traits<Type, Entity>;
- public:
- /*! @brief Allocator type. */
- using allocator_type = Allocator;
- /*! @brief Base type. */
- using base_type = basic_sparse_set<Entity, typename alloc_traits::template rebind_alloc<Entity>>;
- /*! @brief Element type. */
- using element_type = Type;
- /*! @brief Type of the objects assigned to entities. */
- using value_type = void;
- /*! @brief Underlying entity identifier. */
- using entity_type = Entity;
- /*! @brief Unsigned integer type. */
- using size_type = std::size_t;
- /*! @brief Signed integer type. */
- using difference_type = std::ptrdiff_t;
- /*! @brief Extended iterable storage proxy. */
- using iterable = iterable_adaptor<internal::extended_storage_iterator<typename base_type::iterator>>;
- /*! @brief Constant extended iterable storage proxy. */
- using const_iterable = iterable_adaptor<internal::extended_storage_iterator<typename base_type::const_iterator>>;
- /*! @brief Extended reverse iterable storage proxy. */
- using reverse_iterable = iterable_adaptor<internal::extended_storage_iterator<typename base_type::reverse_iterator>>;
- /*! @brief Constant extended reverse iterable storage proxy. */
- using const_reverse_iterable = iterable_adaptor<internal::extended_storage_iterator<typename base_type::const_reverse_iterator>>;
- /*! @brief Storage deletion policy. */
- static constexpr deletion_policy storage_policy{traits_type::in_place_delete};
- /*! @brief Default constructor. */
- basic_storage()
- : basic_storage{allocator_type{}} {}
- /**
- * @brief Constructs an empty container with a given allocator.
- * @param allocator The allocator to use.
- */
- explicit basic_storage(const allocator_type &allocator)
- : base_type{type_id<element_type>(), storage_policy, allocator} {}
- /*! @brief Default copy constructor, deleted on purpose. */
- basic_storage(const basic_storage &) = delete;
- /**
- * @brief Move constructor.
- * @param other The instance to move from.
- */
- basic_storage(basic_storage &&other) noexcept = default;
- /**
- * @brief Allocator-extended move constructor.
- * @param other The instance to move from.
- * @param allocator The allocator to use.
- */
- basic_storage(basic_storage &&other, const allocator_type &allocator)
- : base_type{std::move(other), allocator} {}
- /*! @brief Default destructor. */
- ~basic_storage() override = default;
- /**
- * @brief Default copy assignment operator, deleted on purpose.
- * @return This storage.
- */
- basic_storage &operator=(const basic_storage &) = delete;
- /**
- * @brief Move assignment operator.
- * @param other The instance to move from.
- * @return This storage.
- */
- basic_storage &operator=(basic_storage &&other) noexcept = default;
- /**
- * @brief Returns the associated allocator.
- * @return The associated allocator.
- */
- [[nodiscard]] constexpr allocator_type get_allocator() const noexcept {
- // std::allocator<void> has no cross constructors (waiting for C++20)
- if constexpr(std::is_void_v<element_type> && !std::is_constructible_v<allocator_type, typename base_type::allocator_type>) {
- return allocator_type{};
- } else {
- return allocator_type{base_type::get_allocator()};
- }
- }
- /**
- * @brief Returns the object assigned to an entity, that is `void`.
- *
- * @warning
- * Attempting to use an entity that doesn't belong to the storage results in
- * undefined behavior.
- *
- * @param entt A valid identifier.
- */
- void get([[maybe_unused]] const entity_type entt) const noexcept {
- ENTT_ASSERT(base_type::contains(entt), "Invalid entity");
- }
- /**
- * @brief Returns an empty tuple.
- * @param entt A valid identifier.
- * @return Returns an empty tuple.
- */
- [[nodiscard]] std::tuple<> get_as_tuple([[maybe_unused]] const entity_type entt) const noexcept {
- ENTT_ASSERT(base_type::contains(entt), "Invalid entity");
- return std::tuple{};
- }
- /**
- * @brief Assigns an entity to a storage and constructs its object.
- *
- * @warning
- * Attempting to use an entity that already belongs to the storage results
- * in undefined behavior.
- *
- * @param entt A valid identifier.
- */
- void emplace(const entity_type entt) {
- base_type::try_emplace(entt, false);
- }
- /**
- * @brief Updates the instance assigned to a given entity in-place.
- * @tparam Func Types of the function objects to invoke.
- * @param entt A valid identifier.
- * @param func Valid function objects.
- */
- template<typename... Func>
- void patch([[maybe_unused]] const entity_type entt, Func &&...func) {
- ENTT_ASSERT(base_type::contains(entt), "Invalid entity");
- (std::forward<Func>(func)(), ...);
- }
- /**
- * @brief Assigns entities to a storage.
- * @tparam It Type of input iterator.
- * @param first An iterator to the first element of the range of entities.
- * @param last An iterator past the last element of the range of entities.
- */
- template<typename It>
- void insert(It first, It last) {
- for(; first != last; ++first) {
- base_type::try_emplace(*first, true);
- }
- }
- /**
- * @brief Returns an iterable object to use to _visit_ a storage.
- *
- * The iterable object returns a tuple that contains the current entity.
- *
- * @return An iterable object to use to _visit_ the storage.
- */
- [[nodiscard]] iterable each() noexcept {
- return iterable{base_type::begin(), base_type::end()};
- }
- /*! @copydoc each */
- [[nodiscard]] const_iterable each() const noexcept {
- return const_iterable{base_type::cbegin(), base_type::cend()};
- }
- /**
- * @brief Returns a reverse iterable object to use to _visit_ a storage.
- *
- * @sa each
- *
- * @return A reverse iterable object to use to _visit_ the storage.
- */
- [[nodiscard]] reverse_iterable reach() noexcept {
- return reverse_iterable{{base_type::rbegin()}, {base_type::rend()}};
- }
- /*! @copydoc reach */
- [[nodiscard]] const_reverse_iterable reach() const noexcept {
- return const_reverse_iterable{{base_type::crbegin()}, {base_type::crend()}};
- }
- };
- /**
- * @brief Swap-only entity storage specialization.
- * @tparam Entity A valid entity type.
- * @tparam Allocator Type of allocator used to manage memory and elements.
- */
- template<typename Entity, typename Allocator>
- class basic_storage<Entity, Entity, Allocator>
- : public basic_sparse_set<Entity, Allocator> {
- using alloc_traits = std::allocator_traits<Allocator>;
- static_assert(std::is_same_v<typename alloc_traits::value_type, Entity>, "Invalid value type");
- using underlying_iterator = typename basic_sparse_set<Entity, Allocator>::basic_iterator;
- using traits_type = entt_traits<Entity>;
- auto from_placeholder() noexcept {
- const auto entt = traits_type::combine(static_cast<typename traits_type::entity_type>(placeholder), {});
- ENTT_ASSERT(entt != null, "No more entities available");
- placeholder += static_cast<size_type>(entt != null);
- return entt;
- }
- auto next() noexcept {
- entity_type entt = from_placeholder();
- while(base_type::current(entt) != traits_type::to_version(tombstone) && entt != null) {
- entt = from_placeholder();
- }
- return entt;
- }
- protected:
- /*! @brief Erases all entities of a storage. */
- void pop_all() override {
- base_type::pop_all();
- placeholder = {};
- }
- /**
- * @brief Assigns an entity to a storage.
- * @param hint A valid identifier.
- * @return Iterator pointing to the emplaced element.
- */
- underlying_iterator try_emplace(const Entity hint, const bool, const void *) override {
- return base_type::find(generate(hint));
- }
- public:
- /*! @brief Allocator type. */
- using allocator_type = Allocator;
- /*! @brief Base type. */
- using base_type = basic_sparse_set<Entity, Allocator>;
- /*! @brief Element type. */
- using element_type = Entity;
- /*! @brief Type of the objects assigned to entities. */
- using value_type = void;
- /*! @brief Underlying entity identifier. */
- using entity_type = Entity;
- /*! @brief Unsigned integer type. */
- using size_type = std::size_t;
- /*! @brief Signed integer type. */
- using difference_type = std::ptrdiff_t;
- /*! @brief Extended iterable storage proxy. */
- using iterable = iterable_adaptor<internal::extended_storage_iterator<typename base_type::iterator>>;
- /*! @brief Constant extended iterable storage proxy. */
- using const_iterable = iterable_adaptor<internal::extended_storage_iterator<typename base_type::const_iterator>>;
- /*! @brief Extended reverse iterable storage proxy. */
- using reverse_iterable = iterable_adaptor<internal::extended_storage_iterator<typename base_type::reverse_iterator>>;
- /*! @brief Constant extended reverse iterable storage proxy. */
- using const_reverse_iterable = iterable_adaptor<internal::extended_storage_iterator<typename base_type::const_reverse_iterator>>;
- /*! @brief Storage deletion policy. */
- static constexpr deletion_policy storage_policy = deletion_policy::swap_only;
- /*! @brief Default constructor. */
- basic_storage()
- : basic_storage{allocator_type{}} {
- }
- /**
- * @brief Constructs an empty container with a given allocator.
- * @param allocator The allocator to use.
- */
- explicit basic_storage(const allocator_type &allocator)
- : base_type{type_id<void>(), storage_policy, allocator} {}
- /*! @brief Default copy constructor, deleted on purpose. */
- basic_storage(const basic_storage &) = delete;
- /**
- * @brief Move constructor.
- * @param other The instance to move from.
- */
- // NOLINTNEXTLINE(cppcoreguidelines-rvalue-reference-param-not-moved)
- basic_storage(basic_storage &&other) noexcept
- : base_type{static_cast<base_type &&>(other)},
- placeholder{other.placeholder} {}
- /**
- * @brief Allocator-extended move constructor.
- * @param other The instance to move from.
- * @param allocator The allocator to use.
- */
- // NOLINTNEXTLINE(cppcoreguidelines-rvalue-reference-param-not-moved)
- basic_storage(basic_storage &&other, const allocator_type &allocator)
- : base_type{static_cast<base_type &&>(other), allocator},
- placeholder{other.placeholder} {}
- /*! @brief Default destructor. */
- ~basic_storage() override = default;
- /**
- * @brief Default copy assignment operator, deleted on purpose.
- * @return This storage.
- */
- basic_storage &operator=(const basic_storage &) = delete;
- /**
- * @brief Move assignment operator.
- * @param other The instance to move from.
- * @return This storage.
- */
- basic_storage &operator=(basic_storage &&other) noexcept {
- placeholder = other.placeholder;
- base_type::operator=(std::move(other));
- return *this;
- }
- /**
- * @brief Exchanges the contents with those of a given storage.
- * @param other Storage to exchange the content with.
- */
- void swap(basic_storage &other) noexcept {
- using std::swap;
- swap(placeholder, other.placeholder);
- base_type::swap(other);
- }
- /**
- * @brief Returns the object assigned to an entity, that is `void`.
- *
- * @warning
- * Attempting to use an entity that doesn't belong to the storage results in
- * undefined behavior.
- *
- * @param entt A valid identifier.
- */
- void get([[maybe_unused]] const entity_type entt) const noexcept {
- ENTT_ASSERT(base_type::index(entt) < base_type::free_list(), "The requested entity is not a live one");
- }
- /**
- * @brief Returns an empty tuple.
- * @param entt A valid identifier.
- * @return Returns an empty tuple.
- */
- [[nodiscard]] std::tuple<> get_as_tuple([[maybe_unused]] const entity_type entt) const noexcept {
- ENTT_ASSERT(base_type::index(entt) < base_type::free_list(), "The requested entity is not a live one");
- return std::tuple{};
- }
- /**
- * @brief Creates a new identifier or recycles a destroyed one.
- * @return A valid identifier.
- */
- entity_type generate() {
- const auto len = base_type::free_list();
- const auto entt = (len == base_type::size()) ? next() : base_type::data()[len];
- return *base_type::try_emplace(entt, true);
- }
- /**
- * @brief Creates a new identifier or recycles a destroyed one.
- *
- * If the requested identifier isn't in use, the suggested one is used.
- * Otherwise, a new identifier is returned.
- *
- * @param hint Required identifier.
- * @return A valid identifier.
- */
- entity_type generate(const entity_type hint) {
- if(hint != null && hint != tombstone) {
- if(const auto curr = traits_type::construct(traits_type::to_entity(hint), base_type::current(hint)); curr == tombstone || !(base_type::index(curr) < base_type::free_list())) {
- return *base_type::try_emplace(hint, true);
- }
- }
- return generate();
- }
- /**
- * @brief Assigns each element in a range an identifier.
- * @tparam It Type of mutable forward iterator.
- * @param first An iterator to the first element of the range to generate.
- * @param last An iterator past the last element of the range to generate.
- */
- template<typename It>
- void generate(It first, It last) {
- for(const auto sz = base_type::size(); first != last && base_type::free_list() != sz; ++first) {
- *first = *base_type::try_emplace(base_type::data()[base_type::free_list()], true);
- }
- for(; first != last; ++first) {
- *first = *base_type::try_emplace(next(), true);
- }
- }
- /**
- * @brief Updates a given identifier.
- * @tparam Func Types of the function objects to invoke.
- * @param entt A valid identifier.
- * @param func Valid function objects.
- */
- template<typename... Func>
- void patch([[maybe_unused]] const entity_type entt, Func &&...func) {
- ENTT_ASSERT(base_type::index(entt) < base_type::free_list(), "The requested entity is not a live one");
- (std::forward<Func>(func)(), ...);
- }
- /**
- * @brief Returns an iterable object to use to _visit_ a storage.
- *
- * The iterable object returns a tuple that contains the current entity.
- *
- * @return An iterable object to use to _visit_ the storage.
- */
- [[nodiscard]] iterable each() noexcept {
- return std::as_const(*this).each();
- }
- /*! @copydoc each */
- [[nodiscard]] const_iterable each() const noexcept {
- const auto it = base_type::cend();
- const auto offset = static_cast<difference_type>(base_type::free_list());
- return const_iterable{it - offset, it};
- }
- /**
- * @brief Returns a reverse iterable object to use to _visit_ a storage.
- *
- * @sa each
- *
- * @return A reverse iterable object to use to _visit_ the storage.
- */
- [[nodiscard]] reverse_iterable reach() noexcept {
- return std::as_const(*this).reach();
- }
- /*! @copydoc reach */
- [[nodiscard]] const_reverse_iterable reach() const noexcept {
- const auto it = base_type::crbegin();
- const auto offset = static_cast<difference_type>(base_type::free_list());
- return const_reverse_iterable{it, it + offset};
- }
- /**
- * @brief Sets the starting identifier for generation.
- *
- * The version is ignored, regardless of the value.
- *
- * @param hint A valid identifier.
- */
- void start_from(const entity_type hint) {
- placeholder = static_cast<size_type>(traits_type::to_entity(hint));
- }
- private:
- size_type placeholder{};
- };
- } // namespace entt
- #endif
- // #include "entity/view.hpp"
- #ifndef ENTT_ENTITY_VIEW_HPP
- #define ENTT_ENTITY_VIEW_HPP
- #include <array>
- #include <cstddef>
- #include <iterator>
- #include <tuple>
- #include <type_traits>
- #include <utility>
- // #include "../config/config.h"
- // #include "../core/iterator.hpp"
- // #include "../core/type_traits.hpp"
- // #include "entity.hpp"
- // #include "fwd.hpp"
- namespace entt {
- /*! @cond TURN_OFF_DOXYGEN */
- namespace internal {
- template<typename... Type>
- // NOLINTNEXTLINE(misc-redundant-expression)
- static constexpr bool tombstone_check_v = ((sizeof...(Type) == 1u) && ... && (Type::storage_policy == deletion_policy::in_place));
- template<typename Type>
- const Type *view_placeholder() {
- static_assert(std::is_same_v<std::remove_const_t<std::remove_reference_t<Type>>, Type>, "Unexpected type");
- static const Type placeholder{};
- return &placeholder;
- }
- template<typename It, typename Entity>
- [[nodiscard]] bool all_of(It first, const It last, const Entity entt) noexcept {
- for(; (first != last) && (*first)->contains(entt); ++first) {}
- return first == last;
- }
- template<typename It, typename Entity>
- [[nodiscard]] bool none_of(It first, const It last, const Entity entt) noexcept {
- for(; (first != last) && !(*first)->contains(entt); ++first) {}
- return first == last;
- }
- template<typename It>
- [[nodiscard]] bool fully_initialized(It first, const It last, const std::remove_pointer_t<typename std::iterator_traits<It>::value_type> *placeholder) noexcept {
- for(; (first != last) && *first != placeholder; ++first) {}
- return first == last;
- }
- template<typename Result, typename View, typename Other, std::size_t... GLhs, std::size_t... ELhs, std::size_t... GRhs, std::size_t... ERhs>
- [[nodiscard]] Result view_pack(const View &view, const Other &other, std::index_sequence<GLhs...>, std::index_sequence<ELhs...>, std::index_sequence<GRhs...>, std::index_sequence<ERhs...>) {
- Result elem{};
- // friend-initialization, avoid multiple calls to refresh
- elem.pools = {view.template storage<GLhs>()..., other.template storage<GRhs>()...};
- auto filter_or_placeholder = [placeholder = elem.placeholder](auto *value) { return (value == nullptr) ? placeholder : value; };
- elem.filter = {filter_or_placeholder(view.template storage<sizeof...(GLhs) + ELhs>())..., filter_or_placeholder(other.template storage<sizeof...(GRhs) + ERhs>())...};
- elem.refresh();
- return elem;
- }
- template<typename Type, bool Checked, std::size_t Get, std::size_t Exclude>
- class view_iterator final {
- template<typename, typename...>
- friend class extended_view_iterator;
- using iterator_type = typename Type::const_iterator;
- using iterator_traits = std::iterator_traits<iterator_type>;
- [[nodiscard]] bool valid(const typename iterator_traits::value_type entt) const noexcept {
- return (!Checked || (entt != tombstone))
- && ((Get == 1u) || (internal::all_of(pools.begin(), pools.begin() + index, entt) && internal::all_of(pools.begin() + index + 1, pools.end(), entt)))
- && ((Exclude == 0u) || internal::none_of(filter.begin(), filter.end(), entt));
- }
- void seek_next() {
- for(constexpr iterator_type sentinel{}; it != sentinel && !valid(*it); ++it) {}
- }
- public:
- using value_type = typename iterator_traits::value_type;
- using pointer = typename iterator_traits::pointer;
- using reference = typename iterator_traits::reference;
- using difference_type = typename iterator_traits::difference_type;
- using iterator_category = std::forward_iterator_tag;
- constexpr view_iterator() noexcept
- : it{},
- pools{},
- filter{},
- index{} {}
- view_iterator(iterator_type first, std::array<const Type *, Get> value, std::array<const Type *, Exclude> excl, const std::size_t idx) noexcept
- : it{first},
- pools{value},
- filter{excl},
- index{static_cast<difference_type>(idx)} {
- ENTT_ASSERT((Get != 1u) || (Exclude != 0u) || pools[0u]->policy() == deletion_policy::in_place, "Non in-place storage view iterator");
- seek_next();
- }
- view_iterator &operator++() noexcept {
- ++it;
- seek_next();
- return *this;
- }
- view_iterator operator++(int) noexcept {
- const view_iterator orig = *this;
- return ++(*this), orig;
- }
- [[nodiscard]] pointer operator->() const noexcept {
- return &*it;
- }
- [[nodiscard]] reference operator*() const noexcept {
- return *operator->();
- }
- template<typename LhsType, auto... LhsArgs, typename RhsType, auto... RhsArgs>
- friend constexpr bool operator==(const view_iterator<LhsType, LhsArgs...> &, const view_iterator<RhsType, RhsArgs...> &) noexcept;
- private:
- iterator_type it;
- std::array<const Type *, Get> pools;
- std::array<const Type *, Exclude> filter;
- difference_type index;
- };
- template<typename LhsType, auto... LhsArgs, typename RhsType, auto... RhsArgs>
- [[nodiscard]] constexpr bool operator==(const view_iterator<LhsType, LhsArgs...> &lhs, const view_iterator<RhsType, RhsArgs...> &rhs) noexcept {
- return lhs.it == rhs.it;
- }
- template<typename LhsType, auto... LhsArgs, typename RhsType, auto... RhsArgs>
- [[nodiscard]] constexpr bool operator!=(const view_iterator<LhsType, LhsArgs...> &lhs, const view_iterator<RhsType, RhsArgs...> &rhs) noexcept {
- return !(lhs == rhs);
- }
- template<typename It, typename... Get>
- class extended_view_iterator final {
- template<std::size_t... Index>
- [[nodiscard]] auto dereference(std::index_sequence<Index...>) const noexcept {
- return std::tuple_cat(std::make_tuple(*it), static_cast<Get *>(const_cast<constness_as_t<typename Get::base_type, Get> *>(std::get<Index>(it.pools)))->get_as_tuple(*it)...);
- }
- public:
- using iterator_type = It;
- using value_type = decltype(std::tuple_cat(std::make_tuple(*std::declval<It>()), std::declval<Get>().get_as_tuple({})...));
- using pointer = input_iterator_pointer<value_type>;
- using reference = value_type;
- using difference_type = std::ptrdiff_t;
- using iterator_category = std::input_iterator_tag;
- using iterator_concept = std::forward_iterator_tag;
- constexpr extended_view_iterator()
- : it{} {}
- extended_view_iterator(iterator_type from)
- : it{from} {}
- extended_view_iterator &operator++() noexcept {
- return ++it, *this;
- }
- extended_view_iterator operator++(int) noexcept {
- const extended_view_iterator orig = *this;
- return ++(*this), orig;
- }
- [[nodiscard]] reference operator*() const noexcept {
- return dereference(std::index_sequence_for<Get...>{});
- }
- [[nodiscard]] pointer operator->() const noexcept {
- return operator*();
- }
- [[nodiscard]] constexpr iterator_type base() const noexcept {
- return it;
- }
- template<typename... Lhs, typename... Rhs>
- friend bool constexpr operator==(const extended_view_iterator<Lhs...> &, const extended_view_iterator<Rhs...> &) noexcept;
- private:
- It it;
- };
- template<typename... Lhs, typename... Rhs>
- [[nodiscard]] constexpr bool operator==(const extended_view_iterator<Lhs...> &lhs, const extended_view_iterator<Rhs...> &rhs) noexcept {
- return lhs.it == rhs.it;
- }
- template<typename... Lhs, typename... Rhs>
- [[nodiscard]] constexpr bool operator!=(const extended_view_iterator<Lhs...> &lhs, const extended_view_iterator<Rhs...> &rhs) noexcept {
- return !(lhs == rhs);
- }
- } // namespace internal
- /*! @endcond */
- /**
- * @brief View implementation.
- *
- * Primary template isn't defined on purpose. All the specializations give a
- * compile-time error, but for a few reasonable cases.
- *
- * @b Important
- *
- * View iterators aren't invalidated if:
- *
- * * New elements are added to the storage iterated by the view.
- * * The entity currently returned is modified (for example, elements are added
- * or removed from it).
- * * The entity currently returned is destroyed.
- *
- * In all other cases, modifying the storage iterated by a view in any way can
- * invalidate all iterators.
- */
- template<typename, typename, typename>
- class basic_view;
- /**
- * @brief Basic storage view implementation.
- * @warning For internal use only, backward compatibility not guaranteed.
- * @tparam Type Common type among all storage types.
- * @tparam Checked True to enable the tombstone check, false otherwise.
- * @tparam Get Number of storage iterated by the view.
- * @tparam Exclude Number of storage used to filter the view.
- */
- template<typename Type, bool Checked, std::size_t Get, std::size_t Exclude>
- class basic_common_view {
- static_assert(std::is_same_v<std::remove_const_t<std::remove_reference_t<Type>>, Type>, "Unexpected type");
- template<typename Return, typename View, typename Other, std::size_t... GLhs, std::size_t... ELhs, std::size_t... GRhs, std::size_t... ERhs>
- friend Return internal::view_pack(const View &, const Other &, std::index_sequence<GLhs...>, std::index_sequence<ELhs...>, std::index_sequence<GRhs...>, std::index_sequence<ERhs...>);
- [[nodiscard]] auto offset() const noexcept {
- ENTT_ASSERT(index != Get, "Invalid view");
- return (pools[index]->policy() == deletion_policy::swap_only) ? pools[index]->free_list() : pools[index]->size();
- }
- void unchecked_refresh() noexcept {
- index = 0u;
- if constexpr(Get > 1u) {
- for(size_type pos{1u}; pos < Get; ++pos) {
- if(pools[pos]->size() < pools[index]->size()) {
- index = pos;
- }
- }
- }
- }
- protected:
- /*! @cond TURN_OFF_DOXYGEN */
- basic_common_view() noexcept {
- for(size_type pos{}, last = filter.size(); pos < last; ++pos) {
- filter[pos] = placeholder;
- }
- }
- basic_common_view(std::array<const Type *, Get> value, std::array<const Type *, Exclude> excl) noexcept
- : pools{value},
- filter{excl},
- index{Get} {
- unchecked_refresh();
- }
- [[nodiscard]] const Type *pool_at(const std::size_t pos) const noexcept {
- return pools[pos];
- }
- void pool_at(const std::size_t pos, const Type *elem) noexcept {
- ENTT_ASSERT(elem != nullptr, "Unexpected element");
- pools[pos] = elem;
- refresh();
- }
- [[nodiscard]] const Type *filter_at(const std::size_t pos) const noexcept {
- return (filter[pos] == placeholder) ? nullptr : filter[pos];
- }
- void filter_at(const std::size_t pos, const Type *elem) noexcept {
- ENTT_ASSERT(elem != nullptr, "Unexpected element");
- filter[pos] = elem;
- }
- [[nodiscard]] bool none_of(const typename Type::entity_type entt) const noexcept {
- return internal::none_of(filter.begin(), filter.end(), entt);
- }
- void use(const std::size_t pos) noexcept {
- index = (index != Get) ? pos : Get;
- }
- /*! @endcond */
- public:
- /*! @brief Common type among all storage types. */
- using common_type = Type;
- /*! @brief Underlying entity identifier. */
- using entity_type = typename Type::entity_type;
- /*! @brief Unsigned integer type. */
- using size_type = std::size_t;
- /*! @brief Signed integer type. */
- using difference_type = std::ptrdiff_t;
- /*! @brief Forward iterator type. */
- using iterator = internal::view_iterator<common_type, Checked, Get, Exclude>;
- /*! @brief Updates the internal leading view if required. */
- void refresh() noexcept {
- size_type pos = static_cast<size_type>(index != Get) * Get;
- for(; pos < Get && pools[pos] != nullptr; ++pos) {}
- if(pos == Get) {
- unchecked_refresh();
- }
- }
- /**
- * @brief Returns the leading storage of a view, if any.
- * @return The leading storage of the view.
- */
- [[nodiscard]] const common_type *handle() const noexcept {
- return (index != Get) ? pools[index] : nullptr;
- }
- /**
- * @brief Estimates the number of entities iterated by the view.
- * @return Estimated number of entities iterated by the view.
- */
- [[nodiscard]] size_type size_hint() const noexcept {
- return (index != Get) ? offset() : size_type{};
- }
- /**
- * @brief Returns an iterator to the first entity of the view.
- *
- * If the view is empty, the returned iterator will be equal to `end()`.
- *
- * @return An iterator to the first entity of the view.
- */
- [[nodiscard]] iterator begin() const noexcept {
- return (index != Get) ? iterator{pools[index]->end() - static_cast<difference_type>(offset()), pools, filter, index} : iterator{};
- }
- /**
- * @brief Returns an iterator that is past the last entity of the view.
- * @return An iterator to the entity following the last entity of the view.
- */
- [[nodiscard]] iterator end() const noexcept {
- return (index != Get) ? iterator{pools[index]->end(), pools, filter, index} : iterator{};
- }
- /**
- * @brief Returns the first entity of the view, if any.
- * @return The first entity of the view if one exists, the null entity
- * otherwise.
- */
- [[nodiscard]] entity_type front() const noexcept {
- const auto it = begin();
- return it != end() ? *it : null;
- }
- /**
- * @brief Returns the last entity of the view, if any.
- * @return The last entity of the view if one exists, the null entity
- * otherwise.
- */
- [[nodiscard]] entity_type back() const noexcept {
- if(index != Get) {
- auto it = pools[index]->rbegin();
- const auto last = it + static_cast<difference_type>(offset());
- for(const auto idx = static_cast<difference_type>(index); it != last && !(internal::all_of(pools.begin(), pools.begin() + idx, *it) && internal::all_of(pools.begin() + idx + 1, pools.end(), *it) && internal::none_of(filter.begin(), filter.end(), *it)); ++it) {}
- return it == last ? null : *it;
- }
- return null;
- }
- /**
- * @brief Finds an entity.
- * @param entt A valid identifier.
- * @return An iterator to the given entity if it's found, past the end
- * iterator otherwise.
- */
- [[nodiscard]] iterator find(const entity_type entt) const noexcept {
- return contains(entt) ? iterator{pools[index]->find(entt), pools, filter, index} : end();
- }
- /**
- * @brief Checks if a view is fully initialized.
- * @return True if the view is fully initialized, false otherwise.
- */
- [[nodiscard]] explicit operator bool() const noexcept {
- return (index != Get) && internal::fully_initialized(filter.begin(), filter.end(), placeholder);
- }
- /**
- * @brief Checks if a view contains an entity.
- * @param entt A valid identifier.
- * @return True if the view contains the given entity, false otherwise.
- */
- [[nodiscard]] bool contains(const entity_type entt) const noexcept {
- return (index != Get)
- && internal::all_of(pools.begin(), pools.end(), entt)
- && internal::none_of(filter.begin(), filter.end(), entt)
- && pools[index]->index(entt) < offset();
- }
- private:
- std::array<const common_type *, Get> pools{};
- std::array<const common_type *, Exclude> filter{};
- const common_type *placeholder{internal::view_placeholder<common_type>()};
- size_type index{Get};
- };
- /**
- * @brief General purpose view.
- *
- * This view visits all entities that are at least in the given storage. During
- * initialization, it also looks at the number of elements available for each
- * storage and uses the smallest set in order to get a performance boost.
- *
- * @sa basic_view
- *
- * @tparam Get Types of storage iterated by the view.
- * @tparam Exclude Types of storage used to filter the view.
- */
- template<typename... Get, typename... Exclude>
- class basic_view<get_t<Get...>, exclude_t<Exclude...>, std::enable_if_t<(sizeof...(Get) != 0u)>>
- : public basic_common_view<std::common_type_t<typename Get::base_type...>, internal::tombstone_check_v<Get...>, sizeof...(Get), sizeof...(Exclude)> {
- using base_type = basic_common_view<std::common_type_t<typename Get::base_type...>, internal::tombstone_check_v<Get...>, sizeof...(Get), sizeof...(Exclude)>;
- template<std::size_t Index>
- using element_at = type_list_element_t<Index, type_list<Get..., Exclude...>>;
- template<typename Type>
- static constexpr std::size_t index_of = type_list_index_v<std::remove_const_t<Type>, type_list<typename Get::element_type..., typename Exclude::element_type...>>;
- template<std::size_t... Index>
- [[nodiscard]] auto get(const typename base_type::entity_type entt, std::index_sequence<Index...>) const noexcept {
- return std::tuple_cat(storage<Index>()->get_as_tuple(entt)...);
- }
- template<std::size_t Curr, std::size_t Other, typename... Args>
- [[nodiscard]] auto dispatch_get(const std::tuple<typename base_type::entity_type, Args...> &curr) const {
- if constexpr(Curr == Other) {
- return std::forward_as_tuple(std::get<Args>(curr)...);
- } else {
- return storage<Other>()->get_as_tuple(std::get<0>(curr));
- }
- }
- template<std::size_t Curr, typename Func, std::size_t... Index>
- void each(Func &func, std::index_sequence<Index...>) const {
- for(const auto curr: storage<Curr>()->each()) {
- if(const auto entt = std::get<0>(curr); (!internal::tombstone_check_v<Get...> || (entt != tombstone)) && ((Curr == Index || base_type::pool_at(Index)->contains(entt)) && ...) && base_type::none_of(entt)) {
- if constexpr(is_applicable_v<Func, decltype(std::tuple_cat(std::tuple<entity_type>{}, std::declval<basic_view>().get({})))>) {
- std::apply(func, std::tuple_cat(std::make_tuple(entt), dispatch_get<Curr, Index>(curr)...));
- } else {
- std::apply(func, std::tuple_cat(dispatch_get<Curr, Index>(curr)...));
- }
- }
- }
- }
- template<typename Func, std::size_t... Index>
- void pick_and_each(Func &func, std::index_sequence<Index...> seq) const {
- if(const auto *view = base_type::handle(); view != nullptr) {
- ((view == base_type::pool_at(Index) ? each<Index>(func, seq) : void()), ...);
- }
- }
- public:
- /*! @brief Common type among all storage types. */
- using common_type = typename base_type::common_type;
- /*! @brief Underlying entity identifier. */
- using entity_type = typename base_type::entity_type;
- /*! @brief Unsigned integer type. */
- using size_type = typename base_type::size_type;
- /*! @brief Signed integer type. */
- using difference_type = std::ptrdiff_t;
- /*! @brief Forward iterator type. */
- using iterator = typename base_type::iterator;
- /*! @brief Iterable view type. */
- using iterable = iterable_adaptor<internal::extended_view_iterator<iterator, Get...>>;
- /*! @brief Default constructor to use to create empty, invalid views. */
- basic_view() noexcept
- : base_type{} {}
- /**
- * @brief Constructs a view from a set of storage classes.
- * @param value The storage for the types to iterate.
- * @param excl The storage for the types used to filter the view.
- */
- basic_view(Get &...value, Exclude &...excl) noexcept
- : base_type{{&value...}, {&excl...}} {
- }
- /**
- * @brief Constructs a view from a set of storage classes.
- * @param value The storage for the types to iterate.
- * @param excl The storage for the types used to filter the view.
- */
- basic_view(std::tuple<Get &...> value, std::tuple<Exclude &...> excl = {}) noexcept
- : basic_view{std::make_from_tuple<basic_view>(std::tuple_cat(value, excl))} {}
- /**
- * @brief Forces a view to use a given element to drive iterations
- * @tparam Type Type of element to use to drive iterations.
- */
- template<typename Type>
- void use() noexcept {
- use<index_of<Type>>();
- }
- /**
- * @brief Forces a view to use a given element to drive iterations
- * @tparam Index Index of the element to use to drive iterations.
- */
- template<std::size_t Index>
- void use() noexcept {
- base_type::use(Index);
- }
- /**
- * @brief Returns the storage for a given element type, if any.
- * @tparam Type Type of element of which to return the storage.
- * @return The storage for the given element type.
- */
- template<typename Type>
- [[nodiscard]] auto *storage() const noexcept {
- return storage<index_of<Type>>();
- }
- /**
- * @brief Returns the storage for a given index, if any.
- * @tparam Index Index of the storage to return.
- * @return The storage for the given index.
- */
- template<std::size_t Index>
- [[nodiscard]] auto *storage() const noexcept {
- if constexpr(Index < sizeof...(Get)) {
- return static_cast<element_at<Index> *>(const_cast<constness_as_t<common_type, element_at<Index>> *>(base_type::pool_at(Index)));
- } else {
- return static_cast<element_at<Index> *>(const_cast<constness_as_t<common_type, element_at<Index>> *>(base_type::filter_at(Index - sizeof...(Get))));
- }
- }
- /**
- * @brief Assigns a storage to a view.
- * @tparam Type Type of storage to assign to the view.
- * @param elem A storage to assign to the view.
- */
- template<typename Type>
- void storage(Type &elem) noexcept {
- storage<index_of<typename Type::element_type>>(elem);
- }
- /**
- * @brief Assigns a storage to a view.
- * @tparam Index Index of the storage to assign to the view.
- * @tparam Type Type of storage to assign to the view.
- * @param elem A storage to assign to the view.
- */
- template<std::size_t Index, typename Type>
- void storage(Type &elem) noexcept {
- static_assert(std::is_convertible_v<Type &, element_at<Index> &>, "Unexpected type");
- if constexpr(Index < sizeof...(Get)) {
- base_type::pool_at(Index, &elem);
- } else {
- base_type::filter_at(Index - sizeof...(Get), &elem);
- }
- }
- /**
- * @brief Returns the elements assigned to the given entity.
- * @param entt A valid identifier.
- * @return The elements assigned to the given entity.
- */
- [[nodiscard]] decltype(auto) operator[](const entity_type entt) const {
- return get(entt);
- }
- /**
- * @brief Returns the elements assigned to the given entity.
- * @tparam Type Type of the element to get.
- * @tparam Other Other types of elements to get.
- * @param entt A valid identifier.
- * @return The elements assigned to the entity.
- */
- template<typename Type, typename... Other>
- [[nodiscard]] decltype(auto) get(const entity_type entt) const {
- return get<index_of<Type>, index_of<Other>...>(entt);
- }
- /**
- * @brief Returns the elements assigned to the given entity.
- * @tparam Index Indexes of the elements to get.
- * @param entt A valid identifier.
- * @return The elements assigned to the entity.
- */
- template<std::size_t... Index>
- [[nodiscard]] decltype(auto) get(const entity_type entt) const {
- if constexpr(sizeof...(Index) == 0) {
- return get(entt, std::index_sequence_for<Get...>{});
- } else if constexpr(sizeof...(Index) == 1) {
- return (storage<Index>()->get(entt), ...);
- } else {
- return std::tuple_cat(storage<Index>()->get_as_tuple(entt)...);
- }
- }
- /**
- * @brief Iterates entities and elements and applies the given function
- * object to them.
- *
- * The signature of the function must be equivalent to one of the following
- * (non-empty types only, constness as requested):
- *
- * @code{.cpp}
- * void(const entity_type, Type &...);
- * void(Type &...);
- * @endcode
- *
- * @tparam Func Type of the function object to invoke.
- * @param func A valid function object.
- */
- template<typename Func>
- void each(Func func) const {
- pick_and_each(func, std::index_sequence_for<Get...>{});
- }
- /**
- * @brief Returns an iterable object to use to _visit_ a view.
- *
- * The iterable object returns a tuple that contains the current entity and
- * a set of references to its non-empty elements. The _constness_ of the
- * elements is as requested.
- *
- * @return An iterable object to use to _visit_ the view.
- */
- [[nodiscard]] iterable each() const noexcept {
- return iterable{base_type::begin(), base_type::end()};
- }
- /**
- * @brief Combines a view and a storage in _more specific_ view.
- * @tparam OGet Type of storage to combine the view with.
- * @param other The storage for the type to combine the view with.
- * @return A more specific view.
- */
- template<typename OGet>
- [[nodiscard]] std::enable_if_t<std::is_base_of_v<common_type, OGet>, basic_view<get_t<Get..., OGet>, exclude_t<Exclude...>>> operator|(OGet &other) const noexcept {
- return *this | basic_view<get_t<OGet>, exclude_t<>>{other};
- }
- /**
- * @brief Combines two views in a _more specific_ one.
- * @tparam OGet Element list of the view to combine with.
- * @tparam OExclude Filter list of the view to combine with.
- * @param other The view to combine with.
- * @return A more specific view.
- */
- template<typename... OGet, typename... OExclude>
- [[nodiscard]] auto operator|(const basic_view<get_t<OGet...>, exclude_t<OExclude...>> &other) const noexcept {
- return internal::view_pack<basic_view<get_t<Get..., OGet...>, exclude_t<Exclude..., OExclude...>>>(
- *this, other, std::index_sequence_for<Get...>{}, std::index_sequence_for<Exclude...>{}, std::index_sequence_for<OGet...>{}, std::index_sequence_for<OExclude...>{});
- }
- };
- /**
- * @brief Basic storage view implementation.
- * @warning For internal use only, backward compatibility not guaranteed.
- * @tparam Type Common type among all storage types.
- * @tparam Policy Storage policy.
- */
- template<typename Type, deletion_policy Policy>
- class basic_storage_view {
- static_assert(std::is_same_v<std::remove_const_t<std::remove_reference_t<Type>>, Type>, "Unexpected type");
- protected:
- /*! @cond TURN_OFF_DOXYGEN */
- basic_storage_view() noexcept = default;
- basic_storage_view(const Type *value) noexcept
- : leading{value} {
- ENTT_ASSERT(leading->policy() == Policy, "Unexpected storage policy");
- }
- /*! @endcond */
- public:
- /*! @brief Common type among all storage types. */
- using common_type = Type;
- /*! @brief Underlying entity identifier. */
- using entity_type = typename common_type::entity_type;
- /*! @brief Unsigned integer type. */
- using size_type = std::size_t;
- /*! @brief Signed integer type. */
- using difference_type = std::ptrdiff_t;
- /*! @brief Random access iterator type. */
- using iterator = std::conditional_t<Policy == deletion_policy::in_place, internal::view_iterator<common_type, true, 1u, 0u>, typename common_type::iterator>;
- /*! @brief Reverse iterator type. */
- using reverse_iterator = std::conditional_t<Policy == deletion_policy::in_place, void, typename common_type::reverse_iterator>;
- /**
- * @brief Returns the leading storage of a view, if any.
- * @return The leading storage of the view.
- */
- [[nodiscard]] const common_type *handle() const noexcept {
- return leading;
- }
- /**
- * @brief Returns the number of entities that have the given element.
- * @tparam Pol Dummy template parameter used for sfinae purposes only.
- * @return Number of entities that have the given element.
- */
- template<typename..., deletion_policy Pol = Policy>
- [[nodiscard]] std::enable_if_t<Pol != deletion_policy::in_place, size_type> size() const noexcept {
- if constexpr(Policy == deletion_policy::swap_and_pop) {
- return leading ? leading->size() : size_type{};
- } else {
- static_assert(Policy == deletion_policy::swap_only, "Unexpected storage policy");
- return leading ? leading->free_list() : size_type{};
- }
- }
- /**
- * @brief Estimates the number of entities iterated by the view.
- * @tparam Pol Dummy template parameter used for sfinae purposes only.
- * @return Estimated number of entities iterated by the view.
- */
- template<typename..., deletion_policy Pol = Policy>
- [[nodiscard]] std::enable_if_t<Pol == deletion_policy::in_place, size_type> size_hint() const noexcept {
- return leading ? leading->size() : size_type{};
- }
- /**
- * @brief Checks whether a view is empty.
- * @tparam Pol Dummy template parameter used for sfinae purposes only.
- * @return True if the view is empty, false otherwise.
- */
- template<typename..., deletion_policy Pol = Policy>
- [[nodiscard]] std::enable_if_t<Pol != deletion_policy::in_place, bool> empty() const noexcept {
- if constexpr(Policy == deletion_policy::swap_and_pop) {
- return !leading || leading->empty();
- } else {
- static_assert(Policy == deletion_policy::swap_only, "Unexpected storage policy");
- return !leading || (leading->free_list() == 0u);
- }
- }
- /**
- * @brief Returns an iterator to the first entity of the view.
- *
- * If the view is empty, the returned iterator will be equal to `end()`.
- *
- * @return An iterator to the first entity of the view.
- */
- [[nodiscard]] iterator begin() const noexcept {
- if constexpr(Policy == deletion_policy::swap_and_pop) {
- return leading ? leading->begin() : iterator{};
- } else if constexpr(Policy == deletion_policy::swap_only) {
- return leading ? (leading->end() - static_cast<difference_type>(leading->free_list())) : iterator{};
- } else {
- static_assert(Policy == deletion_policy::in_place, "Unexpected storage policy");
- return leading ? iterator{leading->begin(), {leading}, {}, 0u} : iterator{};
- }
- }
- /**
- * @brief Returns an iterator that is past the last entity of the view.
- * @return An iterator to the entity following the last entity of the view.
- */
- [[nodiscard]] iterator end() const noexcept {
- if constexpr(Policy == deletion_policy::swap_and_pop || Policy == deletion_policy::swap_only) {
- return leading ? leading->end() : iterator{};
- } else {
- static_assert(Policy == deletion_policy::in_place, "Unexpected storage policy");
- return leading ? iterator{leading->end(), {leading}, {}, 0u} : iterator{};
- }
- }
- /**
- * @brief Returns an iterator to the first entity of the reversed view.
- *
- * If the view is empty, the returned iterator will be equal to `rend()`.
- *
- * @tparam Pol Dummy template parameter used for sfinae purposes only.
- * @return An iterator to the first entity of the reversed view.
- */
- template<typename..., deletion_policy Pol = Policy>
- [[nodiscard]] std::enable_if_t<Pol != deletion_policy::in_place, reverse_iterator> rbegin() const noexcept {
- return leading ? leading->rbegin() : reverse_iterator{};
- }
- /**
- * @brief Returns an iterator that is past the last entity of the reversed
- * view.
- * @tparam Pol Dummy template parameter used for sfinae purposes only.
- * @return An iterator to the entity following the last entity of the
- * reversed view.
- */
- template<typename..., deletion_policy Pol = Policy>
- [[nodiscard]] std::enable_if_t<Pol != deletion_policy::in_place, reverse_iterator> rend() const noexcept {
- if constexpr(Policy == deletion_policy::swap_and_pop) {
- return leading ? leading->rend() : reverse_iterator{};
- } else {
- static_assert(Policy == deletion_policy::swap_only, "Unexpected storage policy");
- return leading ? (leading->rbegin() + static_cast<difference_type>(leading->free_list())) : reverse_iterator{};
- }
- }
- /**
- * @brief Returns the first entity of the view, if any.
- * @return The first entity of the view if one exists, the null entity
- * otherwise.
- */
- [[nodiscard]] entity_type front() const noexcept {
- if constexpr(Policy == deletion_policy::swap_and_pop) {
- return empty() ? null : *leading->begin();
- } else if constexpr(Policy == deletion_policy::swap_only) {
- return empty() ? null : *(leading->end() - static_cast<difference_type>(leading->free_list()));
- } else {
- static_assert(Policy == deletion_policy::in_place, "Unexpected storage policy");
- const auto it = begin();
- return (it == end()) ? null : *it;
- }
- }
- /**
- * @brief Returns the last entity of the view, if any.
- * @return The last entity of the view if one exists, the null entity
- * otherwise.
- */
- [[nodiscard]] entity_type back() const noexcept {
- if constexpr(Policy == deletion_policy::swap_and_pop || Policy == deletion_policy::swap_only) {
- return empty() ? null : *leading->rbegin();
- } else {
- static_assert(Policy == deletion_policy::in_place, "Unexpected storage policy");
- if(leading) {
- auto it = leading->rbegin();
- const auto last = leading->rend();
- for(; (it != last) && (*it == tombstone); ++it) {}
- return it == last ? null : *it;
- }
- return null;
- }
- }
- /**
- * @brief Finds an entity.
- * @param entt A valid identifier.
- * @return An iterator to the given entity if it's found, past the end
- * iterator otherwise.
- */
- [[nodiscard]] iterator find(const entity_type entt) const noexcept {
- if constexpr(Policy == deletion_policy::swap_and_pop) {
- return leading ? leading->find(entt) : iterator{};
- } else if constexpr(Policy == deletion_policy::swap_only) {
- const auto it = leading ? leading->find(entt) : iterator{};
- return leading && (static_cast<size_type>(it.index()) < leading->free_list()) ? it : iterator{};
- } else {
- return leading ? iterator{leading->find(entt), {leading}, {}, 0u} : iterator{};
- }
- }
- /**
- * @brief Checks if a view is fully initialized.
- * @return True if the view is fully initialized, false otherwise.
- */
- [[nodiscard]] explicit operator bool() const noexcept {
- return (leading != nullptr);
- }
- /**
- * @brief Checks if a view contains an entity.
- * @param entt A valid identifier.
- * @return True if the view contains the given entity, false otherwise.
- */
- [[nodiscard]] bool contains(const entity_type entt) const noexcept {
- if constexpr(Policy == deletion_policy::swap_and_pop || Policy == deletion_policy::in_place) {
- return leading && leading->contains(entt);
- } else {
- static_assert(Policy == deletion_policy::swap_only, "Unexpected storage policy");
- return leading && leading->contains(entt) && (leading->index(entt) < leading->free_list());
- }
- }
- private:
- const common_type *leading{};
- };
- /**
- * @brief Storage view specialization.
- *
- * This specialization offers a boost in terms of performance. It can access the
- * underlying data structure directly and avoid superfluous checks.
- *
- * @sa basic_view
- *
- * @tparam Get Type of storage iterated by the view.
- */
- template<typename Get>
- class basic_view<get_t<Get>, exclude_t<>>
- : public basic_storage_view<typename Get::base_type, Get::storage_policy> {
- using base_type = basic_storage_view<typename Get::base_type, Get::storage_policy>;
- public:
- /*! @brief Common type among all storage types. */
- using common_type = typename base_type::common_type;
- /*! @brief Underlying entity identifier. */
- using entity_type = typename base_type::entity_type;
- /*! @brief Unsigned integer type. */
- using size_type = typename base_type::size_type;
- /*! @brief Signed integer type. */
- using difference_type = std::ptrdiff_t;
- /*! @brief Random access iterator type. */
- using iterator = typename base_type::iterator;
- /*! @brief Reverse iterator type. */
- using reverse_iterator = typename base_type::reverse_iterator;
- /*! @brief Iterable view type. */
- using iterable = std::conditional_t<Get::storage_policy == deletion_policy::in_place, iterable_adaptor<internal::extended_view_iterator<iterator, Get>>, decltype(std::declval<Get>().each())>;
- /*! @brief Default constructor to use to create empty, invalid views. */
- basic_view() noexcept
- : base_type{} {}
- /**
- * @brief Constructs a view from a storage class.
- * @param value The storage for the type to iterate.
- */
- basic_view(Get &value) noexcept
- : base_type{&value} {
- }
- /**
- * @brief Constructs a view from a storage class.
- * @param value The storage for the type to iterate.
- */
- basic_view(std::tuple<Get &> value, std::tuple<> = {}) noexcept
- : basic_view{std::get<0>(value)} {}
- /**
- * @brief Returns the storage for a given element type, if any.
- * @tparam Type Type of element of which to return the storage.
- * @return The storage for the given element type.
- */
- template<typename Type = typename Get::element_type>
- [[nodiscard]] auto *storage() const noexcept {
- static_assert(std::is_same_v<std::remove_const_t<Type>, typename Get::element_type>, "Invalid element type");
- return storage<0>();
- }
- /**
- * @brief Returns the storage for a given index, if any.
- * @tparam Index Index of the storage to return.
- * @return The storage for the given index.
- */
- template<std::size_t Index>
- [[nodiscard]] auto *storage() const noexcept {
- static_assert(Index == 0u, "Index out of bounds");
- return static_cast<Get *>(const_cast<constness_as_t<common_type, Get> *>(base_type::handle()));
- }
- /**
- * @brief Assigns a storage to a view.
- * @param elem A storage to assign to the view.
- */
- void storage(Get &elem) noexcept {
- storage<0>(elem);
- }
- /**
- * @brief Assigns a storage to a view.
- * @tparam Index Index of the storage to assign to the view.
- * @param elem A storage to assign to the view.
- */
- template<std::size_t Index>
- void storage(Get &elem) noexcept {
- static_assert(Index == 0u, "Index out of bounds");
- *this = basic_view{elem};
- }
- /**
- * @brief Returns a pointer to the underlying storage.
- * @return A pointer to the underlying storage.
- */
- [[nodiscard]] Get *operator->() const noexcept {
- return storage();
- }
- /**
- * @brief Returns the element assigned to the given entity.
- * @param entt A valid identifier.
- * @return The element assigned to the given entity.
- */
- [[nodiscard]] decltype(auto) operator[](const entity_type entt) const {
- return storage()->get(entt);
- }
- /**
- * @brief Returns the element assigned to the given entity.
- * @tparam Elem Type of the element to get.
- * @param entt A valid identifier.
- * @return The element assigned to the entity.
- */
- template<typename Elem>
- [[nodiscard]] decltype(auto) get(const entity_type entt) const {
- static_assert(std::is_same_v<std::remove_const_t<Elem>, typename Get::element_type>, "Invalid element type");
- return get<0>(entt);
- }
- /**
- * @brief Returns the element assigned to the given entity.
- * @tparam Index Index of the element to get.
- * @param entt A valid identifier.
- * @return The element assigned to the entity.
- */
- template<std::size_t... Index>
- [[nodiscard]] decltype(auto) get(const entity_type entt) const {
- if constexpr(sizeof...(Index) == 0) {
- return storage()->get_as_tuple(entt);
- } else {
- return storage<Index...>()->get(entt);
- }
- }
- /**
- * @brief Iterates entities and elements and applies the given function
- * object to them.
- *
- * The signature of the function must be equivalent to one of the following
- * (non-empty types only, constness as requested):
- *
- * @code{.cpp}
- * void(const entity_type, Type &);
- * void(typename Type &);
- * @endcode
- *
- * @tparam Func Type of the function object to invoke.
- * @param func A valid function object.
- */
- template<typename Func>
- void each(Func func) const {
- if constexpr(is_applicable_v<Func, decltype(std::tuple_cat(std::tuple<entity_type>{}, std::declval<basic_view>().get({})))>) {
- for(const auto pack: each()) {
- std::apply(func, pack);
- }
- } else if constexpr(Get::storage_policy == deletion_policy::swap_and_pop || Get::storage_policy == deletion_policy::swap_only) {
- if constexpr(std::is_void_v<typename Get::value_type>) {
- for(size_type pos = base_type::size(); pos; --pos) {
- func();
- }
- } else {
- if(const auto len = static_cast<difference_type>(base_type::size()); len != 0) {
- for(auto last = storage()->end(), first = last - len; first != last; ++first) {
- func(*first);
- }
- }
- }
- } else {
- static_assert(Get::storage_policy == deletion_policy::in_place, "Unexpected storage policy");
- for(const auto pack: each()) {
- std::apply([&func](const auto, auto &&...elem) { func(std::forward<decltype(elem)>(elem)...); }, pack);
- }
- }
- }
- /**
- * @brief Returns an iterable object to use to _visit_ a view.
- *
- * The iterable object returns a tuple that contains the current entity and
- * a reference to its element if it's a non-empty one. The _constness_ of
- * the element is as requested.
- *
- * @return An iterable object to use to _visit_ the view.
- */
- [[nodiscard]] iterable each() const noexcept {
- if constexpr(Get::storage_policy == deletion_policy::swap_and_pop || Get::storage_policy == deletion_policy::swap_only) {
- return base_type::handle() ? storage()->each() : iterable{};
- } else {
- static_assert(Get::storage_policy == deletion_policy::in_place, "Unexpected storage policy");
- return iterable{base_type::begin(), base_type::end()};
- }
- }
- /**
- * @brief Combines a view and a storage in _more specific_ view.
- * @tparam OGet Type of storage to combine the view with.
- * @param other The storage for the type to combine the view with.
- * @return A more specific view.
- */
- template<typename OGet>
- [[nodiscard]] std::enable_if_t<std::is_base_of_v<common_type, OGet>, basic_view<get_t<Get, OGet>, exclude_t<>>> operator|(OGet &other) const noexcept {
- return *this | basic_view<get_t<OGet>, exclude_t<>>{other};
- }
- /**
- * @brief Combines two views in a _more specific_ one.
- * @tparam OGet Element list of the view to combine with.
- * @tparam OExclude Filter list of the view to combine with.
- * @param other The view to combine with.
- * @return A more specific view.
- */
- template<typename... OGet, typename... OExclude>
- [[nodiscard]] auto operator|(const basic_view<get_t<OGet...>, exclude_t<OExclude...>> &other) const noexcept {
- return internal::view_pack<basic_view<get_t<Get, OGet...>, exclude_t<OExclude...>>>(
- *this, other, std::index_sequence_for<Get>{}, std::index_sequence_for<>{}, std::index_sequence_for<OGet...>{}, std::index_sequence_for<OExclude...>{});
- }
- };
- /**
- * @brief Deduction guide.
- * @tparam Type Type of storage classes used to create the view.
- * @param storage The storage for the types to iterate.
- */
- template<typename... Type>
- basic_view(Type &...storage) -> basic_view<get_t<Type...>, exclude_t<>>;
- /**
- * @brief Deduction guide.
- * @tparam Get Types of elements iterated by the view.
- * @tparam Exclude Types of elements used to filter the view.
- */
- template<typename... Get, typename... Exclude>
- basic_view(std::tuple<Get &...>, std::tuple<Exclude &...> = {}) -> basic_view<get_t<Get...>, exclude_t<Exclude...>>;
- } // namespace entt
- #endif
- // #include "graph/adjacency_matrix.hpp"
- #ifndef ENTT_GRAPH_ADJACENCY_MATRIX_HPP
- #define ENTT_GRAPH_ADJACENCY_MATRIX_HPP
- #include <cstddef>
- #include <iterator>
- #include <memory>
- #include <type_traits>
- #include <utility>
- #include <vector>
- // #include "../config/config.h"
- #ifndef ENTT_CONFIG_CONFIG_H
- #define ENTT_CONFIG_CONFIG_H
- // #include "version.h"
- #ifndef ENTT_CONFIG_VERSION_H
- #define ENTT_CONFIG_VERSION_H
- // #include "macro.h"
- #ifndef ENTT_CONFIG_MACRO_H
- #define ENTT_CONFIG_MACRO_H
- // NOLINTBEGIN(cppcoreguidelines-macro-usage)
- #define ENTT_STR(arg) #arg
- #define ENTT_XSTR(arg) ENTT_STR(arg)
- // NOLINTEND(cppcoreguidelines-macro-usage)
- #endif
- // NOLINTBEGIN(cppcoreguidelines-macro-*,modernize-macro-*)
- #define ENTT_VERSION_MAJOR 3
- #define ENTT_VERSION_MINOR 16
- #define ENTT_VERSION_PATCH 0
- #define ENTT_VERSION \
- ENTT_XSTR(ENTT_VERSION_MAJOR) \
- "." ENTT_XSTR(ENTT_VERSION_MINOR) "." ENTT_XSTR(ENTT_VERSION_PATCH)
- // NOLINTEND(cppcoreguidelines-macro-*,modernize-macro-*)
- #endif
- // NOLINTBEGIN(cppcoreguidelines-macro-usage)
- #if defined(__cpp_exceptions) && !defined(ENTT_NOEXCEPTION)
- # define ENTT_CONSTEXPR
- # define ENTT_THROW throw
- # define ENTT_TRY try
- # define ENTT_CATCH catch(...)
- #else
- # define ENTT_CONSTEXPR constexpr // use only with throwing functions (waiting for C++20)
- # define ENTT_THROW
- # define ENTT_TRY if(true)
- # define ENTT_CATCH if(false)
- #endif
- #if __has_include(<version>)
- # include <version>
- #
- # if defined(__cpp_consteval)
- # define ENTT_CONSTEVAL consteval
- # endif
- #endif
- #ifndef ENTT_CONSTEVAL
- # define ENTT_CONSTEVAL constexpr
- #endif
- #ifdef ENTT_USE_ATOMIC
- # include <atomic>
- # define ENTT_MAYBE_ATOMIC(Type) std::atomic<Type>
- #else
- # define ENTT_MAYBE_ATOMIC(Type) Type
- #endif
- #ifndef ENTT_ID_TYPE
- # include <cstdint>
- # define ENTT_ID_TYPE std::uint32_t
- #else
- # include <cstdint> // provides coverage for types in the std namespace
- #endif
- #ifndef ENTT_SPARSE_PAGE
- # define ENTT_SPARSE_PAGE 4096
- #endif
- #ifndef ENTT_PACKED_PAGE
- # define ENTT_PACKED_PAGE 1024
- #endif
- #ifdef ENTT_DISABLE_ASSERT
- # undef ENTT_ASSERT
- # define ENTT_ASSERT(condition, msg) (void(0))
- #elif !defined ENTT_ASSERT
- # include <cassert>
- # define ENTT_ASSERT(condition, msg) assert(((condition) && (msg)))
- #endif
- #ifdef ENTT_DISABLE_ASSERT
- # undef ENTT_ASSERT_CONSTEXPR
- # define ENTT_ASSERT_CONSTEXPR(condition, msg) (void(0))
- #elif !defined ENTT_ASSERT_CONSTEXPR
- # define ENTT_ASSERT_CONSTEXPR(condition, msg) ENTT_ASSERT(condition, msg)
- #endif
- #define ENTT_FAIL(msg) ENTT_ASSERT(false, msg);
- #ifdef ENTT_NO_ETO
- # define ENTT_ETO_TYPE(Type) void
- #else
- # define ENTT_ETO_TYPE(Type) Type
- #endif
- #ifdef ENTT_NO_MIXIN
- # define ENTT_STORAGE(Mixin, ...) __VA_ARGS__
- #else
- # define ENTT_STORAGE(Mixin, ...) Mixin<__VA_ARGS__>
- #endif
- #ifdef ENTT_STANDARD_CPP
- # define ENTT_NONSTD false
- #else
- # define ENTT_NONSTD true
- # if defined __clang__ || defined __GNUC__
- # define ENTT_PRETTY_FUNCTION __PRETTY_FUNCTION__
- # define ENTT_PRETTY_FUNCTION_PREFIX '='
- # define ENTT_PRETTY_FUNCTION_SUFFIX ']'
- # elif defined _MSC_VER
- # define ENTT_PRETTY_FUNCTION __FUNCSIG__
- # define ENTT_PRETTY_FUNCTION_PREFIX '<'
- # define ENTT_PRETTY_FUNCTION_SUFFIX '>'
- # endif
- #endif
- #ifndef ENTT_EXPORT
- # if defined _WIN32 || defined __CYGWIN__ || defined _MSC_VER
- # define ENTT_EXPORT __declspec(dllexport)
- # define ENTT_IMPORT __declspec(dllimport)
- # define ENTT_HIDDEN
- # elif defined __GNUC__ && __GNUC__ >= 4
- # define ENTT_EXPORT __attribute__((visibility("default")))
- # define ENTT_IMPORT __attribute__((visibility("default")))
- # define ENTT_HIDDEN __attribute__((visibility("hidden")))
- # else /* Unsupported compiler */
- # define ENTT_EXPORT
- # define ENTT_IMPORT
- # define ENTT_HIDDEN
- # endif
- #endif
- #ifndef ENTT_API
- # if defined ENTT_API_EXPORT
- # define ENTT_API ENTT_EXPORT
- # elif defined ENTT_API_IMPORT
- # define ENTT_API ENTT_IMPORT
- # else /* No API */
- # define ENTT_API
- # endif
- #endif
- #if defined _MSC_VER
- # pragma detect_mismatch("entt.version", ENTT_VERSION)
- # pragma detect_mismatch("entt.noexcept", ENTT_XSTR(ENTT_TRY))
- # pragma detect_mismatch("entt.id", ENTT_XSTR(ENTT_ID_TYPE))
- # pragma detect_mismatch("entt.nonstd", ENTT_XSTR(ENTT_NONSTD))
- #endif
- // NOLINTEND(cppcoreguidelines-macro-usage)
- #endif
- // #include "../core/iterator.hpp"
- #ifndef ENTT_CORE_ITERATOR_HPP
- #define ENTT_CORE_ITERATOR_HPP
- #include <iterator>
- #include <memory>
- #include <type_traits>
- #include <utility>
- namespace entt {
- /**
- * @brief Helper type to use as pointer with input iterators.
- * @tparam Type of wrapped value.
- */
- template<typename Type>
- struct input_iterator_pointer final {
- /*! @brief Value type. */
- using value_type = Type;
- /*! @brief Pointer type. */
- using pointer = Type *;
- /*! @brief Reference type. */
- using reference = Type &;
- /**
- * @brief Constructs a proxy object by move.
- * @param val Value to use to initialize the proxy object.
- */
- constexpr input_iterator_pointer(value_type &&val) noexcept(std::is_nothrow_move_constructible_v<value_type>)
- : value{std::move(val)} {}
- /**
- * @brief Access operator for accessing wrapped values.
- * @return A pointer to the wrapped value.
- */
- [[nodiscard]] constexpr pointer operator->() noexcept {
- return std::addressof(value);
- }
- /**
- * @brief Dereference operator for accessing wrapped values.
- * @return A reference to the wrapped value.
- */
- [[nodiscard]] constexpr reference operator*() noexcept {
- return value;
- }
- private:
- Type value;
- };
- /**
- * @brief Plain iota iterator (waiting for C++20).
- * @tparam Type Value type.
- */
- template<typename Type>
- class iota_iterator final {
- static_assert(std::is_integral_v<Type>, "Not an integral type");
- public:
- /*! @brief Value type, likely an integral one. */
- using value_type = Type;
- /*! @brief Invalid pointer type. */
- using pointer = void;
- /*! @brief Non-reference type, same as value type. */
- using reference = value_type;
- /*! @brief Difference type. */
- using difference_type = std::ptrdiff_t;
- /*! @brief Iterator category. */
- using iterator_category = std::input_iterator_tag;
- /*! @brief Default constructor. */
- constexpr iota_iterator() noexcept
- : current{} {}
- /**
- * @brief Constructs an iota iterator from a given value.
- * @param init The initial value assigned to the iota iterator.
- */
- constexpr iota_iterator(const value_type init) noexcept
- : current{init} {}
- /**
- * @brief Pre-increment operator.
- * @return This iota iterator.
- */
- constexpr iota_iterator &operator++() noexcept {
- return ++current, *this;
- }
- /**
- * @brief Post-increment operator.
- * @return This iota iterator.
- */
- constexpr iota_iterator operator++(int) noexcept {
- const iota_iterator orig = *this;
- return ++(*this), orig;
- }
- /**
- * @brief Dereference operator.
- * @return The underlying value.
- */
- [[nodiscard]] constexpr reference operator*() const noexcept {
- return current;
- }
- private:
- value_type current;
- };
- /**
- * @brief Comparison operator.
- * @tparam Type Value type of the iota iterator.
- * @param lhs A properly initialized iota iterator.
- * @param rhs A properly initialized iota iterator.
- * @return True if the two iterators are identical, false otherwise.
- */
- template<typename Type>
- [[nodiscard]] constexpr bool operator==(const iota_iterator<Type> &lhs, const iota_iterator<Type> &rhs) noexcept {
- return *lhs == *rhs;
- }
- /**
- * @brief Comparison operator.
- * @tparam Type Value type of the iota iterator.
- * @param lhs A properly initialized iota iterator.
- * @param rhs A properly initialized iota iterator.
- * @return True if the two iterators differ, false otherwise.
- */
- template<typename Type>
- [[nodiscard]] constexpr bool operator!=(const iota_iterator<Type> &lhs, const iota_iterator<Type> &rhs) noexcept {
- return !(lhs == rhs);
- }
- /**
- * @brief Utility class to create an iterable object from a pair of iterators.
- * @tparam It Type of iterator.
- * @tparam Sentinel Type of sentinel.
- */
- template<typename It, typename Sentinel = It>
- struct iterable_adaptor final {
- /*! @brief Value type. */
- using value_type = typename std::iterator_traits<It>::value_type;
- /*! @brief Iterator type. */
- using iterator = It;
- /*! @brief Sentinel type. */
- using sentinel = Sentinel;
- /*! @brief Default constructor. */
- constexpr iterable_adaptor() noexcept(std::is_nothrow_default_constructible_v<iterator> && std::is_nothrow_default_constructible_v<sentinel>)
- : first{},
- last{} {}
- /**
- * @brief Creates an iterable object from a pair of iterators.
- * @param from Begin iterator.
- * @param to End iterator.
- */
- constexpr iterable_adaptor(iterator from, sentinel to) noexcept(std::is_nothrow_move_constructible_v<iterator> && std::is_nothrow_move_constructible_v<sentinel>)
- : first{std::move(from)},
- last{std::move(to)} {}
- /**
- * @brief Returns an iterator to the beginning.
- * @return An iterator to the first element of the range.
- */
- [[nodiscard]] constexpr iterator begin() const noexcept {
- return first;
- }
- /**
- * @brief Returns an iterator to the end.
- * @return An iterator to the element following the last element of the
- * range.
- */
- [[nodiscard]] constexpr sentinel end() const noexcept {
- return last;
- }
- /*! @copydoc begin */
- [[nodiscard]] constexpr iterator cbegin() const noexcept {
- return begin();
- }
- /*! @copydoc end */
- [[nodiscard]] constexpr sentinel cend() const noexcept {
- return end();
- }
- private:
- It first;
- Sentinel last;
- };
- } // namespace entt
- #endif
- // #include "fwd.hpp"
- #ifndef ENTT_GRAPH_FWD_HPP
- #define ENTT_GRAPH_FWD_HPP
- #include <cstddef>
- #include <memory>
- // #include "../core/fwd.hpp"
- #ifndef ENTT_CORE_FWD_HPP
- #define ENTT_CORE_FWD_HPP
- #include <cstddef>
- #include <cstdint>
- // #include "../config/config.h"
- #ifndef ENTT_CONFIG_CONFIG_H
- #define ENTT_CONFIG_CONFIG_H
- // #include "version.h"
- #ifndef ENTT_CONFIG_VERSION_H
- #define ENTT_CONFIG_VERSION_H
- // #include "macro.h"
- #ifndef ENTT_CONFIG_MACRO_H
- #define ENTT_CONFIG_MACRO_H
- // NOLINTBEGIN(cppcoreguidelines-macro-usage)
- #define ENTT_STR(arg) #arg
- #define ENTT_XSTR(arg) ENTT_STR(arg)
- // NOLINTEND(cppcoreguidelines-macro-usage)
- #endif
- // NOLINTBEGIN(cppcoreguidelines-macro-*,modernize-macro-*)
- #define ENTT_VERSION_MAJOR 3
- #define ENTT_VERSION_MINOR 16
- #define ENTT_VERSION_PATCH 0
- #define ENTT_VERSION \
- ENTT_XSTR(ENTT_VERSION_MAJOR) \
- "." ENTT_XSTR(ENTT_VERSION_MINOR) "." ENTT_XSTR(ENTT_VERSION_PATCH)
- // NOLINTEND(cppcoreguidelines-macro-*,modernize-macro-*)
- #endif
- // NOLINTBEGIN(cppcoreguidelines-macro-usage)
- #if defined(__cpp_exceptions) && !defined(ENTT_NOEXCEPTION)
- # define ENTT_CONSTEXPR
- # define ENTT_THROW throw
- # define ENTT_TRY try
- # define ENTT_CATCH catch(...)
- #else
- # define ENTT_CONSTEXPR constexpr // use only with throwing functions (waiting for C++20)
- # define ENTT_THROW
- # define ENTT_TRY if(true)
- # define ENTT_CATCH if(false)
- #endif
- #if __has_include(<version>)
- # include <version>
- #
- # if defined(__cpp_consteval)
- # define ENTT_CONSTEVAL consteval
- # endif
- #endif
- #ifndef ENTT_CONSTEVAL
- # define ENTT_CONSTEVAL constexpr
- #endif
- #ifdef ENTT_USE_ATOMIC
- # include <atomic>
- # define ENTT_MAYBE_ATOMIC(Type) std::atomic<Type>
- #else
- # define ENTT_MAYBE_ATOMIC(Type) Type
- #endif
- #ifndef ENTT_ID_TYPE
- # include <cstdint>
- # define ENTT_ID_TYPE std::uint32_t
- #else
- # include <cstdint> // provides coverage for types in the std namespace
- #endif
- #ifndef ENTT_SPARSE_PAGE
- # define ENTT_SPARSE_PAGE 4096
- #endif
- #ifndef ENTT_PACKED_PAGE
- # define ENTT_PACKED_PAGE 1024
- #endif
- #ifdef ENTT_DISABLE_ASSERT
- # undef ENTT_ASSERT
- # define ENTT_ASSERT(condition, msg) (void(0))
- #elif !defined ENTT_ASSERT
- # include <cassert>
- # define ENTT_ASSERT(condition, msg) assert(((condition) && (msg)))
- #endif
- #ifdef ENTT_DISABLE_ASSERT
- # undef ENTT_ASSERT_CONSTEXPR
- # define ENTT_ASSERT_CONSTEXPR(condition, msg) (void(0))
- #elif !defined ENTT_ASSERT_CONSTEXPR
- # define ENTT_ASSERT_CONSTEXPR(condition, msg) ENTT_ASSERT(condition, msg)
- #endif
- #define ENTT_FAIL(msg) ENTT_ASSERT(false, msg);
- #ifdef ENTT_NO_ETO
- # define ENTT_ETO_TYPE(Type) void
- #else
- # define ENTT_ETO_TYPE(Type) Type
- #endif
- #ifdef ENTT_NO_MIXIN
- # define ENTT_STORAGE(Mixin, ...) __VA_ARGS__
- #else
- # define ENTT_STORAGE(Mixin, ...) Mixin<__VA_ARGS__>
- #endif
- #ifdef ENTT_STANDARD_CPP
- # define ENTT_NONSTD false
- #else
- # define ENTT_NONSTD true
- # if defined __clang__ || defined __GNUC__
- # define ENTT_PRETTY_FUNCTION __PRETTY_FUNCTION__
- # define ENTT_PRETTY_FUNCTION_PREFIX '='
- # define ENTT_PRETTY_FUNCTION_SUFFIX ']'
- # elif defined _MSC_VER
- # define ENTT_PRETTY_FUNCTION __FUNCSIG__
- # define ENTT_PRETTY_FUNCTION_PREFIX '<'
- # define ENTT_PRETTY_FUNCTION_SUFFIX '>'
- # endif
- #endif
- #ifndef ENTT_EXPORT
- # if defined _WIN32 || defined __CYGWIN__ || defined _MSC_VER
- # define ENTT_EXPORT __declspec(dllexport)
- # define ENTT_IMPORT __declspec(dllimport)
- # define ENTT_HIDDEN
- # elif defined __GNUC__ && __GNUC__ >= 4
- # define ENTT_EXPORT __attribute__((visibility("default")))
- # define ENTT_IMPORT __attribute__((visibility("default")))
- # define ENTT_HIDDEN __attribute__((visibility("hidden")))
- # else /* Unsupported compiler */
- # define ENTT_EXPORT
- # define ENTT_IMPORT
- # define ENTT_HIDDEN
- # endif
- #endif
- #ifndef ENTT_API
- # if defined ENTT_API_EXPORT
- # define ENTT_API ENTT_EXPORT
- # elif defined ENTT_API_IMPORT
- # define ENTT_API ENTT_IMPORT
- # else /* No API */
- # define ENTT_API
- # endif
- #endif
- #if defined _MSC_VER
- # pragma detect_mismatch("entt.version", ENTT_VERSION)
- # pragma detect_mismatch("entt.noexcept", ENTT_XSTR(ENTT_TRY))
- # pragma detect_mismatch("entt.id", ENTT_XSTR(ENTT_ID_TYPE))
- # pragma detect_mismatch("entt.nonstd", ENTT_XSTR(ENTT_NONSTD))
- #endif
- // NOLINTEND(cppcoreguidelines-macro-usage)
- #endif
- namespace entt {
- /*! @brief Possible modes of an any object. */
- enum class any_policy : std::uint8_t {
- /*! @brief Default mode, no element available. */
- empty,
- /*! @brief Owning mode, dynamically allocated element. */
- dynamic,
- /*! @brief Owning mode, embedded element. */
- embedded,
- /*! @brief Aliasing mode, non-const reference. */
- ref,
- /*! @brief Const aliasing mode, const reference. */
- cref
- };
- // NOLINTNEXTLINE(cppcoreguidelines-avoid-c-arrays, modernize-avoid-c-arrays)
- template<std::size_t Len = sizeof(double[2]), std::size_t = alignof(double[2])>
- class basic_any;
- /*! @brief Alias declaration for type identifiers. */
- using id_type = ENTT_ID_TYPE;
- /*! @brief Alias declaration for the most common use case. */
- using any = basic_any<>;
- template<typename, typename>
- class compressed_pair;
- template<typename>
- class basic_hashed_string;
- /*! @brief Aliases for common character types. */
- using hashed_string = basic_hashed_string<char>;
- /*! @brief Aliases for common character types. */
- using hashed_wstring = basic_hashed_string<wchar_t>;
- // NOLINTNEXTLINE(bugprone-forward-declaration-namespace)
- struct type_info;
- } // namespace entt
- #endif
- namespace entt {
- /*! @brief Undirected graph category tag. */
- struct directed_tag {};
- /*! @brief Directed graph category tag. */
- struct undirected_tag: directed_tag {};
- template<typename, typename = std::allocator<std::size_t>>
- class adjacency_matrix;
- template<typename = std::allocator<id_type>>
- class basic_flow;
- /*! @brief Alias declaration for the most common use case. */
- using flow = basic_flow<>;
- } // namespace entt
- #endif
- namespace entt {
- /*! @cond TURN_OFF_DOXYGEN */
- namespace internal {
- template<typename It>
- class edge_iterator {
- using size_type = std::size_t;
- void find_next() noexcept {
- for(; pos != last && !it[static_cast<typename It::difference_type>(pos)]; pos += offset) {}
- }
- public:
- using value_type = std::pair<size_type, size_type>;
- using pointer = input_iterator_pointer<value_type>;
- using reference = value_type;
- using difference_type = std::ptrdiff_t;
- using iterator_category = std::input_iterator_tag;
- using iterator_concept = std::forward_iterator_tag;
- constexpr edge_iterator() noexcept = default;
- // NOLINTNEXTLINE(bugprone-easily-swappable-parameters)
- constexpr edge_iterator(It base, const size_type vertices, const size_type from, const size_type to, const size_type step) noexcept
- : it{std::move(base)},
- vert{vertices},
- pos{from},
- last{to},
- offset{step} {
- find_next();
- }
- constexpr edge_iterator &operator++() noexcept {
- pos += offset;
- find_next();
- return *this;
- }
- constexpr edge_iterator operator++(int) noexcept {
- const edge_iterator orig = *this;
- return ++(*this), orig;
- }
- [[nodiscard]] constexpr reference operator*() const noexcept {
- return *operator->();
- }
- [[nodiscard]] constexpr pointer operator->() const noexcept {
- return std::make_pair<size_type>(pos / vert, pos % vert);
- }
- template<typename Type>
- friend constexpr bool operator==(const edge_iterator<Type> &, const edge_iterator<Type> &) noexcept;
- private:
- It it{};
- size_type vert{};
- size_type pos{};
- size_type last{};
- size_type offset{};
- };
- template<typename Container>
- [[nodiscard]] constexpr bool operator==(const edge_iterator<Container> &lhs, const edge_iterator<Container> &rhs) noexcept {
- return lhs.pos == rhs.pos;
- }
- template<typename Container>
- [[nodiscard]] constexpr bool operator!=(const edge_iterator<Container> &lhs, const edge_iterator<Container> &rhs) noexcept {
- return !(lhs == rhs);
- }
- } // namespace internal
- /*! @endcond */
- /**
- * @brief Basic implementation of a directed adjacency matrix.
- * @tparam Category Either a directed or undirected category tag.
- * @tparam Allocator Type of allocator used to manage memory and elements.
- */
- template<typename Category, typename Allocator>
- class adjacency_matrix {
- using alloc_traits = std::allocator_traits<Allocator>;
- static_assert(std::is_base_of_v<directed_tag, Category>, "Invalid graph category");
- static_assert(std::is_same_v<typename alloc_traits::value_type, std::size_t>, "Invalid value type");
- using container_type = std::vector<std::size_t, typename alloc_traits::template rebind_alloc<std::size_t>>;
- public:
- /*! @brief Allocator type. */
- using allocator_type = Allocator;
- /*! @brief Unsigned integer type. */
- using size_type = std::size_t;
- /*! @brief Vertex type. */
- using vertex_type = size_type;
- /*! @brief Edge type. */
- using edge_type = std::pair<vertex_type, vertex_type>;
- /*! @brief Vertex iterator type. */
- using vertex_iterator = iota_iterator<vertex_type>;
- /*! @brief Edge iterator type. */
- using edge_iterator = internal::edge_iterator<typename container_type::const_iterator>;
- /*! @brief Out-edge iterator type. */
- using out_edge_iterator = edge_iterator;
- /*! @brief In-edge iterator type. */
- using in_edge_iterator = edge_iterator;
- /*! @brief Graph category tag. */
- using graph_category = Category;
- /*! @brief Default constructor. */
- adjacency_matrix() noexcept(noexcept(allocator_type{}))
- : adjacency_matrix{0u} {
- }
- /**
- * @brief Constructs an empty container with a given allocator.
- * @param allocator The allocator to use.
- */
- explicit adjacency_matrix(const allocator_type &allocator) noexcept
- : adjacency_matrix{0u, allocator} {}
- /**
- * @brief Constructs an empty container with a given allocator and user
- * supplied number of vertices.
- * @param vertices Number of vertices.
- * @param allocator The allocator to use.
- */
- adjacency_matrix(const size_type vertices, const allocator_type &allocator = allocator_type{})
- : matrix{vertices * vertices, allocator},
- vert{vertices} {}
- /*! @brief Default copy constructor. */
- adjacency_matrix(const adjacency_matrix &) = default;
- /**
- * @brief Allocator-extended copy constructor.
- * @param other The instance to copy from.
- * @param allocator The allocator to use.
- */
- adjacency_matrix(const adjacency_matrix &other, const allocator_type &allocator)
- : matrix{other.matrix, allocator},
- vert{other.vert} {}
- /*! @brief Default move constructor. */
- adjacency_matrix(adjacency_matrix &&) noexcept = default;
- /**
- * @brief Allocator-extended move constructor.
- * @param other The instance to move from.
- * @param allocator The allocator to use.
- */
- adjacency_matrix(adjacency_matrix &&other, const allocator_type &allocator)
- : matrix{std::move(other.matrix), allocator},
- vert{other.vert} {}
- /*! @brief Default destructor. */
- ~adjacency_matrix() = default;
- /**
- * @brief Default copy assignment operator.
- * @return This container.
- */
- adjacency_matrix &operator=(const adjacency_matrix &) = default;
- /**
- * @brief Default move assignment operator.
- * @return This container.
- */
- adjacency_matrix &operator=(adjacency_matrix &&) noexcept = default;
- /**
- * @brief Exchanges the contents with those of a given adjacency matrix.
- * @param other Adjacency matrix to exchange the content with.
- */
- void swap(adjacency_matrix &other) noexcept {
- using std::swap;
- swap(matrix, other.matrix);
- swap(vert, other.vert);
- }
- /**
- * @brief Returns the associated allocator.
- * @return The associated allocator.
- */
- [[nodiscard]] constexpr allocator_type get_allocator() const noexcept {
- return matrix.get_allocator();
- }
- /*! @brief Clears the adjacency matrix. */
- void clear() noexcept {
- matrix.clear();
- vert = {};
- }
- /**
- * @brief Returns true if an adjacency matrix is empty, false otherwise.
- *
- * @warning
- * Potentially expensive, try to avoid it on hot paths.
- *
- * @return True if the adjacency matrix is empty, false otherwise.
- */
- [[nodiscard]] bool empty() const noexcept {
- const auto iterable = edges();
- return (iterable.begin() == iterable.end());
- }
- /**
- * @brief Returns the number of vertices.
- * @return The number of vertices.
- */
- [[nodiscard]] size_type size() const noexcept {
- return vert;
- }
- /**
- * @brief Returns an iterable object to visit all vertices of a matrix.
- * @return An iterable object to visit all vertices of a matrix.
- */
- [[nodiscard]] iterable_adaptor<vertex_iterator> vertices() const noexcept {
- return {0u, vert};
- }
- /**
- * @brief Returns an iterable object to visit all edges of a matrix.
- * @return An iterable object to visit all edges of a matrix.
- */
- [[nodiscard]] iterable_adaptor<edge_iterator> edges() const noexcept {
- const auto it = matrix.cbegin();
- const auto sz = matrix.size();
- return {{it, vert, 0u, sz, 1u}, {it, vert, sz, sz, 1u}};
- }
- /**
- * @brief Returns an iterable object to visit all out-edges of a vertex.
- * @param vertex The vertex of which to return all out-edges.
- * @return An iterable object to visit all out-edges of a vertex.
- */
- [[nodiscard]] iterable_adaptor<out_edge_iterator> out_edges(const vertex_type vertex) const noexcept {
- const auto it = matrix.cbegin();
- const auto from = vertex * vert;
- const auto to = from + vert;
- return {{it, vert, from, to, 1u}, {it, vert, to, to, 1u}};
- }
- /**
- * @brief Returns an iterable object to visit all in-edges of a vertex.
- * @param vertex The vertex of which to return all in-edges.
- * @return An iterable object to visit all in-edges of a vertex.
- */
- [[nodiscard]] iterable_adaptor<in_edge_iterator> in_edges(const vertex_type vertex) const noexcept {
- const auto it = matrix.cbegin();
- const auto from = vertex;
- const auto to = vert * vert + from;
- return {{it, vert, from, to, vert}, {it, vert, to, to, vert}};
- }
- /**
- * @brief Resizes an adjacency matrix.
- * @param vertices The new number of vertices.
- */
- void resize(const size_type vertices) {
- adjacency_matrix other{vertices, get_allocator()};
- for(auto [lhs, rhs]: edges()) {
- other.insert(lhs, rhs);
- }
- other.swap(*this);
- }
- /**
- * @brief Inserts an edge into the adjacency matrix, if it does not exist.
- * @param lhs The left hand vertex of the edge.
- * @param rhs The right hand vertex of the edge.
- * @return A pair consisting of an iterator to the inserted element (or to
- * the element that prevented the insertion) and a bool denoting whether the
- * insertion took place.
- */
- std::pair<edge_iterator, bool> insert(const vertex_type lhs, const vertex_type rhs) {
- const auto pos = lhs * vert + rhs;
- if constexpr(std::is_same_v<graph_category, undirected_tag>) {
- const auto rev = rhs * vert + lhs;
- ENTT_ASSERT(matrix[pos] == matrix[rev], "Something went really wrong");
- matrix[rev] = 1u;
- }
- const auto inserted = !std::exchange(matrix[pos], 1u);
- return {edge_iterator{matrix.cbegin(), vert, pos, matrix.size(), 1u}, inserted};
- }
- /**
- * @brief Removes the edge associated with a pair of given vertices.
- * @param lhs The left hand vertex of the edge.
- * @param rhs The right hand vertex of the edge.
- * @return Number of elements removed (either 0 or 1).
- */
- size_type erase(const vertex_type lhs, const vertex_type rhs) {
- const auto pos = lhs * vert + rhs;
- if constexpr(std::is_same_v<graph_category, undirected_tag>) {
- const auto rev = rhs * vert + lhs;
- ENTT_ASSERT(matrix[pos] == matrix[rev], "Something went really wrong");
- matrix[rev] = 0u;
- }
- return std::exchange(matrix[pos], 0u);
- }
- /**
- * @brief Checks if an adjacency matrix contains a given edge.
- * @param lhs The left hand vertex of the edge.
- * @param rhs The right hand vertex of the edge.
- * @return True if there is such an edge, false otherwise.
- */
- [[nodiscard]] bool contains(const vertex_type lhs, const vertex_type rhs) const {
- const auto pos = lhs * vert + rhs;
- return pos < matrix.size() && matrix[pos];
- }
- private:
- container_type matrix;
- size_type vert;
- };
- } // namespace entt
- #endif
- // #include "graph/dot.hpp"
- #ifndef ENTT_GRAPH_DOT_HPP
- #define ENTT_GRAPH_DOT_HPP
- #include <ostream>
- #include <type_traits>
- // #include "fwd.hpp"
- namespace entt {
- /**
- * @brief Outputs a graph in dot format.
- * @tparam Graph Graph type, valid as long as it exposes edges and vertices.
- * @tparam Writer Vertex decorator type.
- * @param out A standard output stream.
- * @param graph The graph to output.
- * @param writer Vertex decorator object.
- */
- template<typename Graph, typename Writer>
- void dot(std::ostream &out, const Graph &graph, Writer writer) {
- static_assert(std::is_base_of_v<directed_tag, typename Graph::graph_category>, "Invalid graph category");
- if constexpr(std::is_same_v<typename Graph::graph_category, undirected_tag>) {
- out << "graph{";
- } else {
- out << "digraph{";
- }
- for(auto &&vertex: graph.vertices()) {
- out << vertex << "[";
- writer(out, vertex);
- out << "];";
- }
- for(auto [lhs, rhs]: graph.edges()) {
- if constexpr(std::is_same_v<typename Graph::graph_category, undirected_tag>) {
- out << lhs << "--" << rhs << ";";
- } else {
- out << lhs << "->" << rhs << ";";
- }
- }
- out << "}";
- }
- /**
- * @brief Outputs a graph in dot format.
- * @tparam Graph Graph type, valid as long as it exposes edges and vertices.
- * @param out A standard output stream.
- * @param graph The graph to output.
- */
- template<typename Graph>
- void dot(std::ostream &out, const Graph &graph) {
- return dot(out, graph, [](auto &&...) {});
- }
- } // namespace entt
- #endif
- // #include "graph/flow.hpp"
- #ifndef ENTT_GRAPH_FLOW_HPP
- #define ENTT_GRAPH_FLOW_HPP
- #include <algorithm>
- #include <cstddef>
- #include <functional>
- #include <iterator>
- #include <memory>
- #include <type_traits>
- #include <utility>
- #include <vector>
- // #include "../config/config.h"
- // #include "../container/dense_map.hpp"
- #ifndef ENTT_CONTAINER_DENSE_MAP_HPP
- #define ENTT_CONTAINER_DENSE_MAP_HPP
- #include <cmath>
- #include <cstddef>
- #include <functional>
- #include <iterator>
- #include <limits>
- #include <memory>
- #include <tuple>
- #include <type_traits>
- #include <utility>
- #include <vector>
- // #include "../config/config.h"
- #ifndef ENTT_CONFIG_CONFIG_H
- #define ENTT_CONFIG_CONFIG_H
- // #include "version.h"
- #ifndef ENTT_CONFIG_VERSION_H
- #define ENTT_CONFIG_VERSION_H
- // #include "macro.h"
- #ifndef ENTT_CONFIG_MACRO_H
- #define ENTT_CONFIG_MACRO_H
- // NOLINTBEGIN(cppcoreguidelines-macro-usage)
- #define ENTT_STR(arg) #arg
- #define ENTT_XSTR(arg) ENTT_STR(arg)
- // NOLINTEND(cppcoreguidelines-macro-usage)
- #endif
- // NOLINTBEGIN(cppcoreguidelines-macro-*,modernize-macro-*)
- #define ENTT_VERSION_MAJOR 3
- #define ENTT_VERSION_MINOR 16
- #define ENTT_VERSION_PATCH 0
- #define ENTT_VERSION \
- ENTT_XSTR(ENTT_VERSION_MAJOR) \
- "." ENTT_XSTR(ENTT_VERSION_MINOR) "." ENTT_XSTR(ENTT_VERSION_PATCH)
- // NOLINTEND(cppcoreguidelines-macro-*,modernize-macro-*)
- #endif
- // NOLINTBEGIN(cppcoreguidelines-macro-usage)
- #if defined(__cpp_exceptions) && !defined(ENTT_NOEXCEPTION)
- # define ENTT_CONSTEXPR
- # define ENTT_THROW throw
- # define ENTT_TRY try
- # define ENTT_CATCH catch(...)
- #else
- # define ENTT_CONSTEXPR constexpr // use only with throwing functions (waiting for C++20)
- # define ENTT_THROW
- # define ENTT_TRY if(true)
- # define ENTT_CATCH if(false)
- #endif
- #if __has_include(<version>)
- # include <version>
- #
- # if defined(__cpp_consteval)
- # define ENTT_CONSTEVAL consteval
- # endif
- #endif
- #ifndef ENTT_CONSTEVAL
- # define ENTT_CONSTEVAL constexpr
- #endif
- #ifdef ENTT_USE_ATOMIC
- # include <atomic>
- # define ENTT_MAYBE_ATOMIC(Type) std::atomic<Type>
- #else
- # define ENTT_MAYBE_ATOMIC(Type) Type
- #endif
- #ifndef ENTT_ID_TYPE
- # include <cstdint>
- # define ENTT_ID_TYPE std::uint32_t
- #else
- # include <cstdint> // provides coverage for types in the std namespace
- #endif
- #ifndef ENTT_SPARSE_PAGE
- # define ENTT_SPARSE_PAGE 4096
- #endif
- #ifndef ENTT_PACKED_PAGE
- # define ENTT_PACKED_PAGE 1024
- #endif
- #ifdef ENTT_DISABLE_ASSERT
- # undef ENTT_ASSERT
- # define ENTT_ASSERT(condition, msg) (void(0))
- #elif !defined ENTT_ASSERT
- # include <cassert>
- # define ENTT_ASSERT(condition, msg) assert(((condition) && (msg)))
- #endif
- #ifdef ENTT_DISABLE_ASSERT
- # undef ENTT_ASSERT_CONSTEXPR
- # define ENTT_ASSERT_CONSTEXPR(condition, msg) (void(0))
- #elif !defined ENTT_ASSERT_CONSTEXPR
- # define ENTT_ASSERT_CONSTEXPR(condition, msg) ENTT_ASSERT(condition, msg)
- #endif
- #define ENTT_FAIL(msg) ENTT_ASSERT(false, msg);
- #ifdef ENTT_NO_ETO
- # define ENTT_ETO_TYPE(Type) void
- #else
- # define ENTT_ETO_TYPE(Type) Type
- #endif
- #ifdef ENTT_NO_MIXIN
- # define ENTT_STORAGE(Mixin, ...) __VA_ARGS__
- #else
- # define ENTT_STORAGE(Mixin, ...) Mixin<__VA_ARGS__>
- #endif
- #ifdef ENTT_STANDARD_CPP
- # define ENTT_NONSTD false
- #else
- # define ENTT_NONSTD true
- # if defined __clang__ || defined __GNUC__
- # define ENTT_PRETTY_FUNCTION __PRETTY_FUNCTION__
- # define ENTT_PRETTY_FUNCTION_PREFIX '='
- # define ENTT_PRETTY_FUNCTION_SUFFIX ']'
- # elif defined _MSC_VER
- # define ENTT_PRETTY_FUNCTION __FUNCSIG__
- # define ENTT_PRETTY_FUNCTION_PREFIX '<'
- # define ENTT_PRETTY_FUNCTION_SUFFIX '>'
- # endif
- #endif
- #ifndef ENTT_EXPORT
- # if defined _WIN32 || defined __CYGWIN__ || defined _MSC_VER
- # define ENTT_EXPORT __declspec(dllexport)
- # define ENTT_IMPORT __declspec(dllimport)
- # define ENTT_HIDDEN
- # elif defined __GNUC__ && __GNUC__ >= 4
- # define ENTT_EXPORT __attribute__((visibility("default")))
- # define ENTT_IMPORT __attribute__((visibility("default")))
- # define ENTT_HIDDEN __attribute__((visibility("hidden")))
- # else /* Unsupported compiler */
- # define ENTT_EXPORT
- # define ENTT_IMPORT
- # define ENTT_HIDDEN
- # endif
- #endif
- #ifndef ENTT_API
- # if defined ENTT_API_EXPORT
- # define ENTT_API ENTT_EXPORT
- # elif defined ENTT_API_IMPORT
- # define ENTT_API ENTT_IMPORT
- # else /* No API */
- # define ENTT_API
- # endif
- #endif
- #if defined _MSC_VER
- # pragma detect_mismatch("entt.version", ENTT_VERSION)
- # pragma detect_mismatch("entt.noexcept", ENTT_XSTR(ENTT_TRY))
- # pragma detect_mismatch("entt.id", ENTT_XSTR(ENTT_ID_TYPE))
- # pragma detect_mismatch("entt.nonstd", ENTT_XSTR(ENTT_NONSTD))
- #endif
- // NOLINTEND(cppcoreguidelines-macro-usage)
- #endif
- // #include "../core/bit.hpp"
- #ifndef ENTT_CORE_BIT_HPP
- #define ENTT_CORE_BIT_HPP
- #include <cstddef>
- #include <limits>
- #include <type_traits>
- // #include "../config/config.h"
- #ifndef ENTT_CONFIG_CONFIG_H
- #define ENTT_CONFIG_CONFIG_H
- // #include "version.h"
- #ifndef ENTT_CONFIG_VERSION_H
- #define ENTT_CONFIG_VERSION_H
- // #include "macro.h"
- #ifndef ENTT_CONFIG_MACRO_H
- #define ENTT_CONFIG_MACRO_H
- // NOLINTBEGIN(cppcoreguidelines-macro-usage)
- #define ENTT_STR(arg) #arg
- #define ENTT_XSTR(arg) ENTT_STR(arg)
- // NOLINTEND(cppcoreguidelines-macro-usage)
- #endif
- // NOLINTBEGIN(cppcoreguidelines-macro-*,modernize-macro-*)
- #define ENTT_VERSION_MAJOR 3
- #define ENTT_VERSION_MINOR 16
- #define ENTT_VERSION_PATCH 0
- #define ENTT_VERSION \
- ENTT_XSTR(ENTT_VERSION_MAJOR) \
- "." ENTT_XSTR(ENTT_VERSION_MINOR) "." ENTT_XSTR(ENTT_VERSION_PATCH)
- // NOLINTEND(cppcoreguidelines-macro-*,modernize-macro-*)
- #endif
- // NOLINTBEGIN(cppcoreguidelines-macro-usage)
- #if defined(__cpp_exceptions) && !defined(ENTT_NOEXCEPTION)
- # define ENTT_CONSTEXPR
- # define ENTT_THROW throw
- # define ENTT_TRY try
- # define ENTT_CATCH catch(...)
- #else
- # define ENTT_CONSTEXPR constexpr // use only with throwing functions (waiting for C++20)
- # define ENTT_THROW
- # define ENTT_TRY if(true)
- # define ENTT_CATCH if(false)
- #endif
- #if __has_include(<version>)
- # include <version>
- #
- # if defined(__cpp_consteval)
- # define ENTT_CONSTEVAL consteval
- # endif
- #endif
- #ifndef ENTT_CONSTEVAL
- # define ENTT_CONSTEVAL constexpr
- #endif
- #ifdef ENTT_USE_ATOMIC
- # include <atomic>
- # define ENTT_MAYBE_ATOMIC(Type) std::atomic<Type>
- #else
- # define ENTT_MAYBE_ATOMIC(Type) Type
- #endif
- #ifndef ENTT_ID_TYPE
- # include <cstdint>
- # define ENTT_ID_TYPE std::uint32_t
- #else
- # include <cstdint> // provides coverage for types in the std namespace
- #endif
- #ifndef ENTT_SPARSE_PAGE
- # define ENTT_SPARSE_PAGE 4096
- #endif
- #ifndef ENTT_PACKED_PAGE
- # define ENTT_PACKED_PAGE 1024
- #endif
- #ifdef ENTT_DISABLE_ASSERT
- # undef ENTT_ASSERT
- # define ENTT_ASSERT(condition, msg) (void(0))
- #elif !defined ENTT_ASSERT
- # include <cassert>
- # define ENTT_ASSERT(condition, msg) assert(((condition) && (msg)))
- #endif
- #ifdef ENTT_DISABLE_ASSERT
- # undef ENTT_ASSERT_CONSTEXPR
- # define ENTT_ASSERT_CONSTEXPR(condition, msg) (void(0))
- #elif !defined ENTT_ASSERT_CONSTEXPR
- # define ENTT_ASSERT_CONSTEXPR(condition, msg) ENTT_ASSERT(condition, msg)
- #endif
- #define ENTT_FAIL(msg) ENTT_ASSERT(false, msg);
- #ifdef ENTT_NO_ETO
- # define ENTT_ETO_TYPE(Type) void
- #else
- # define ENTT_ETO_TYPE(Type) Type
- #endif
- #ifdef ENTT_NO_MIXIN
- # define ENTT_STORAGE(Mixin, ...) __VA_ARGS__
- #else
- # define ENTT_STORAGE(Mixin, ...) Mixin<__VA_ARGS__>
- #endif
- #ifdef ENTT_STANDARD_CPP
- # define ENTT_NONSTD false
- #else
- # define ENTT_NONSTD true
- # if defined __clang__ || defined __GNUC__
- # define ENTT_PRETTY_FUNCTION __PRETTY_FUNCTION__
- # define ENTT_PRETTY_FUNCTION_PREFIX '='
- # define ENTT_PRETTY_FUNCTION_SUFFIX ']'
- # elif defined _MSC_VER
- # define ENTT_PRETTY_FUNCTION __FUNCSIG__
- # define ENTT_PRETTY_FUNCTION_PREFIX '<'
- # define ENTT_PRETTY_FUNCTION_SUFFIX '>'
- # endif
- #endif
- #ifndef ENTT_EXPORT
- # if defined _WIN32 || defined __CYGWIN__ || defined _MSC_VER
- # define ENTT_EXPORT __declspec(dllexport)
- # define ENTT_IMPORT __declspec(dllimport)
- # define ENTT_HIDDEN
- # elif defined __GNUC__ && __GNUC__ >= 4
- # define ENTT_EXPORT __attribute__((visibility("default")))
- # define ENTT_IMPORT __attribute__((visibility("default")))
- # define ENTT_HIDDEN __attribute__((visibility("hidden")))
- # else /* Unsupported compiler */
- # define ENTT_EXPORT
- # define ENTT_IMPORT
- # define ENTT_HIDDEN
- # endif
- #endif
- #ifndef ENTT_API
- # if defined ENTT_API_EXPORT
- # define ENTT_API ENTT_EXPORT
- # elif defined ENTT_API_IMPORT
- # define ENTT_API ENTT_IMPORT
- # else /* No API */
- # define ENTT_API
- # endif
- #endif
- #if defined _MSC_VER
- # pragma detect_mismatch("entt.version", ENTT_VERSION)
- # pragma detect_mismatch("entt.noexcept", ENTT_XSTR(ENTT_TRY))
- # pragma detect_mismatch("entt.id", ENTT_XSTR(ENTT_ID_TYPE))
- # pragma detect_mismatch("entt.nonstd", ENTT_XSTR(ENTT_NONSTD))
- #endif
- // NOLINTEND(cppcoreguidelines-macro-usage)
- #endif
- namespace entt {
- /**
- * @brief Returns the number of set bits in a value (waiting for C++20 and
- * `std::popcount`).
- * @tparam Type Unsigned integer type.
- * @param value A value of unsigned integer type.
- * @return The number of set bits in the value.
- */
- template<typename Type>
- [[nodiscard]] constexpr std::enable_if_t<std::is_unsigned_v<Type>, int> popcount(const Type value) noexcept {
- return value ? (int(value & 1) + popcount(static_cast<Type>(value >> 1))) : 0;
- }
- /**
- * @brief Checks whether a value is a power of two or not (waiting for C++20 and
- * `std::has_single_bit`).
- * @tparam Type Unsigned integer type.
- * @param value A value of unsigned integer type.
- * @return True if the value is a power of two, false otherwise.
- */
- template<typename Type>
- [[nodiscard]] constexpr std::enable_if_t<std::is_unsigned_v<Type>, bool> has_single_bit(const Type value) noexcept {
- return value && ((value & (value - 1)) == 0);
- }
- /**
- * @brief Computes the smallest power of two greater than or equal to a value
- * (waiting for C++20 and `std::bit_ceil`).
- * @tparam Type Unsigned integer type.
- * @param value A value of unsigned integer type.
- * @return The smallest power of two greater than or equal to the given value.
- */
- template<typename Type>
- [[nodiscard]] constexpr std::enable_if_t<std::is_unsigned_v<Type>, Type> next_power_of_two(const Type value) noexcept {
- // NOLINTNEXTLINE(bugprone-assert-side-effect)
- ENTT_ASSERT_CONSTEXPR(value < (Type{1u} << (std::numeric_limits<Type>::digits - 1)), "Numeric limits exceeded");
- Type curr = value - (value != 0u);
- for(int next = 1; next < std::numeric_limits<Type>::digits; next = next * 2) {
- curr |= (curr >> next);
- }
- return ++curr;
- }
- /**
- * @brief Fast module utility function (powers of two only).
- * @tparam Type Unsigned integer type.
- * @param value A value of unsigned integer type.
- * @param mod _Modulus_, it must be a power of two.
- * @return The common remainder.
- */
- template<typename Type>
- [[nodiscard]] constexpr std::enable_if_t<std::is_unsigned_v<Type>, Type> fast_mod(const Type value, const std::size_t mod) noexcept {
- ENTT_ASSERT_CONSTEXPR(has_single_bit(mod), "Value must be a power of two");
- return static_cast<Type>(value & (mod - 1u));
- }
- } // namespace entt
- #endif
- // #include "../core/compressed_pair.hpp"
- #ifndef ENTT_CORE_COMPRESSED_PAIR_HPP
- #define ENTT_CORE_COMPRESSED_PAIR_HPP
- #include <cstddef>
- #include <tuple>
- #include <type_traits>
- #include <utility>
- // #include "fwd.hpp"
- #ifndef ENTT_CORE_FWD_HPP
- #define ENTT_CORE_FWD_HPP
- #include <cstddef>
- #include <cstdint>
- // #include "../config/config.h"
- namespace entt {
- /*! @brief Possible modes of an any object. */
- enum class any_policy : std::uint8_t {
- /*! @brief Default mode, no element available. */
- empty,
- /*! @brief Owning mode, dynamically allocated element. */
- dynamic,
- /*! @brief Owning mode, embedded element. */
- embedded,
- /*! @brief Aliasing mode, non-const reference. */
- ref,
- /*! @brief Const aliasing mode, const reference. */
- cref
- };
- // NOLINTNEXTLINE(cppcoreguidelines-avoid-c-arrays, modernize-avoid-c-arrays)
- template<std::size_t Len = sizeof(double[2]), std::size_t = alignof(double[2])>
- class basic_any;
- /*! @brief Alias declaration for type identifiers. */
- using id_type = ENTT_ID_TYPE;
- /*! @brief Alias declaration for the most common use case. */
- using any = basic_any<>;
- template<typename, typename>
- class compressed_pair;
- template<typename>
- class basic_hashed_string;
- /*! @brief Aliases for common character types. */
- using hashed_string = basic_hashed_string<char>;
- /*! @brief Aliases for common character types. */
- using hashed_wstring = basic_hashed_string<wchar_t>;
- // NOLINTNEXTLINE(bugprone-forward-declaration-namespace)
- struct type_info;
- } // namespace entt
- #endif
- // #include "type_traits.hpp"
- #ifndef ENTT_CORE_TYPE_TRAITS_HPP
- #define ENTT_CORE_TYPE_TRAITS_HPP
- #include <cstddef>
- #include <iterator>
- #include <tuple>
- #include <type_traits>
- #include <utility>
- // #include "../config/config.h"
- // #include "fwd.hpp"
- namespace entt {
- /**
- * @brief Utility class to disambiguate overloaded functions.
- * @tparam N Number of choices available.
- */
- template<std::size_t N>
- struct choice_t
- // unfortunately, doxygen cannot parse such a construct
- : /*! @cond TURN_OFF_DOXYGEN */ choice_t<N - 1> /*! @endcond */
- {};
- /*! @copybrief choice_t */
- template<>
- struct choice_t<0> {};
- /**
- * @brief Variable template for the choice trick.
- * @tparam N Number of choices available.
- */
- template<std::size_t N>
- inline constexpr choice_t<N> choice{};
- /**
- * @brief Identity type trait.
- *
- * Useful to establish non-deduced contexts in template argument deduction
- * (waiting for C++20) or to provide types through function arguments.
- *
- * @tparam Type A type.
- */
- template<typename Type>
- struct type_identity {
- /*! @brief Identity type. */
- using type = Type;
- };
- /**
- * @brief Helper type.
- * @tparam Type A type.
- */
- template<typename Type>
- using type_identity_t = typename type_identity<Type>::type;
- /**
- * @brief A type-only `sizeof` wrapper that returns 0 where `sizeof` complains.
- * @tparam Type The type of which to return the size.
- */
- template<typename Type, typename = void>
- struct size_of: std::integral_constant<std::size_t, 0u> {};
- /*! @copydoc size_of */
- template<typename Type>
- struct size_of<Type, std::void_t<decltype(sizeof(Type))>>
- // NOLINTNEXTLINE(bugprone-sizeof-expression)
- : std::integral_constant<std::size_t, sizeof(Type)> {};
- /**
- * @brief Helper variable template.
- * @tparam Type The type of which to return the size.
- */
- template<typename Type>
- inline constexpr std::size_t size_of_v = size_of<Type>::value;
- /**
- * @brief Using declaration to be used to _repeat_ the same type a number of
- * times equal to the size of a given parameter pack.
- * @tparam Type A type to repeat.
- */
- template<typename Type, typename>
- using unpack_as_type = Type;
- /**
- * @brief Helper variable template to be used to _repeat_ the same value a
- * number of times equal to the size of a given parameter pack.
- * @tparam Value A value to repeat.
- */
- template<auto Value, typename>
- inline constexpr auto unpack_as_value = Value;
- /**
- * @brief Wraps a static constant.
- * @tparam Value A static constant.
- */
- template<auto Value>
- using integral_constant = std::integral_constant<decltype(Value), Value>;
- /**
- * @brief Alias template to facilitate the creation of named values.
- * @tparam Value A constant value at least convertible to `id_type`.
- */
- template<id_type Value>
- using tag = integral_constant<Value>;
- /**
- * @brief A class to use to push around lists of types, nothing more.
- * @tparam Type Types provided by the type list.
- */
- template<typename... Type>
- struct type_list {
- /*! @brief Type list type. */
- using type = type_list;
- /*! @brief Compile-time number of elements in the type list. */
- static constexpr auto size = sizeof...(Type);
- };
- /*! @brief Primary template isn't defined on purpose. */
- template<std::size_t, typename>
- struct type_list_element;
- /**
- * @brief Provides compile-time indexed access to the types of a type list.
- * @tparam Index Index of the type to return.
- * @tparam First First type provided by the type list.
- * @tparam Other Other types provided by the type list.
- */
- template<std::size_t Index, typename First, typename... Other>
- struct type_list_element<Index, type_list<First, Other...>>
- : type_list_element<Index - 1u, type_list<Other...>> {};
- /**
- * @brief Provides compile-time indexed access to the types of a type list.
- * @tparam First First type provided by the type list.
- * @tparam Other Other types provided by the type list.
- */
- template<typename First, typename... Other>
- struct type_list_element<0u, type_list<First, Other...>> {
- /*! @brief Searched type. */
- using type = First;
- };
- /**
- * @brief Helper type.
- * @tparam Index Index of the type to return.
- * @tparam List Type list to search into.
- */
- template<std::size_t Index, typename List>
- using type_list_element_t = typename type_list_element<Index, List>::type;
- /*! @brief Primary template isn't defined on purpose. */
- template<typename, typename>
- struct type_list_index;
- /**
- * @brief Provides compile-time type access to the types of a type list.
- * @tparam Type Type to look for and for which to return the index.
- * @tparam First First type provided by the type list.
- * @tparam Other Other types provided by the type list.
- */
- template<typename Type, typename First, typename... Other>
- struct type_list_index<Type, type_list<First, Other...>> {
- /*! @brief Unsigned integer type. */
- using value_type = std::size_t;
- /*! @brief Compile-time position of the given type in the sublist. */
- static constexpr value_type value = 1u + type_list_index<Type, type_list<Other...>>::value;
- };
- /**
- * @brief Provides compile-time type access to the types of a type list.
- * @tparam Type Type to look for and for which to return the index.
- * @tparam Other Other types provided by the type list.
- */
- template<typename Type, typename... Other>
- struct type_list_index<Type, type_list<Type, Other...>> {
- static_assert(type_list_index<Type, type_list<Other...>>::value == sizeof...(Other), "Non-unique type");
- /*! @brief Unsigned integer type. */
- using value_type = std::size_t;
- /*! @brief Compile-time position of the given type in the sublist. */
- static constexpr value_type value = 0u;
- };
- /**
- * @brief Provides compile-time type access to the types of a type list.
- * @tparam Type Type to look for and for which to return the index.
- */
- template<typename Type>
- struct type_list_index<Type, type_list<>> {
- /*! @brief Unsigned integer type. */
- using value_type = std::size_t;
- /*! @brief Compile-time position of the given type in the sublist. */
- static constexpr value_type value = 0u;
- };
- /**
- * @brief Helper variable template.
- * @tparam List Type list.
- * @tparam Type Type to look for and for which to return the index.
- */
- template<typename Type, typename List>
- inline constexpr std::size_t type_list_index_v = type_list_index<Type, List>::value;
- /**
- * @brief Concatenates multiple type lists.
- * @tparam Type Types provided by the first type list.
- * @tparam Other Types provided by the second type list.
- * @return A type list composed by the types of both the type lists.
- */
- template<typename... Type, typename... Other>
- constexpr type_list<Type..., Other...> operator+(type_list<Type...>, type_list<Other...>) {
- return {};
- }
- /*! @brief Primary template isn't defined on purpose. */
- template<typename...>
- struct type_list_cat;
- /*! @brief Concatenates multiple type lists. */
- template<>
- struct type_list_cat<> {
- /*! @brief A type list composed by the types of all the type lists. */
- using type = type_list<>;
- };
- /**
- * @brief Concatenates multiple type lists.
- * @tparam Type Types provided by the first type list.
- * @tparam Other Types provided by the second type list.
- * @tparam List Other type lists, if any.
- */
- template<typename... Type, typename... Other, typename... List>
- struct type_list_cat<type_list<Type...>, type_list<Other...>, List...> {
- /*! @brief A type list composed by the types of all the type lists. */
- using type = typename type_list_cat<type_list<Type..., Other...>, List...>::type;
- };
- /**
- * @brief Concatenates multiple type lists.
- * @tparam Type Types provided by the type list.
- */
- template<typename... Type>
- struct type_list_cat<type_list<Type...>> {
- /*! @brief A type list composed by the types of all the type lists. */
- using type = type_list<Type...>;
- };
- /**
- * @brief Helper type.
- * @tparam List Type lists to concatenate.
- */
- template<typename... List>
- using type_list_cat_t = typename type_list_cat<List...>::type;
- /*! @cond TURN_OFF_DOXYGEN */
- namespace internal {
- template<typename...>
- struct type_list_unique;
- template<typename First, typename... Other, typename... Type>
- struct type_list_unique<type_list<First, Other...>, Type...>
- : std::conditional_t<(std::is_same_v<First, Type> || ...), type_list_unique<type_list<Other...>, Type...>, type_list_unique<type_list<Other...>, Type..., First>> {};
- template<typename... Type>
- struct type_list_unique<type_list<>, Type...> {
- using type = type_list<Type...>;
- };
- } // namespace internal
- /*! @endcond */
- /**
- * @brief Removes duplicates types from a type list.
- * @tparam List Type list.
- */
- template<typename List>
- struct type_list_unique {
- /*! @brief A type list without duplicate types. */
- using type = typename internal::type_list_unique<List>::type;
- };
- /**
- * @brief Helper type.
- * @tparam List Type list.
- */
- template<typename List>
- using type_list_unique_t = typename type_list_unique<List>::type;
- /**
- * @brief Provides the member constant `value` to true if a type list contains a
- * given type, false otherwise.
- * @tparam List Type list.
- * @tparam Type Type to look for.
- */
- template<typename List, typename Type>
- struct type_list_contains;
- /**
- * @copybrief type_list_contains
- * @tparam Type Types provided by the type list.
- * @tparam Other Type to look for.
- */
- template<typename... Type, typename Other>
- struct type_list_contains<type_list<Type...>, Other>
- : std::bool_constant<(std::is_same_v<Type, Other> || ...)> {};
- /**
- * @brief Helper variable template.
- * @tparam List Type list.
- * @tparam Type Type to look for.
- */
- template<typename List, typename Type>
- inline constexpr bool type_list_contains_v = type_list_contains<List, Type>::value;
- /*! @brief Primary template isn't defined on purpose. */
- template<typename...>
- struct type_list_diff;
- /**
- * @brief Computes the difference between two type lists.
- * @tparam Type Types provided by the first type list.
- * @tparam Other Types provided by the second type list.
- */
- template<typename... Type, typename... Other>
- struct type_list_diff<type_list<Type...>, type_list<Other...>> {
- /*! @brief A type list that is the difference between the two type lists. */
- using type = type_list_cat_t<std::conditional_t<type_list_contains_v<type_list<Other...>, Type>, type_list<>, type_list<Type>>...>;
- };
- /**
- * @brief Helper type.
- * @tparam List Type lists between which to compute the difference.
- */
- template<typename... List>
- using type_list_diff_t = typename type_list_diff<List...>::type;
- /*! @brief Primary template isn't defined on purpose. */
- template<typename, template<typename...> class>
- struct type_list_transform;
- /**
- * @brief Applies a given _function_ to a type list and generate a new list.
- * @tparam Type Types provided by the type list.
- * @tparam Op Unary operation as template class with a type member named `type`.
- */
- template<typename... Type, template<typename...> class Op>
- struct type_list_transform<type_list<Type...>, Op> {
- /*! @brief Resulting type list after applying the transform function. */
- // NOLINTNEXTLINE(modernize-type-traits)
- using type = type_list<typename Op<Type>::type...>;
- };
- /**
- * @brief Helper type.
- * @tparam List Type list.
- * @tparam Op Unary operation as template class with a type member named `type`.
- */
- template<typename List, template<typename...> class Op>
- using type_list_transform_t = typename type_list_transform<List, Op>::type;
- /**
- * @brief A class to use to push around lists of constant values, nothing more.
- * @tparam Value Values provided by the value list.
- */
- template<auto... Value>
- struct value_list {
- /*! @brief Value list type. */
- using type = value_list;
- /*! @brief Compile-time number of elements in the value list. */
- static constexpr auto size = sizeof...(Value);
- };
- /*! @brief Primary template isn't defined on purpose. */
- template<std::size_t, typename>
- struct value_list_element;
- /**
- * @brief Provides compile-time indexed access to the values of a value list.
- * @tparam Index Index of the value to return.
- * @tparam Value First value provided by the value list.
- * @tparam Other Other values provided by the value list.
- */
- template<std::size_t Index, auto Value, auto... Other>
- struct value_list_element<Index, value_list<Value, Other...>>
- : value_list_element<Index - 1u, value_list<Other...>> {};
- /**
- * @brief Provides compile-time indexed access to the types of a type list.
- * @tparam Value First value provided by the value list.
- * @tparam Other Other values provided by the value list.
- */
- template<auto Value, auto... Other>
- struct value_list_element<0u, value_list<Value, Other...>> {
- /*! @brief Searched type. */
- using type = decltype(Value);
- /*! @brief Searched value. */
- static constexpr auto value = Value;
- };
- /**
- * @brief Helper type.
- * @tparam Index Index of the type to return.
- * @tparam List Value list to search into.
- */
- template<std::size_t Index, typename List>
- using value_list_element_t = typename value_list_element<Index, List>::type;
- /**
- * @brief Helper type.
- * @tparam Index Index of the value to return.
- * @tparam List Value list to search into.
- */
- template<std::size_t Index, typename List>
- inline constexpr auto value_list_element_v = value_list_element<Index, List>::value;
- /*! @brief Primary template isn't defined on purpose. */
- template<auto, typename>
- struct value_list_index;
- /**
- * @brief Provides compile-time type access to the values of a value list.
- * @tparam Value Value to look for and for which to return the index.
- * @tparam First First value provided by the value list.
- * @tparam Other Other values provided by the value list.
- */
- template<auto Value, auto First, auto... Other>
- struct value_list_index<Value, value_list<First, Other...>> {
- /*! @brief Unsigned integer type. */
- using value_type = std::size_t;
- /*! @brief Compile-time position of the given value in the sublist. */
- static constexpr value_type value = 1u + value_list_index<Value, value_list<Other...>>::value;
- };
- /**
- * @brief Provides compile-time type access to the values of a value list.
- * @tparam Value Value to look for and for which to return the index.
- * @tparam Other Other values provided by the value list.
- */
- template<auto Value, auto... Other>
- struct value_list_index<Value, value_list<Value, Other...>> {
- static_assert(value_list_index<Value, value_list<Other...>>::value == sizeof...(Other), "Non-unique type");
- /*! @brief Unsigned integer type. */
- using value_type = std::size_t;
- /*! @brief Compile-time position of the given value in the sublist. */
- static constexpr value_type value = 0u;
- };
- /**
- * @brief Provides compile-time type access to the values of a value list.
- * @tparam Value Value to look for and for which to return the index.
- */
- template<auto Value>
- struct value_list_index<Value, value_list<>> {
- /*! @brief Unsigned integer type. */
- using value_type = std::size_t;
- /*! @brief Compile-time position of the given type in the sublist. */
- static constexpr value_type value = 0u;
- };
- /**
- * @brief Helper variable template.
- * @tparam List Value list.
- * @tparam Value Value to look for and for which to return the index.
- */
- template<auto Value, typename List>
- inline constexpr std::size_t value_list_index_v = value_list_index<Value, List>::value;
- /**
- * @brief Concatenates multiple value lists.
- * @tparam Value Values provided by the first value list.
- * @tparam Other Values provided by the second value list.
- * @return A value list composed by the values of both the value lists.
- */
- template<auto... Value, auto... Other>
- constexpr value_list<Value..., Other...> operator+(value_list<Value...>, value_list<Other...>) {
- return {};
- }
- /*! @brief Primary template isn't defined on purpose. */
- template<typename...>
- struct value_list_cat;
- /*! @brief Concatenates multiple value lists. */
- template<>
- struct value_list_cat<> {
- /*! @brief A value list composed by the values of all the value lists. */
- using type = value_list<>;
- };
- /**
- * @brief Concatenates multiple value lists.
- * @tparam Value Values provided by the first value list.
- * @tparam Other Values provided by the second value list.
- * @tparam List Other value lists, if any.
- */
- template<auto... Value, auto... Other, typename... List>
- struct value_list_cat<value_list<Value...>, value_list<Other...>, List...> {
- /*! @brief A value list composed by the values of all the value lists. */
- using type = typename value_list_cat<value_list<Value..., Other...>, List...>::type;
- };
- /**
- * @brief Concatenates multiple value lists.
- * @tparam Value Values provided by the value list.
- */
- template<auto... Value>
- struct value_list_cat<value_list<Value...>> {
- /*! @brief A value list composed by the values of all the value lists. */
- using type = value_list<Value...>;
- };
- /**
- * @brief Helper type.
- * @tparam List Value lists to concatenate.
- */
- template<typename... List>
- using value_list_cat_t = typename value_list_cat<List...>::type;
- /*! @brief Primary template isn't defined on purpose. */
- template<typename>
- struct value_list_unique;
- /**
- * @brief Removes duplicates values from a value list.
- * @tparam Value One of the values provided by the given value list.
- * @tparam Other The other values provided by the given value list.
- */
- template<auto Value, auto... Other>
- struct value_list_unique<value_list<Value, Other...>> {
- /*! @brief A value list without duplicate types. */
- using type = std::conditional_t<
- ((Value == Other) || ...),
- typename value_list_unique<value_list<Other...>>::type,
- value_list_cat_t<value_list<Value>, typename value_list_unique<value_list<Other...>>::type>>;
- };
- /*! @brief Removes duplicates values from a value list. */
- template<>
- struct value_list_unique<value_list<>> {
- /*! @brief A value list without duplicate types. */
- using type = value_list<>;
- };
- /**
- * @brief Helper type.
- * @tparam Type A value list.
- */
- template<typename Type>
- using value_list_unique_t = typename value_list_unique<Type>::type;
- /**
- * @brief Provides the member constant `value` to true if a value list contains
- * a given value, false otherwise.
- * @tparam List Value list.
- * @tparam Value Value to look for.
- */
- template<typename List, auto Value>
- struct value_list_contains;
- /**
- * @copybrief value_list_contains
- * @tparam Value Values provided by the value list.
- * @tparam Other Value to look for.
- */
- template<auto... Value, auto Other>
- struct value_list_contains<value_list<Value...>, Other>
- : std::bool_constant<((Value == Other) || ...)> {};
- /**
- * @brief Helper variable template.
- * @tparam List Value list.
- * @tparam Value Value to look for.
- */
- template<typename List, auto Value>
- inline constexpr bool value_list_contains_v = value_list_contains<List, Value>::value;
- /*! @brief Primary template isn't defined on purpose. */
- template<typename...>
- struct value_list_diff;
- /**
- * @brief Computes the difference between two value lists.
- * @tparam Value Values provided by the first value list.
- * @tparam Other Values provided by the second value list.
- */
- template<auto... Value, auto... Other>
- struct value_list_diff<value_list<Value...>, value_list<Other...>> {
- /*! @brief A value list that is the difference between the two value lists. */
- using type = value_list_cat_t<std::conditional_t<value_list_contains_v<value_list<Other...>, Value>, value_list<>, value_list<Value>>...>;
- };
- /**
- * @brief Helper type.
- * @tparam List Value lists between which to compute the difference.
- */
- template<typename... List>
- using value_list_diff_t = typename value_list_diff<List...>::type;
- /*! @brief Same as std::is_invocable, but with tuples. */
- template<typename, typename>
- struct is_applicable: std::false_type {};
- /**
- * @copybrief is_applicable
- * @tparam Func A valid function type.
- * @tparam Tuple Tuple-like type.
- * @tparam Args The list of arguments to use to probe the function type.
- */
- template<typename Func, template<typename...> class Tuple, typename... Args>
- struct is_applicable<Func, Tuple<Args...>>: std::is_invocable<Func, Args...> {};
- /**
- * @copybrief is_applicable
- * @tparam Func A valid function type.
- * @tparam Tuple Tuple-like type.
- * @tparam Args The list of arguments to use to probe the function type.
- */
- template<typename Func, template<typename...> class Tuple, typename... Args>
- struct is_applicable<Func, const Tuple<Args...>>: std::is_invocable<Func, Args...> {};
- /**
- * @brief Helper variable template.
- * @tparam Func A valid function type.
- * @tparam Args The list of arguments to use to probe the function type.
- */
- template<typename Func, typename Args>
- inline constexpr bool is_applicable_v = is_applicable<Func, Args>::value;
- /*! @brief Same as std::is_invocable_r, but with tuples for arguments. */
- template<typename, typename, typename>
- struct is_applicable_r: std::false_type {};
- /**
- * @copybrief is_applicable_r
- * @tparam Ret The type to which the return type of the function should be
- * convertible.
- * @tparam Func A valid function type.
- * @tparam Args The list of arguments to use to probe the function type.
- */
- template<typename Ret, typename Func, typename... Args>
- struct is_applicable_r<Ret, Func, std::tuple<Args...>>: std::is_invocable_r<Ret, Func, Args...> {};
- /**
- * @brief Helper variable template.
- * @tparam Ret The type to which the return type of the function should be
- * convertible.
- * @tparam Func A valid function type.
- * @tparam Args The list of arguments to use to probe the function type.
- */
- template<typename Ret, typename Func, typename Args>
- inline constexpr bool is_applicable_r_v = is_applicable_r<Ret, Func, Args>::value;
- /**
- * @brief Provides the member constant `value` to true if a given type is
- * complete, false otherwise.
- * @tparam Type The type to test.
- */
- template<typename Type, typename = void>
- struct is_complete: std::false_type {};
- /*! @copydoc is_complete */
- template<typename Type>
- struct is_complete<Type, std::void_t<decltype(sizeof(Type))>>: std::true_type {};
- /**
- * @brief Helper variable template.
- * @tparam Type The type to test.
- */
- template<typename Type>
- inline constexpr bool is_complete_v = is_complete<Type>::value;
- /**
- * @brief Provides the member constant `value` to true if a given type is an
- * iterator, false otherwise.
- * @tparam Type The type to test.
- */
- template<typename Type, typename = void>
- struct is_iterator: std::false_type {};
- /*! @cond TURN_OFF_DOXYGEN */
- namespace internal {
- template<typename, typename = void>
- struct has_iterator_category: std::false_type {};
- template<typename Type>
- struct has_iterator_category<Type, std::void_t<typename std::iterator_traits<Type>::iterator_category>>: std::true_type {};
- } // namespace internal
- /*! @endcond */
- /*! @copydoc is_iterator */
- template<typename Type>
- struct is_iterator<Type, std::enable_if_t<!std::is_void_v<std::remove_const_t<std::remove_pointer_t<Type>>>>>
- : internal::has_iterator_category<Type> {};
- /**
- * @brief Helper variable template.
- * @tparam Type The type to test.
- */
- template<typename Type>
- inline constexpr bool is_iterator_v = is_iterator<Type>::value;
- /**
- * @brief Provides the member constant `value` to true if a given type is both
- * an empty and non-final class, false otherwise.
- * @tparam Type The type to test
- */
- template<typename Type>
- struct is_ebco_eligible
- : std::bool_constant<std::is_empty_v<Type> && !std::is_final_v<Type>> {};
- /**
- * @brief Helper variable template.
- * @tparam Type The type to test.
- */
- template<typename Type>
- inline constexpr bool is_ebco_eligible_v = is_ebco_eligible<Type>::value;
- /**
- * @brief Provides the member constant `value` to true if `Type::is_transparent`
- * is valid and denotes a type, false otherwise.
- * @tparam Type The type to test.
- */
- template<typename Type, typename = void>
- struct is_transparent: std::false_type {};
- /*! @copydoc is_transparent */
- template<typename Type>
- struct is_transparent<Type, std::void_t<typename Type::is_transparent>>: std::true_type {};
- /**
- * @brief Helper variable template.
- * @tparam Type The type to test.
- */
- template<typename Type>
- inline constexpr bool is_transparent_v = is_transparent<Type>::value;
- /*! @cond TURN_OFF_DOXYGEN */
- namespace internal {
- template<typename, typename = void>
- struct has_tuple_size_value: std::false_type {};
- template<typename Type>
- struct has_tuple_size_value<Type, std::void_t<decltype(std::tuple_size<const Type>::value)>>: std::true_type {};
- template<typename, typename = void>
- struct has_value_type: std::false_type {};
- template<typename Type>
- struct has_value_type<Type, std::void_t<typename Type::value_type>>: std::true_type {};
- template<typename>
- [[nodiscard]] constexpr bool dispatch_is_equality_comparable();
- template<typename Type, std::size_t... Index>
- [[nodiscard]] constexpr bool unpack_maybe_equality_comparable(std::index_sequence<Index...>) {
- return (dispatch_is_equality_comparable<std::tuple_element_t<Index, Type>>() && ...);
- }
- template<typename>
- [[nodiscard]] constexpr bool maybe_equality_comparable(char) {
- return false;
- }
- template<typename Type>
- [[nodiscard]] constexpr auto maybe_equality_comparable(int) -> decltype(std::declval<Type>() == std::declval<Type>()) {
- return true;
- }
- template<typename Type>
- [[nodiscard]] constexpr bool dispatch_is_equality_comparable() {
- // NOLINTBEGIN(modernize-use-transparent-functors)
- if constexpr(std::is_array_v<Type>) {
- return false;
- } else if constexpr(is_complete_v<std::tuple_size<std::remove_const_t<Type>>>) {
- if constexpr(has_tuple_size_value<Type>::value) {
- return maybe_equality_comparable<Type>(0) && unpack_maybe_equality_comparable<Type>(std::make_index_sequence<std::tuple_size<Type>::value>{});
- } else {
- return maybe_equality_comparable<Type>(0);
- }
- } else if constexpr(has_value_type<Type>::value) {
- if constexpr(is_iterator_v<Type> || std::is_same_v<typename Type::value_type, Type> || dispatch_is_equality_comparable<typename Type::value_type>()) {
- return maybe_equality_comparable<Type>(0);
- } else {
- return false;
- }
- } else {
- return maybe_equality_comparable<Type>(0);
- }
- // NOLINTEND(modernize-use-transparent-functors)
- }
- } // namespace internal
- /*! @endcond */
- /**
- * @brief Provides the member constant `value` to true if a given type is
- * equality comparable, false otherwise.
- * @tparam Type The type to test.
- */
- template<typename Type>
- struct is_equality_comparable: std::bool_constant<internal::dispatch_is_equality_comparable<Type>()> {};
- /*! @copydoc is_equality_comparable */
- template<typename Type>
- struct is_equality_comparable<const Type>: is_equality_comparable<Type> {};
- /**
- * @brief Helper variable template.
- * @tparam Type The type to test.
- */
- template<typename Type>
- inline constexpr bool is_equality_comparable_v = is_equality_comparable<Type>::value;
- /**
- * @brief Transcribes the constness of a type to another type.
- * @tparam To The type to which to transcribe the constness.
- * @tparam From The type from which to transcribe the constness.
- */
- template<typename To, typename From>
- struct constness_as {
- /*! @brief The type resulting from the transcription of the constness. */
- using type = std::remove_const_t<To>;
- };
- /*! @copydoc constness_as */
- template<typename To, typename From>
- struct constness_as<To, const From> {
- /*! @brief The type resulting from the transcription of the constness. */
- using type = const To;
- };
- /**
- * @brief Alias template to facilitate the transcription of the constness.
- * @tparam To The type to which to transcribe the constness.
- * @tparam From The type from which to transcribe the constness.
- */
- template<typename To, typename From>
- using constness_as_t = typename constness_as<To, From>::type;
- /**
- * @brief Extracts the class of a non-static member object or function.
- * @tparam Member A pointer to a non-static member object or function.
- */
- template<typename Member>
- class member_class {
- static_assert(std::is_member_pointer_v<Member>, "Invalid pointer type to non-static member object or function");
- template<typename Class, typename Ret, typename... Args>
- static Class *clazz(Ret (Class::*)(Args...));
- template<typename Class, typename Ret, typename... Args>
- static Class *clazz(Ret (Class::*)(Args...) const);
- template<typename Class, typename Type>
- static Class *clazz(Type Class::*);
- public:
- /*! @brief The class of the given non-static member object or function. */
- using type = std::remove_pointer_t<decltype(clazz(std::declval<Member>()))>;
- };
- /**
- * @brief Helper type.
- * @tparam Member A pointer to a non-static member object or function.
- */
- template<typename Member>
- using member_class_t = typename member_class<Member>::type;
- /**
- * @brief Extracts the n-th argument of a _callable_ type.
- * @tparam Index The index of the argument to extract.
- * @tparam Candidate A valid _callable_ type.
- */
- template<std::size_t Index, typename Candidate>
- class nth_argument {
- template<typename Ret, typename... Args>
- static constexpr type_list<Args...> pick_up(Ret (*)(Args...));
- template<typename Ret, typename Class, typename... Args>
- static constexpr type_list<Args...> pick_up(Ret (Class ::*)(Args...));
- template<typename Ret, typename Class, typename... Args>
- static constexpr type_list<Args...> pick_up(Ret (Class ::*)(Args...) const);
- template<typename Type, typename Class>
- static constexpr type_list<Type> pick_up(Type Class ::*);
- template<typename Type>
- static constexpr decltype(pick_up(&Type::operator())) pick_up(Type &&);
- public:
- /*! @brief N-th argument of the _callable_ type. */
- using type = type_list_element_t<Index, decltype(pick_up(std::declval<Candidate>()))>;
- };
- /**
- * @brief Helper type.
- * @tparam Index The index of the argument to extract.
- * @tparam Candidate A valid function, member function or data member type.
- */
- template<std::size_t Index, typename Candidate>
- using nth_argument_t = typename nth_argument<Index, Candidate>::type;
- } // namespace entt
- template<typename... Type>
- struct std::tuple_size<entt::type_list<Type...>>: std::integral_constant<std::size_t, entt::type_list<Type...>::size> {};
- template<std::size_t Index, typename... Type>
- struct std::tuple_element<Index, entt::type_list<Type...>>: entt::type_list_element<Index, entt::type_list<Type...>> {};
- template<auto... Value>
- struct std::tuple_size<entt::value_list<Value...>>: std::integral_constant<std::size_t, entt::value_list<Value...>::size> {};
- template<std::size_t Index, auto... Value>
- struct std::tuple_element<Index, entt::value_list<Value...>>: entt::value_list_element<Index, entt::value_list<Value...>> {};
- #endif
- namespace entt {
- /*! @cond TURN_OFF_DOXYGEN */
- namespace internal {
- template<typename Type, std::size_t, typename = void>
- struct compressed_pair_element {
- using reference = Type &;
- using const_reference = const Type &;
- template<typename Dummy = Type, typename = std::enable_if_t<std::is_default_constructible_v<Dummy>>>
- // NOLINTNEXTLINE(modernize-use-equals-default)
- constexpr compressed_pair_element() noexcept(std::is_nothrow_default_constructible_v<Type>) {}
- template<typename Arg, typename = std::enable_if_t<!std::is_same_v<std::remove_const_t<std::remove_reference_t<Arg>>, compressed_pair_element>>>
- constexpr compressed_pair_element(Arg &&arg) noexcept(std::is_nothrow_constructible_v<Type, Arg>)
- : value{std::forward<Arg>(arg)} {}
- template<typename... Args, std::size_t... Index>
- constexpr compressed_pair_element(std::tuple<Args...> args, std::index_sequence<Index...>) noexcept(std::is_nothrow_constructible_v<Type, Args...>)
- : value{std::forward<Args>(std::get<Index>(args))...} {}
- [[nodiscard]] constexpr reference get() noexcept {
- return value;
- }
- [[nodiscard]] constexpr const_reference get() const noexcept {
- return value;
- }
- private:
- Type value{};
- };
- template<typename Type, std::size_t Tag>
- struct compressed_pair_element<Type, Tag, std::enable_if_t<is_ebco_eligible_v<Type>>>: Type {
- using reference = Type &;
- using const_reference = const Type &;
- using base_type = Type;
- template<typename Dummy = Type, typename = std::enable_if_t<std::is_default_constructible_v<Dummy>>>
- constexpr compressed_pair_element() noexcept(std::is_nothrow_default_constructible_v<base_type>)
- : base_type{} {}
- template<typename Arg, typename = std::enable_if_t<!std::is_same_v<std::remove_const_t<std::remove_reference_t<Arg>>, compressed_pair_element>>>
- constexpr compressed_pair_element(Arg &&arg) noexcept(std::is_nothrow_constructible_v<base_type, Arg>)
- : base_type{std::forward<Arg>(arg)} {}
- template<typename... Args, std::size_t... Index>
- constexpr compressed_pair_element(std::tuple<Args...> args, std::index_sequence<Index...>) noexcept(std::is_nothrow_constructible_v<base_type, Args...>)
- : base_type{std::forward<Args>(std::get<Index>(args))...} {}
- [[nodiscard]] constexpr reference get() noexcept {
- return *this;
- }
- [[nodiscard]] constexpr const_reference get() const noexcept {
- return *this;
- }
- };
- } // namespace internal
- /*! @endcond */
- /**
- * @brief A compressed pair.
- *
- * A pair that exploits the _Empty Base Class Optimization_ (or _EBCO_) to
- * reduce its final size to a minimum.
- *
- * @tparam First The type of the first element that the pair stores.
- * @tparam Second The type of the second element that the pair stores.
- */
- template<typename First, typename Second>
- class compressed_pair final
- : internal::compressed_pair_element<First, 0u>,
- internal::compressed_pair_element<Second, 1u> {
- using first_base = internal::compressed_pair_element<First, 0u>;
- using second_base = internal::compressed_pair_element<Second, 1u>;
- public:
- /*! @brief The type of the first element that the pair stores. */
- using first_type = First;
- /*! @brief The type of the second element that the pair stores. */
- using second_type = Second;
- /**
- * @brief Default constructor, conditionally enabled.
- *
- * This constructor is only available when the types that the pair stores
- * are both at least default constructible.
- *
- * @tparam Dummy Dummy template parameter used for internal purposes.
- */
- template<bool Dummy = true, typename = std::enable_if_t<Dummy && std::is_default_constructible_v<first_type> && std::is_default_constructible_v<second_type>>>
- constexpr compressed_pair() noexcept(std::is_nothrow_default_constructible_v<first_base> && std::is_nothrow_default_constructible_v<second_base>)
- : first_base{},
- second_base{} {}
- /**
- * @brief Copy constructor.
- * @param other The instance to copy from.
- */
- constexpr compressed_pair(const compressed_pair &other) = default;
- /**
- * @brief Move constructor.
- * @param other The instance to move from.
- */
- constexpr compressed_pair(compressed_pair &&other) noexcept = default;
- /**
- * @brief Constructs a pair from its values.
- * @tparam Arg Type of value to use to initialize the first element.
- * @tparam Other Type of value to use to initialize the second element.
- * @param arg Value to use to initialize the first element.
- * @param other Value to use to initialize the second element.
- */
- template<typename Arg, typename Other>
- constexpr compressed_pair(Arg &&arg, Other &&other) noexcept(std::is_nothrow_constructible_v<first_base, Arg> && std::is_nothrow_constructible_v<second_base, Other>)
- : first_base{std::forward<Arg>(arg)},
- second_base{std::forward<Other>(other)} {}
- /**
- * @brief Constructs a pair by forwarding the arguments to its parts.
- * @tparam Args Types of arguments to use to initialize the first element.
- * @tparam Other Types of arguments to use to initialize the second element.
- * @param args Arguments to use to initialize the first element.
- * @param other Arguments to use to initialize the second element.
- */
- template<typename... Args, typename... Other>
- constexpr compressed_pair(std::piecewise_construct_t, std::tuple<Args...> args, std::tuple<Other...> other) noexcept(std::is_nothrow_constructible_v<first_base, Args...> && std::is_nothrow_constructible_v<second_base, Other...>)
- : first_base{std::move(args), std::index_sequence_for<Args...>{}},
- second_base{std::move(other), std::index_sequence_for<Other...>{}} {}
- /*! @brief Default destructor. */
- ~compressed_pair() = default;
- /**
- * @brief Copy assignment operator.
- * @param other The instance to copy from.
- * @return This compressed pair object.
- */
- constexpr compressed_pair &operator=(const compressed_pair &other) = default;
- /**
- * @brief Move assignment operator.
- * @param other The instance to move from.
- * @return This compressed pair object.
- */
- constexpr compressed_pair &operator=(compressed_pair &&other) noexcept = default;
- /**
- * @brief Returns the first element that a pair stores.
- * @return The first element that a pair stores.
- */
- [[nodiscard]] constexpr first_type &first() noexcept {
- return static_cast<first_base &>(*this).get();
- }
- /*! @copydoc first */
- [[nodiscard]] constexpr const first_type &first() const noexcept {
- return static_cast<const first_base &>(*this).get();
- }
- /**
- * @brief Returns the second element that a pair stores.
- * @return The second element that a pair stores.
- */
- [[nodiscard]] constexpr second_type &second() noexcept {
- return static_cast<second_base &>(*this).get();
- }
- /*! @copydoc second */
- [[nodiscard]] constexpr const second_type &second() const noexcept {
- return static_cast<const second_base &>(*this).get();
- }
- /**
- * @brief Swaps two compressed pair objects.
- * @param other The compressed pair to swap with.
- */
- constexpr void swap(compressed_pair &other) noexcept {
- using std::swap;
- swap(first(), other.first());
- swap(second(), other.second());
- }
- /**
- * @brief Extracts an element from the compressed pair.
- * @tparam Index An integer value that is either 0 or 1.
- * @return Returns a reference to the first element if `Index` is 0 and a
- * reference to the second element if `Index` is 1.
- */
- template<std::size_t Index>
- [[nodiscard]] constexpr decltype(auto) get() noexcept {
- if constexpr(Index == 0u) {
- return first();
- } else {
- static_assert(Index == 1u, "Index out of bounds");
- return second();
- }
- }
- /*! @copydoc get */
- template<std::size_t Index>
- [[nodiscard]] constexpr decltype(auto) get() const noexcept {
- if constexpr(Index == 0u) {
- return first();
- } else {
- static_assert(Index == 1u, "Index out of bounds");
- return second();
- }
- }
- };
- /**
- * @brief Deduction guide.
- * @tparam Type Type of value to use to initialize the first element.
- * @tparam Other Type of value to use to initialize the second element.
- */
- template<typename Type, typename Other>
- compressed_pair(Type &&, Other &&) -> compressed_pair<std::decay_t<Type>, std::decay_t<Other>>;
- /**
- * @brief Swaps two compressed pair objects.
- * @tparam First The type of the first element that the pairs store.
- * @tparam Second The type of the second element that the pairs store.
- * @param lhs A valid compressed pair object.
- * @param rhs A valid compressed pair object.
- */
- template<typename First, typename Second>
- constexpr void swap(compressed_pair<First, Second> &lhs, compressed_pair<First, Second> &rhs) noexcept {
- lhs.swap(rhs);
- }
- } // namespace entt
- namespace std {
- /**
- * @brief `std::tuple_size` specialization for `compressed_pair`s.
- * @tparam First The type of the first element that the pair stores.
- * @tparam Second The type of the second element that the pair stores.
- */
- template<typename First, typename Second>
- struct tuple_size<entt::compressed_pair<First, Second>>: integral_constant<size_t, 2u> {};
- /**
- * @brief `std::tuple_element` specialization for `compressed_pair`s.
- * @tparam Index The index of the type to return.
- * @tparam First The type of the first element that the pair stores.
- * @tparam Second The type of the second element that the pair stores.
- */
- template<size_t Index, typename First, typename Second>
- struct tuple_element<Index, entt::compressed_pair<First, Second>>: conditional<Index == 0u, First, Second> {
- static_assert(Index < 2u, "Index out of bounds");
- };
- } // namespace std
- #endif
- // #include "../core/iterator.hpp"
- #ifndef ENTT_CORE_ITERATOR_HPP
- #define ENTT_CORE_ITERATOR_HPP
- #include <iterator>
- #include <memory>
- #include <type_traits>
- #include <utility>
- namespace entt {
- /**
- * @brief Helper type to use as pointer with input iterators.
- * @tparam Type of wrapped value.
- */
- template<typename Type>
- struct input_iterator_pointer final {
- /*! @brief Value type. */
- using value_type = Type;
- /*! @brief Pointer type. */
- using pointer = Type *;
- /*! @brief Reference type. */
- using reference = Type &;
- /**
- * @brief Constructs a proxy object by move.
- * @param val Value to use to initialize the proxy object.
- */
- constexpr input_iterator_pointer(value_type &&val) noexcept(std::is_nothrow_move_constructible_v<value_type>)
- : value{std::move(val)} {}
- /**
- * @brief Access operator for accessing wrapped values.
- * @return A pointer to the wrapped value.
- */
- [[nodiscard]] constexpr pointer operator->() noexcept {
- return std::addressof(value);
- }
- /**
- * @brief Dereference operator for accessing wrapped values.
- * @return A reference to the wrapped value.
- */
- [[nodiscard]] constexpr reference operator*() noexcept {
- return value;
- }
- private:
- Type value;
- };
- /**
- * @brief Plain iota iterator (waiting for C++20).
- * @tparam Type Value type.
- */
- template<typename Type>
- class iota_iterator final {
- static_assert(std::is_integral_v<Type>, "Not an integral type");
- public:
- /*! @brief Value type, likely an integral one. */
- using value_type = Type;
- /*! @brief Invalid pointer type. */
- using pointer = void;
- /*! @brief Non-reference type, same as value type. */
- using reference = value_type;
- /*! @brief Difference type. */
- using difference_type = std::ptrdiff_t;
- /*! @brief Iterator category. */
- using iterator_category = std::input_iterator_tag;
- /*! @brief Default constructor. */
- constexpr iota_iterator() noexcept
- : current{} {}
- /**
- * @brief Constructs an iota iterator from a given value.
- * @param init The initial value assigned to the iota iterator.
- */
- constexpr iota_iterator(const value_type init) noexcept
- : current{init} {}
- /**
- * @brief Pre-increment operator.
- * @return This iota iterator.
- */
- constexpr iota_iterator &operator++() noexcept {
- return ++current, *this;
- }
- /**
- * @brief Post-increment operator.
- * @return This iota iterator.
- */
- constexpr iota_iterator operator++(int) noexcept {
- const iota_iterator orig = *this;
- return ++(*this), orig;
- }
- /**
- * @brief Dereference operator.
- * @return The underlying value.
- */
- [[nodiscard]] constexpr reference operator*() const noexcept {
- return current;
- }
- private:
- value_type current;
- };
- /**
- * @brief Comparison operator.
- * @tparam Type Value type of the iota iterator.
- * @param lhs A properly initialized iota iterator.
- * @param rhs A properly initialized iota iterator.
- * @return True if the two iterators are identical, false otherwise.
- */
- template<typename Type>
- [[nodiscard]] constexpr bool operator==(const iota_iterator<Type> &lhs, const iota_iterator<Type> &rhs) noexcept {
- return *lhs == *rhs;
- }
- /**
- * @brief Comparison operator.
- * @tparam Type Value type of the iota iterator.
- * @param lhs A properly initialized iota iterator.
- * @param rhs A properly initialized iota iterator.
- * @return True if the two iterators differ, false otherwise.
- */
- template<typename Type>
- [[nodiscard]] constexpr bool operator!=(const iota_iterator<Type> &lhs, const iota_iterator<Type> &rhs) noexcept {
- return !(lhs == rhs);
- }
- /**
- * @brief Utility class to create an iterable object from a pair of iterators.
- * @tparam It Type of iterator.
- * @tparam Sentinel Type of sentinel.
- */
- template<typename It, typename Sentinel = It>
- struct iterable_adaptor final {
- /*! @brief Value type. */
- using value_type = typename std::iterator_traits<It>::value_type;
- /*! @brief Iterator type. */
- using iterator = It;
- /*! @brief Sentinel type. */
- using sentinel = Sentinel;
- /*! @brief Default constructor. */
- constexpr iterable_adaptor() noexcept(std::is_nothrow_default_constructible_v<iterator> && std::is_nothrow_default_constructible_v<sentinel>)
- : first{},
- last{} {}
- /**
- * @brief Creates an iterable object from a pair of iterators.
- * @param from Begin iterator.
- * @param to End iterator.
- */
- constexpr iterable_adaptor(iterator from, sentinel to) noexcept(std::is_nothrow_move_constructible_v<iterator> && std::is_nothrow_move_constructible_v<sentinel>)
- : first{std::move(from)},
- last{std::move(to)} {}
- /**
- * @brief Returns an iterator to the beginning.
- * @return An iterator to the first element of the range.
- */
- [[nodiscard]] constexpr iterator begin() const noexcept {
- return first;
- }
- /**
- * @brief Returns an iterator to the end.
- * @return An iterator to the element following the last element of the
- * range.
- */
- [[nodiscard]] constexpr sentinel end() const noexcept {
- return last;
- }
- /*! @copydoc begin */
- [[nodiscard]] constexpr iterator cbegin() const noexcept {
- return begin();
- }
- /*! @copydoc end */
- [[nodiscard]] constexpr sentinel cend() const noexcept {
- return end();
- }
- private:
- It first;
- Sentinel last;
- };
- } // namespace entt
- #endif
- // #include "../core/memory.hpp"
- #ifndef ENTT_CORE_MEMORY_HPP
- #define ENTT_CORE_MEMORY_HPP
- #include <cstddef>
- #include <memory>
- #include <tuple>
- #include <type_traits>
- #include <utility>
- // #include "../config/config.h"
- namespace entt {
- /**
- * @brief Unwraps fancy pointers, does nothing otherwise (waiting for C++20).
- * @tparam Type Pointer type.
- * @param ptr Fancy or raw pointer.
- * @return A raw pointer that represents the address of the original pointer.
- */
- template<typename Type>
- [[nodiscard]] constexpr auto to_address(Type &&ptr) noexcept {
- if constexpr(std::is_pointer_v<std::decay_t<Type>>) {
- return ptr;
- } else {
- return to_address(std::forward<Type>(ptr).operator->());
- }
- }
- /**
- * @brief Utility function to design allocation-aware containers.
- * @tparam Allocator Type of allocator.
- * @param lhs A valid allocator.
- * @param rhs Another valid allocator.
- */
- template<typename Allocator>
- constexpr void propagate_on_container_copy_assignment([[maybe_unused]] Allocator &lhs, [[maybe_unused]] Allocator &rhs) noexcept {
- if constexpr(std::allocator_traits<Allocator>::propagate_on_container_copy_assignment::value) {
- lhs = rhs;
- }
- }
- /**
- * @brief Utility function to design allocation-aware containers.
- * @tparam Allocator Type of allocator.
- * @param lhs A valid allocator.
- * @param rhs Another valid allocator.
- */
- template<typename Allocator>
- constexpr void propagate_on_container_move_assignment([[maybe_unused]] Allocator &lhs, [[maybe_unused]] Allocator &rhs) noexcept {
- if constexpr(std::allocator_traits<Allocator>::propagate_on_container_move_assignment::value) {
- lhs = std::move(rhs);
- }
- }
- /**
- * @brief Utility function to design allocation-aware containers.
- * @tparam Allocator Type of allocator.
- * @param lhs A valid allocator.
- * @param rhs Another valid allocator.
- */
- template<typename Allocator>
- constexpr void propagate_on_container_swap([[maybe_unused]] Allocator &lhs, [[maybe_unused]] Allocator &rhs) noexcept {
- if constexpr(std::allocator_traits<Allocator>::propagate_on_container_swap::value) {
- using std::swap;
- swap(lhs, rhs);
- } else {
- ENTT_ASSERT_CONSTEXPR(lhs == rhs, "Cannot swap the containers");
- }
- }
- /**
- * @brief Deleter for allocator-aware unique pointers (waiting for C++20).
- * @tparam Allocator Type of allocator used to manage memory and elements.
- */
- template<typename Allocator>
- struct allocation_deleter: private Allocator {
- /*! @brief Allocator type. */
- using allocator_type = Allocator;
- /*! @brief Pointer type. */
- using pointer = typename std::allocator_traits<Allocator>::pointer;
- /**
- * @brief Inherited constructors.
- * @param alloc The allocator to use.
- */
- constexpr allocation_deleter(const allocator_type &alloc) noexcept(std::is_nothrow_copy_constructible_v<allocator_type>)
- : Allocator{alloc} {}
- /**
- * @brief Destroys the pointed object and deallocates its memory.
- * @param ptr A valid pointer to an object of the given type.
- */
- constexpr void operator()(pointer ptr) noexcept(std::is_nothrow_destructible_v<typename allocator_type::value_type>) {
- using alloc_traits = std::allocator_traits<Allocator>;
- alloc_traits::destroy(*this, to_address(ptr));
- alloc_traits::deallocate(*this, ptr, 1u);
- }
- };
- /**
- * @brief Allows `std::unique_ptr` to use allocators (waiting for C++20).
- * @tparam Type Type of object to allocate for and to construct.
- * @tparam Allocator Type of allocator used to manage memory and elements.
- * @tparam Args Types of arguments to use to construct the object.
- * @param allocator The allocator to use.
- * @param args Parameters to use to construct the object.
- * @return A properly initialized unique pointer with a custom deleter.
- */
- template<typename Type, typename Allocator, typename... Args>
- ENTT_CONSTEXPR auto allocate_unique(Allocator &allocator, Args &&...args) {
- static_assert(!std::is_array_v<Type>, "Array types are not supported");
- using alloc_traits = typename std::allocator_traits<Allocator>::template rebind_traits<Type>;
- using allocator_type = typename alloc_traits::allocator_type;
- allocator_type alloc{allocator};
- auto ptr = alloc_traits::allocate(alloc, 1u);
- ENTT_TRY {
- alloc_traits::construct(alloc, to_address(ptr), std::forward<Args>(args)...);
- }
- ENTT_CATCH {
- alloc_traits::deallocate(alloc, ptr, 1u);
- ENTT_THROW;
- }
- return std::unique_ptr<Type, allocation_deleter<allocator_type>>{ptr, alloc};
- }
- /*! @cond TURN_OFF_DOXYGEN */
- namespace internal {
- template<typename Type>
- struct uses_allocator_construction {
- template<typename Allocator, typename... Params>
- static constexpr auto args([[maybe_unused]] const Allocator &allocator, Params &&...params) noexcept {
- if constexpr(!std::uses_allocator_v<Type, Allocator> && std::is_constructible_v<Type, Params...>) {
- return std::forward_as_tuple(std::forward<Params>(params)...);
- } else {
- static_assert(std::uses_allocator_v<Type, Allocator>, "Ill-formed request");
- if constexpr(std::is_constructible_v<Type, std::allocator_arg_t, const Allocator &, Params...>) {
- return std::tuple<std::allocator_arg_t, const Allocator &, Params &&...>{std::allocator_arg, allocator, std::forward<Params>(params)...};
- } else {
- static_assert(std::is_constructible_v<Type, Params..., const Allocator &>, "Ill-formed request");
- return std::forward_as_tuple(std::forward<Params>(params)..., allocator);
- }
- }
- }
- };
- template<typename Type, typename Other>
- struct uses_allocator_construction<std::pair<Type, Other>> {
- using type = std::pair<Type, Other>;
- template<typename Allocator, typename First, typename Second>
- static constexpr auto args(const Allocator &allocator, std::piecewise_construct_t, First &&first, Second &&second) noexcept {
- return std::make_tuple(
- std::piecewise_construct,
- std::apply([&allocator](auto &&...curr) { return uses_allocator_construction<Type>::args(allocator, std::forward<decltype(curr)>(curr)...); }, std::forward<First>(first)),
- std::apply([&allocator](auto &&...curr) { return uses_allocator_construction<Other>::args(allocator, std::forward<decltype(curr)>(curr)...); }, std::forward<Second>(second)));
- }
- template<typename Allocator>
- static constexpr auto args(const Allocator &allocator) noexcept {
- return uses_allocator_construction<type>::args(allocator, std::piecewise_construct, std::tuple<>{}, std::tuple<>{});
- }
- template<typename Allocator, typename First, typename Second>
- static constexpr auto args(const Allocator &allocator, First &&first, Second &&second) noexcept {
- return uses_allocator_construction<type>::args(allocator, std::piecewise_construct, std::forward_as_tuple(std::forward<First>(first)), std::forward_as_tuple(std::forward<Second>(second)));
- }
- template<typename Allocator, typename First, typename Second>
- static constexpr auto args(const Allocator &allocator, const std::pair<First, Second> &value) noexcept {
- return uses_allocator_construction<type>::args(allocator, std::piecewise_construct, std::forward_as_tuple(value.first), std::forward_as_tuple(value.second));
- }
- template<typename Allocator, typename First, typename Second>
- static constexpr auto args(const Allocator &allocator, std::pair<First, Second> &&value) noexcept {
- return uses_allocator_construction<type>::args(allocator, std::piecewise_construct, std::forward_as_tuple(std::move(value.first)), std::forward_as_tuple(std::move(value.second)));
- }
- };
- } // namespace internal
- /*! @endcond */
- /**
- * @brief Uses-allocator construction utility (waiting for C++20).
- *
- * Primarily intended for internal use. Prepares the argument list needed to
- * create an object of a given type by means of uses-allocator construction.
- *
- * @tparam Type Type to return arguments for.
- * @tparam Allocator Type of allocator used to manage memory and elements.
- * @tparam Args Types of arguments to use to construct the object.
- * @param allocator The allocator to use.
- * @param args Parameters to use to construct the object.
- * @return The arguments needed to create an object of the given type.
- */
- template<typename Type, typename Allocator, typename... Args>
- constexpr auto uses_allocator_construction_args(const Allocator &allocator, Args &&...args) noexcept {
- return internal::uses_allocator_construction<Type>::args(allocator, std::forward<Args>(args)...);
- }
- /**
- * @brief Uses-allocator construction utility (waiting for C++20).
- *
- * Primarily intended for internal use. Creates an object of a given type by
- * means of uses-allocator construction.
- *
- * @tparam Type Type of object to create.
- * @tparam Allocator Type of allocator used to manage memory and elements.
- * @tparam Args Types of arguments to use to construct the object.
- * @param allocator The allocator to use.
- * @param args Parameters to use to construct the object.
- * @return A newly created object of the given type.
- */
- template<typename Type, typename Allocator, typename... Args>
- constexpr Type make_obj_using_allocator(const Allocator &allocator, Args &&...args) {
- return std::make_from_tuple<Type>(internal::uses_allocator_construction<Type>::args(allocator, std::forward<Args>(args)...));
- }
- /**
- * @brief Uses-allocator construction utility (waiting for C++20).
- *
- * Primarily intended for internal use. Creates an object of a given type by
- * means of uses-allocator construction at an uninitialized memory location.
- *
- * @tparam Type Type of object to create.
- * @tparam Allocator Type of allocator used to manage memory and elements.
- * @tparam Args Types of arguments to use to construct the object.
- * @param value Memory location in which to place the object.
- * @param allocator The allocator to use.
- * @param args Parameters to use to construct the object.
- * @return A pointer to the newly created object of the given type.
- */
- template<typename Type, typename Allocator, typename... Args>
- constexpr Type *uninitialized_construct_using_allocator(Type *value, const Allocator &allocator, Args &&...args) {
- return std::apply([value](auto &&...curr) { return ::new(value) Type(std::forward<decltype(curr)>(curr)...); }, internal::uses_allocator_construction<Type>::args(allocator, std::forward<Args>(args)...));
- }
- } // namespace entt
- #endif
- // #include "../core/type_traits.hpp"
- #ifndef ENTT_CORE_TYPE_TRAITS_HPP
- #define ENTT_CORE_TYPE_TRAITS_HPP
- #include <cstddef>
- #include <iterator>
- #include <tuple>
- #include <type_traits>
- #include <utility>
- // #include "../config/config.h"
- // #include "fwd.hpp"
- namespace entt {
- /**
- * @brief Utility class to disambiguate overloaded functions.
- * @tparam N Number of choices available.
- */
- template<std::size_t N>
- struct choice_t
- // unfortunately, doxygen cannot parse such a construct
- : /*! @cond TURN_OFF_DOXYGEN */ choice_t<N - 1> /*! @endcond */
- {};
- /*! @copybrief choice_t */
- template<>
- struct choice_t<0> {};
- /**
- * @brief Variable template for the choice trick.
- * @tparam N Number of choices available.
- */
- template<std::size_t N>
- inline constexpr choice_t<N> choice{};
- /**
- * @brief Identity type trait.
- *
- * Useful to establish non-deduced contexts in template argument deduction
- * (waiting for C++20) or to provide types through function arguments.
- *
- * @tparam Type A type.
- */
- template<typename Type>
- struct type_identity {
- /*! @brief Identity type. */
- using type = Type;
- };
- /**
- * @brief Helper type.
- * @tparam Type A type.
- */
- template<typename Type>
- using type_identity_t = typename type_identity<Type>::type;
- /**
- * @brief A type-only `sizeof` wrapper that returns 0 where `sizeof` complains.
- * @tparam Type The type of which to return the size.
- */
- template<typename Type, typename = void>
- struct size_of: std::integral_constant<std::size_t, 0u> {};
- /*! @copydoc size_of */
- template<typename Type>
- struct size_of<Type, std::void_t<decltype(sizeof(Type))>>
- // NOLINTNEXTLINE(bugprone-sizeof-expression)
- : std::integral_constant<std::size_t, sizeof(Type)> {};
- /**
- * @brief Helper variable template.
- * @tparam Type The type of which to return the size.
- */
- template<typename Type>
- inline constexpr std::size_t size_of_v = size_of<Type>::value;
- /**
- * @brief Using declaration to be used to _repeat_ the same type a number of
- * times equal to the size of a given parameter pack.
- * @tparam Type A type to repeat.
- */
- template<typename Type, typename>
- using unpack_as_type = Type;
- /**
- * @brief Helper variable template to be used to _repeat_ the same value a
- * number of times equal to the size of a given parameter pack.
- * @tparam Value A value to repeat.
- */
- template<auto Value, typename>
- inline constexpr auto unpack_as_value = Value;
- /**
- * @brief Wraps a static constant.
- * @tparam Value A static constant.
- */
- template<auto Value>
- using integral_constant = std::integral_constant<decltype(Value), Value>;
- /**
- * @brief Alias template to facilitate the creation of named values.
- * @tparam Value A constant value at least convertible to `id_type`.
- */
- template<id_type Value>
- using tag = integral_constant<Value>;
- /**
- * @brief A class to use to push around lists of types, nothing more.
- * @tparam Type Types provided by the type list.
- */
- template<typename... Type>
- struct type_list {
- /*! @brief Type list type. */
- using type = type_list;
- /*! @brief Compile-time number of elements in the type list. */
- static constexpr auto size = sizeof...(Type);
- };
- /*! @brief Primary template isn't defined on purpose. */
- template<std::size_t, typename>
- struct type_list_element;
- /**
- * @brief Provides compile-time indexed access to the types of a type list.
- * @tparam Index Index of the type to return.
- * @tparam First First type provided by the type list.
- * @tparam Other Other types provided by the type list.
- */
- template<std::size_t Index, typename First, typename... Other>
- struct type_list_element<Index, type_list<First, Other...>>
- : type_list_element<Index - 1u, type_list<Other...>> {};
- /**
- * @brief Provides compile-time indexed access to the types of a type list.
- * @tparam First First type provided by the type list.
- * @tparam Other Other types provided by the type list.
- */
- template<typename First, typename... Other>
- struct type_list_element<0u, type_list<First, Other...>> {
- /*! @brief Searched type. */
- using type = First;
- };
- /**
- * @brief Helper type.
- * @tparam Index Index of the type to return.
- * @tparam List Type list to search into.
- */
- template<std::size_t Index, typename List>
- using type_list_element_t = typename type_list_element<Index, List>::type;
- /*! @brief Primary template isn't defined on purpose. */
- template<typename, typename>
- struct type_list_index;
- /**
- * @brief Provides compile-time type access to the types of a type list.
- * @tparam Type Type to look for and for which to return the index.
- * @tparam First First type provided by the type list.
- * @tparam Other Other types provided by the type list.
- */
- template<typename Type, typename First, typename... Other>
- struct type_list_index<Type, type_list<First, Other...>> {
- /*! @brief Unsigned integer type. */
- using value_type = std::size_t;
- /*! @brief Compile-time position of the given type in the sublist. */
- static constexpr value_type value = 1u + type_list_index<Type, type_list<Other...>>::value;
- };
- /**
- * @brief Provides compile-time type access to the types of a type list.
- * @tparam Type Type to look for and for which to return the index.
- * @tparam Other Other types provided by the type list.
- */
- template<typename Type, typename... Other>
- struct type_list_index<Type, type_list<Type, Other...>> {
- static_assert(type_list_index<Type, type_list<Other...>>::value == sizeof...(Other), "Non-unique type");
- /*! @brief Unsigned integer type. */
- using value_type = std::size_t;
- /*! @brief Compile-time position of the given type in the sublist. */
- static constexpr value_type value = 0u;
- };
- /**
- * @brief Provides compile-time type access to the types of a type list.
- * @tparam Type Type to look for and for which to return the index.
- */
- template<typename Type>
- struct type_list_index<Type, type_list<>> {
- /*! @brief Unsigned integer type. */
- using value_type = std::size_t;
- /*! @brief Compile-time position of the given type in the sublist. */
- static constexpr value_type value = 0u;
- };
- /**
- * @brief Helper variable template.
- * @tparam List Type list.
- * @tparam Type Type to look for and for which to return the index.
- */
- template<typename Type, typename List>
- inline constexpr std::size_t type_list_index_v = type_list_index<Type, List>::value;
- /**
- * @brief Concatenates multiple type lists.
- * @tparam Type Types provided by the first type list.
- * @tparam Other Types provided by the second type list.
- * @return A type list composed by the types of both the type lists.
- */
- template<typename... Type, typename... Other>
- constexpr type_list<Type..., Other...> operator+(type_list<Type...>, type_list<Other...>) {
- return {};
- }
- /*! @brief Primary template isn't defined on purpose. */
- template<typename...>
- struct type_list_cat;
- /*! @brief Concatenates multiple type lists. */
- template<>
- struct type_list_cat<> {
- /*! @brief A type list composed by the types of all the type lists. */
- using type = type_list<>;
- };
- /**
- * @brief Concatenates multiple type lists.
- * @tparam Type Types provided by the first type list.
- * @tparam Other Types provided by the second type list.
- * @tparam List Other type lists, if any.
- */
- template<typename... Type, typename... Other, typename... List>
- struct type_list_cat<type_list<Type...>, type_list<Other...>, List...> {
- /*! @brief A type list composed by the types of all the type lists. */
- using type = typename type_list_cat<type_list<Type..., Other...>, List...>::type;
- };
- /**
- * @brief Concatenates multiple type lists.
- * @tparam Type Types provided by the type list.
- */
- template<typename... Type>
- struct type_list_cat<type_list<Type...>> {
- /*! @brief A type list composed by the types of all the type lists. */
- using type = type_list<Type...>;
- };
- /**
- * @brief Helper type.
- * @tparam List Type lists to concatenate.
- */
- template<typename... List>
- using type_list_cat_t = typename type_list_cat<List...>::type;
- /*! @cond TURN_OFF_DOXYGEN */
- namespace internal {
- template<typename...>
- struct type_list_unique;
- template<typename First, typename... Other, typename... Type>
- struct type_list_unique<type_list<First, Other...>, Type...>
- : std::conditional_t<(std::is_same_v<First, Type> || ...), type_list_unique<type_list<Other...>, Type...>, type_list_unique<type_list<Other...>, Type..., First>> {};
- template<typename... Type>
- struct type_list_unique<type_list<>, Type...> {
- using type = type_list<Type...>;
- };
- } // namespace internal
- /*! @endcond */
- /**
- * @brief Removes duplicates types from a type list.
- * @tparam List Type list.
- */
- template<typename List>
- struct type_list_unique {
- /*! @brief A type list without duplicate types. */
- using type = typename internal::type_list_unique<List>::type;
- };
- /**
- * @brief Helper type.
- * @tparam List Type list.
- */
- template<typename List>
- using type_list_unique_t = typename type_list_unique<List>::type;
- /**
- * @brief Provides the member constant `value` to true if a type list contains a
- * given type, false otherwise.
- * @tparam List Type list.
- * @tparam Type Type to look for.
- */
- template<typename List, typename Type>
- struct type_list_contains;
- /**
- * @copybrief type_list_contains
- * @tparam Type Types provided by the type list.
- * @tparam Other Type to look for.
- */
- template<typename... Type, typename Other>
- struct type_list_contains<type_list<Type...>, Other>
- : std::bool_constant<(std::is_same_v<Type, Other> || ...)> {};
- /**
- * @brief Helper variable template.
- * @tparam List Type list.
- * @tparam Type Type to look for.
- */
- template<typename List, typename Type>
- inline constexpr bool type_list_contains_v = type_list_contains<List, Type>::value;
- /*! @brief Primary template isn't defined on purpose. */
- template<typename...>
- struct type_list_diff;
- /**
- * @brief Computes the difference between two type lists.
- * @tparam Type Types provided by the first type list.
- * @tparam Other Types provided by the second type list.
- */
- template<typename... Type, typename... Other>
- struct type_list_diff<type_list<Type...>, type_list<Other...>> {
- /*! @brief A type list that is the difference between the two type lists. */
- using type = type_list_cat_t<std::conditional_t<type_list_contains_v<type_list<Other...>, Type>, type_list<>, type_list<Type>>...>;
- };
- /**
- * @brief Helper type.
- * @tparam List Type lists between which to compute the difference.
- */
- template<typename... List>
- using type_list_diff_t = typename type_list_diff<List...>::type;
- /*! @brief Primary template isn't defined on purpose. */
- template<typename, template<typename...> class>
- struct type_list_transform;
- /**
- * @brief Applies a given _function_ to a type list and generate a new list.
- * @tparam Type Types provided by the type list.
- * @tparam Op Unary operation as template class with a type member named `type`.
- */
- template<typename... Type, template<typename...> class Op>
- struct type_list_transform<type_list<Type...>, Op> {
- /*! @brief Resulting type list after applying the transform function. */
- // NOLINTNEXTLINE(modernize-type-traits)
- using type = type_list<typename Op<Type>::type...>;
- };
- /**
- * @brief Helper type.
- * @tparam List Type list.
- * @tparam Op Unary operation as template class with a type member named `type`.
- */
- template<typename List, template<typename...> class Op>
- using type_list_transform_t = typename type_list_transform<List, Op>::type;
- /**
- * @brief A class to use to push around lists of constant values, nothing more.
- * @tparam Value Values provided by the value list.
- */
- template<auto... Value>
- struct value_list {
- /*! @brief Value list type. */
- using type = value_list;
- /*! @brief Compile-time number of elements in the value list. */
- static constexpr auto size = sizeof...(Value);
- };
- /*! @brief Primary template isn't defined on purpose. */
- template<std::size_t, typename>
- struct value_list_element;
- /**
- * @brief Provides compile-time indexed access to the values of a value list.
- * @tparam Index Index of the value to return.
- * @tparam Value First value provided by the value list.
- * @tparam Other Other values provided by the value list.
- */
- template<std::size_t Index, auto Value, auto... Other>
- struct value_list_element<Index, value_list<Value, Other...>>
- : value_list_element<Index - 1u, value_list<Other...>> {};
- /**
- * @brief Provides compile-time indexed access to the types of a type list.
- * @tparam Value First value provided by the value list.
- * @tparam Other Other values provided by the value list.
- */
- template<auto Value, auto... Other>
- struct value_list_element<0u, value_list<Value, Other...>> {
- /*! @brief Searched type. */
- using type = decltype(Value);
- /*! @brief Searched value. */
- static constexpr auto value = Value;
- };
- /**
- * @brief Helper type.
- * @tparam Index Index of the type to return.
- * @tparam List Value list to search into.
- */
- template<std::size_t Index, typename List>
- using value_list_element_t = typename value_list_element<Index, List>::type;
- /**
- * @brief Helper type.
- * @tparam Index Index of the value to return.
- * @tparam List Value list to search into.
- */
- template<std::size_t Index, typename List>
- inline constexpr auto value_list_element_v = value_list_element<Index, List>::value;
- /*! @brief Primary template isn't defined on purpose. */
- template<auto, typename>
- struct value_list_index;
- /**
- * @brief Provides compile-time type access to the values of a value list.
- * @tparam Value Value to look for and for which to return the index.
- * @tparam First First value provided by the value list.
- * @tparam Other Other values provided by the value list.
- */
- template<auto Value, auto First, auto... Other>
- struct value_list_index<Value, value_list<First, Other...>> {
- /*! @brief Unsigned integer type. */
- using value_type = std::size_t;
- /*! @brief Compile-time position of the given value in the sublist. */
- static constexpr value_type value = 1u + value_list_index<Value, value_list<Other...>>::value;
- };
- /**
- * @brief Provides compile-time type access to the values of a value list.
- * @tparam Value Value to look for and for which to return the index.
- * @tparam Other Other values provided by the value list.
- */
- template<auto Value, auto... Other>
- struct value_list_index<Value, value_list<Value, Other...>> {
- static_assert(value_list_index<Value, value_list<Other...>>::value == sizeof...(Other), "Non-unique type");
- /*! @brief Unsigned integer type. */
- using value_type = std::size_t;
- /*! @brief Compile-time position of the given value in the sublist. */
- static constexpr value_type value = 0u;
- };
- /**
- * @brief Provides compile-time type access to the values of a value list.
- * @tparam Value Value to look for and for which to return the index.
- */
- template<auto Value>
- struct value_list_index<Value, value_list<>> {
- /*! @brief Unsigned integer type. */
- using value_type = std::size_t;
- /*! @brief Compile-time position of the given type in the sublist. */
- static constexpr value_type value = 0u;
- };
- /**
- * @brief Helper variable template.
- * @tparam List Value list.
- * @tparam Value Value to look for and for which to return the index.
- */
- template<auto Value, typename List>
- inline constexpr std::size_t value_list_index_v = value_list_index<Value, List>::value;
- /**
- * @brief Concatenates multiple value lists.
- * @tparam Value Values provided by the first value list.
- * @tparam Other Values provided by the second value list.
- * @return A value list composed by the values of both the value lists.
- */
- template<auto... Value, auto... Other>
- constexpr value_list<Value..., Other...> operator+(value_list<Value...>, value_list<Other...>) {
- return {};
- }
- /*! @brief Primary template isn't defined on purpose. */
- template<typename...>
- struct value_list_cat;
- /*! @brief Concatenates multiple value lists. */
- template<>
- struct value_list_cat<> {
- /*! @brief A value list composed by the values of all the value lists. */
- using type = value_list<>;
- };
- /**
- * @brief Concatenates multiple value lists.
- * @tparam Value Values provided by the first value list.
- * @tparam Other Values provided by the second value list.
- * @tparam List Other value lists, if any.
- */
- template<auto... Value, auto... Other, typename... List>
- struct value_list_cat<value_list<Value...>, value_list<Other...>, List...> {
- /*! @brief A value list composed by the values of all the value lists. */
- using type = typename value_list_cat<value_list<Value..., Other...>, List...>::type;
- };
- /**
- * @brief Concatenates multiple value lists.
- * @tparam Value Values provided by the value list.
- */
- template<auto... Value>
- struct value_list_cat<value_list<Value...>> {
- /*! @brief A value list composed by the values of all the value lists. */
- using type = value_list<Value...>;
- };
- /**
- * @brief Helper type.
- * @tparam List Value lists to concatenate.
- */
- template<typename... List>
- using value_list_cat_t = typename value_list_cat<List...>::type;
- /*! @brief Primary template isn't defined on purpose. */
- template<typename>
- struct value_list_unique;
- /**
- * @brief Removes duplicates values from a value list.
- * @tparam Value One of the values provided by the given value list.
- * @tparam Other The other values provided by the given value list.
- */
- template<auto Value, auto... Other>
- struct value_list_unique<value_list<Value, Other...>> {
- /*! @brief A value list without duplicate types. */
- using type = std::conditional_t<
- ((Value == Other) || ...),
- typename value_list_unique<value_list<Other...>>::type,
- value_list_cat_t<value_list<Value>, typename value_list_unique<value_list<Other...>>::type>>;
- };
- /*! @brief Removes duplicates values from a value list. */
- template<>
- struct value_list_unique<value_list<>> {
- /*! @brief A value list without duplicate types. */
- using type = value_list<>;
- };
- /**
- * @brief Helper type.
- * @tparam Type A value list.
- */
- template<typename Type>
- using value_list_unique_t = typename value_list_unique<Type>::type;
- /**
- * @brief Provides the member constant `value` to true if a value list contains
- * a given value, false otherwise.
- * @tparam List Value list.
- * @tparam Value Value to look for.
- */
- template<typename List, auto Value>
- struct value_list_contains;
- /**
- * @copybrief value_list_contains
- * @tparam Value Values provided by the value list.
- * @tparam Other Value to look for.
- */
- template<auto... Value, auto Other>
- struct value_list_contains<value_list<Value...>, Other>
- : std::bool_constant<((Value == Other) || ...)> {};
- /**
- * @brief Helper variable template.
- * @tparam List Value list.
- * @tparam Value Value to look for.
- */
- template<typename List, auto Value>
- inline constexpr bool value_list_contains_v = value_list_contains<List, Value>::value;
- /*! @brief Primary template isn't defined on purpose. */
- template<typename...>
- struct value_list_diff;
- /**
- * @brief Computes the difference between two value lists.
- * @tparam Value Values provided by the first value list.
- * @tparam Other Values provided by the second value list.
- */
- template<auto... Value, auto... Other>
- struct value_list_diff<value_list<Value...>, value_list<Other...>> {
- /*! @brief A value list that is the difference between the two value lists. */
- using type = value_list_cat_t<std::conditional_t<value_list_contains_v<value_list<Other...>, Value>, value_list<>, value_list<Value>>...>;
- };
- /**
- * @brief Helper type.
- * @tparam List Value lists between which to compute the difference.
- */
- template<typename... List>
- using value_list_diff_t = typename value_list_diff<List...>::type;
- /*! @brief Same as std::is_invocable, but with tuples. */
- template<typename, typename>
- struct is_applicable: std::false_type {};
- /**
- * @copybrief is_applicable
- * @tparam Func A valid function type.
- * @tparam Tuple Tuple-like type.
- * @tparam Args The list of arguments to use to probe the function type.
- */
- template<typename Func, template<typename...> class Tuple, typename... Args>
- struct is_applicable<Func, Tuple<Args...>>: std::is_invocable<Func, Args...> {};
- /**
- * @copybrief is_applicable
- * @tparam Func A valid function type.
- * @tparam Tuple Tuple-like type.
- * @tparam Args The list of arguments to use to probe the function type.
- */
- template<typename Func, template<typename...> class Tuple, typename... Args>
- struct is_applicable<Func, const Tuple<Args...>>: std::is_invocable<Func, Args...> {};
- /**
- * @brief Helper variable template.
- * @tparam Func A valid function type.
- * @tparam Args The list of arguments to use to probe the function type.
- */
- template<typename Func, typename Args>
- inline constexpr bool is_applicable_v = is_applicable<Func, Args>::value;
- /*! @brief Same as std::is_invocable_r, but with tuples for arguments. */
- template<typename, typename, typename>
- struct is_applicable_r: std::false_type {};
- /**
- * @copybrief is_applicable_r
- * @tparam Ret The type to which the return type of the function should be
- * convertible.
- * @tparam Func A valid function type.
- * @tparam Args The list of arguments to use to probe the function type.
- */
- template<typename Ret, typename Func, typename... Args>
- struct is_applicable_r<Ret, Func, std::tuple<Args...>>: std::is_invocable_r<Ret, Func, Args...> {};
- /**
- * @brief Helper variable template.
- * @tparam Ret The type to which the return type of the function should be
- * convertible.
- * @tparam Func A valid function type.
- * @tparam Args The list of arguments to use to probe the function type.
- */
- template<typename Ret, typename Func, typename Args>
- inline constexpr bool is_applicable_r_v = is_applicable_r<Ret, Func, Args>::value;
- /**
- * @brief Provides the member constant `value` to true if a given type is
- * complete, false otherwise.
- * @tparam Type The type to test.
- */
- template<typename Type, typename = void>
- struct is_complete: std::false_type {};
- /*! @copydoc is_complete */
- template<typename Type>
- struct is_complete<Type, std::void_t<decltype(sizeof(Type))>>: std::true_type {};
- /**
- * @brief Helper variable template.
- * @tparam Type The type to test.
- */
- template<typename Type>
- inline constexpr bool is_complete_v = is_complete<Type>::value;
- /**
- * @brief Provides the member constant `value` to true if a given type is an
- * iterator, false otherwise.
- * @tparam Type The type to test.
- */
- template<typename Type, typename = void>
- struct is_iterator: std::false_type {};
- /*! @cond TURN_OFF_DOXYGEN */
- namespace internal {
- template<typename, typename = void>
- struct has_iterator_category: std::false_type {};
- template<typename Type>
- struct has_iterator_category<Type, std::void_t<typename std::iterator_traits<Type>::iterator_category>>: std::true_type {};
- } // namespace internal
- /*! @endcond */
- /*! @copydoc is_iterator */
- template<typename Type>
- struct is_iterator<Type, std::enable_if_t<!std::is_void_v<std::remove_const_t<std::remove_pointer_t<Type>>>>>
- : internal::has_iterator_category<Type> {};
- /**
- * @brief Helper variable template.
- * @tparam Type The type to test.
- */
- template<typename Type>
- inline constexpr bool is_iterator_v = is_iterator<Type>::value;
- /**
- * @brief Provides the member constant `value` to true if a given type is both
- * an empty and non-final class, false otherwise.
- * @tparam Type The type to test
- */
- template<typename Type>
- struct is_ebco_eligible
- : std::bool_constant<std::is_empty_v<Type> && !std::is_final_v<Type>> {};
- /**
- * @brief Helper variable template.
- * @tparam Type The type to test.
- */
- template<typename Type>
- inline constexpr bool is_ebco_eligible_v = is_ebco_eligible<Type>::value;
- /**
- * @brief Provides the member constant `value` to true if `Type::is_transparent`
- * is valid and denotes a type, false otherwise.
- * @tparam Type The type to test.
- */
- template<typename Type, typename = void>
- struct is_transparent: std::false_type {};
- /*! @copydoc is_transparent */
- template<typename Type>
- struct is_transparent<Type, std::void_t<typename Type::is_transparent>>: std::true_type {};
- /**
- * @brief Helper variable template.
- * @tparam Type The type to test.
- */
- template<typename Type>
- inline constexpr bool is_transparent_v = is_transparent<Type>::value;
- /*! @cond TURN_OFF_DOXYGEN */
- namespace internal {
- template<typename, typename = void>
- struct has_tuple_size_value: std::false_type {};
- template<typename Type>
- struct has_tuple_size_value<Type, std::void_t<decltype(std::tuple_size<const Type>::value)>>: std::true_type {};
- template<typename, typename = void>
- struct has_value_type: std::false_type {};
- template<typename Type>
- struct has_value_type<Type, std::void_t<typename Type::value_type>>: std::true_type {};
- template<typename>
- [[nodiscard]] constexpr bool dispatch_is_equality_comparable();
- template<typename Type, std::size_t... Index>
- [[nodiscard]] constexpr bool unpack_maybe_equality_comparable(std::index_sequence<Index...>) {
- return (dispatch_is_equality_comparable<std::tuple_element_t<Index, Type>>() && ...);
- }
- template<typename>
- [[nodiscard]] constexpr bool maybe_equality_comparable(char) {
- return false;
- }
- template<typename Type>
- [[nodiscard]] constexpr auto maybe_equality_comparable(int) -> decltype(std::declval<Type>() == std::declval<Type>()) {
- return true;
- }
- template<typename Type>
- [[nodiscard]] constexpr bool dispatch_is_equality_comparable() {
- // NOLINTBEGIN(modernize-use-transparent-functors)
- if constexpr(std::is_array_v<Type>) {
- return false;
- } else if constexpr(is_complete_v<std::tuple_size<std::remove_const_t<Type>>>) {
- if constexpr(has_tuple_size_value<Type>::value) {
- return maybe_equality_comparable<Type>(0) && unpack_maybe_equality_comparable<Type>(std::make_index_sequence<std::tuple_size<Type>::value>{});
- } else {
- return maybe_equality_comparable<Type>(0);
- }
- } else if constexpr(has_value_type<Type>::value) {
- if constexpr(is_iterator_v<Type> || std::is_same_v<typename Type::value_type, Type> || dispatch_is_equality_comparable<typename Type::value_type>()) {
- return maybe_equality_comparable<Type>(0);
- } else {
- return false;
- }
- } else {
- return maybe_equality_comparable<Type>(0);
- }
- // NOLINTEND(modernize-use-transparent-functors)
- }
- } // namespace internal
- /*! @endcond */
- /**
- * @brief Provides the member constant `value` to true if a given type is
- * equality comparable, false otherwise.
- * @tparam Type The type to test.
- */
- template<typename Type>
- struct is_equality_comparable: std::bool_constant<internal::dispatch_is_equality_comparable<Type>()> {};
- /*! @copydoc is_equality_comparable */
- template<typename Type>
- struct is_equality_comparable<const Type>: is_equality_comparable<Type> {};
- /**
- * @brief Helper variable template.
- * @tparam Type The type to test.
- */
- template<typename Type>
- inline constexpr bool is_equality_comparable_v = is_equality_comparable<Type>::value;
- /**
- * @brief Transcribes the constness of a type to another type.
- * @tparam To The type to which to transcribe the constness.
- * @tparam From The type from which to transcribe the constness.
- */
- template<typename To, typename From>
- struct constness_as {
- /*! @brief The type resulting from the transcription of the constness. */
- using type = std::remove_const_t<To>;
- };
- /*! @copydoc constness_as */
- template<typename To, typename From>
- struct constness_as<To, const From> {
- /*! @brief The type resulting from the transcription of the constness. */
- using type = const To;
- };
- /**
- * @brief Alias template to facilitate the transcription of the constness.
- * @tparam To The type to which to transcribe the constness.
- * @tparam From The type from which to transcribe the constness.
- */
- template<typename To, typename From>
- using constness_as_t = typename constness_as<To, From>::type;
- /**
- * @brief Extracts the class of a non-static member object or function.
- * @tparam Member A pointer to a non-static member object or function.
- */
- template<typename Member>
- class member_class {
- static_assert(std::is_member_pointer_v<Member>, "Invalid pointer type to non-static member object or function");
- template<typename Class, typename Ret, typename... Args>
- static Class *clazz(Ret (Class::*)(Args...));
- template<typename Class, typename Ret, typename... Args>
- static Class *clazz(Ret (Class::*)(Args...) const);
- template<typename Class, typename Type>
- static Class *clazz(Type Class::*);
- public:
- /*! @brief The class of the given non-static member object or function. */
- using type = std::remove_pointer_t<decltype(clazz(std::declval<Member>()))>;
- };
- /**
- * @brief Helper type.
- * @tparam Member A pointer to a non-static member object or function.
- */
- template<typename Member>
- using member_class_t = typename member_class<Member>::type;
- /**
- * @brief Extracts the n-th argument of a _callable_ type.
- * @tparam Index The index of the argument to extract.
- * @tparam Candidate A valid _callable_ type.
- */
- template<std::size_t Index, typename Candidate>
- class nth_argument {
- template<typename Ret, typename... Args>
- static constexpr type_list<Args...> pick_up(Ret (*)(Args...));
- template<typename Ret, typename Class, typename... Args>
- static constexpr type_list<Args...> pick_up(Ret (Class ::*)(Args...));
- template<typename Ret, typename Class, typename... Args>
- static constexpr type_list<Args...> pick_up(Ret (Class ::*)(Args...) const);
- template<typename Type, typename Class>
- static constexpr type_list<Type> pick_up(Type Class ::*);
- template<typename Type>
- static constexpr decltype(pick_up(&Type::operator())) pick_up(Type &&);
- public:
- /*! @brief N-th argument of the _callable_ type. */
- using type = type_list_element_t<Index, decltype(pick_up(std::declval<Candidate>()))>;
- };
- /**
- * @brief Helper type.
- * @tparam Index The index of the argument to extract.
- * @tparam Candidate A valid function, member function or data member type.
- */
- template<std::size_t Index, typename Candidate>
- using nth_argument_t = typename nth_argument<Index, Candidate>::type;
- } // namespace entt
- template<typename... Type>
- struct std::tuple_size<entt::type_list<Type...>>: std::integral_constant<std::size_t, entt::type_list<Type...>::size> {};
- template<std::size_t Index, typename... Type>
- struct std::tuple_element<Index, entt::type_list<Type...>>: entt::type_list_element<Index, entt::type_list<Type...>> {};
- template<auto... Value>
- struct std::tuple_size<entt::value_list<Value...>>: std::integral_constant<std::size_t, entt::value_list<Value...>::size> {};
- template<std::size_t Index, auto... Value>
- struct std::tuple_element<Index, entt::value_list<Value...>>: entt::value_list_element<Index, entt::value_list<Value...>> {};
- #endif
- // #include "fwd.hpp"
- #ifndef ENTT_CONTAINER_FWD_HPP
- #define ENTT_CONTAINER_FWD_HPP
- #include <functional>
- #include <memory>
- #include <utility>
- #include <vector>
- namespace entt {
- template<
- typename Key,
- typename Type,
- typename = std::hash<Key>,
- typename = std::equal_to<>,
- typename = std::allocator<std::pair<const Key, Type>>>
- class dense_map;
- template<
- typename Type,
- typename = std::hash<Type>,
- typename = std::equal_to<>,
- typename = std::allocator<Type>>
- class dense_set;
- template<typename...>
- class basic_table;
- /**
- * @brief Alias declaration for the most common use case.
- * @tparam Type Element types.
- */
- template<typename... Type>
- using table = basic_table<std::vector<Type>...>;
- } // namespace entt
- #endif
- namespace entt {
- /*! @cond TURN_OFF_DOXYGEN */
- namespace internal {
- static constexpr std::size_t dense_map_placeholder_position = (std::numeric_limits<std::size_t>::max)();
- template<typename Key, typename Type>
- struct dense_map_node final {
- using value_type = std::pair<Key, Type>;
- template<typename... Args>
- dense_map_node(const std::size_t pos, Args &&...args)
- : next{pos},
- element{std::forward<Args>(args)...} {}
- template<typename Allocator, typename... Args>
- dense_map_node(std::allocator_arg_t, const Allocator &allocator, const std::size_t pos, Args &&...args)
- : next{pos},
- element{entt::make_obj_using_allocator<value_type>(allocator, std::forward<Args>(args)...)} {}
- template<typename Allocator>
- dense_map_node(std::allocator_arg_t, const Allocator &allocator, const dense_map_node &other)
- : next{other.next},
- element{entt::make_obj_using_allocator<value_type>(allocator, other.element)} {}
- template<typename Allocator>
- dense_map_node(std::allocator_arg_t, const Allocator &allocator, dense_map_node &&other)
- : next{other.next},
- element{entt::make_obj_using_allocator<value_type>(allocator, std::move(other.element))} {}
- std::size_t next;
- value_type element;
- };
- template<typename It>
- class dense_map_iterator final {
- template<typename>
- friend class dense_map_iterator;
- using first_type = decltype(std::as_const(std::declval<It>()->element.first));
- using second_type = decltype((std::declval<It>()->element.second));
- public:
- using value_type = std::pair<first_type, second_type>;
- using pointer = input_iterator_pointer<value_type>;
- using reference = value_type;
- using difference_type = std::ptrdiff_t;
- using iterator_category = std::input_iterator_tag;
- using iterator_concept = std::random_access_iterator_tag;
- constexpr dense_map_iterator() noexcept
- : it{} {}
- constexpr dense_map_iterator(const It iter) noexcept
- : it{iter} {}
- template<typename Other, typename = std::enable_if_t<!std::is_same_v<It, Other> && std::is_constructible_v<It, Other>>>
- constexpr dense_map_iterator(const dense_map_iterator<Other> &other) noexcept
- : it{other.it} {}
- constexpr dense_map_iterator &operator++() noexcept {
- return ++it, *this;
- }
- constexpr dense_map_iterator operator++(int) noexcept {
- const dense_map_iterator orig = *this;
- return ++(*this), orig;
- }
- constexpr dense_map_iterator &operator--() noexcept {
- return --it, *this;
- }
- constexpr dense_map_iterator operator--(int) noexcept {
- const dense_map_iterator orig = *this;
- return operator--(), orig;
- }
- constexpr dense_map_iterator &operator+=(const difference_type value) noexcept {
- it += value;
- return *this;
- }
- constexpr dense_map_iterator operator+(const difference_type value) const noexcept {
- dense_map_iterator copy = *this;
- return (copy += value);
- }
- constexpr dense_map_iterator &operator-=(const difference_type value) noexcept {
- return (*this += -value);
- }
- constexpr dense_map_iterator operator-(const difference_type value) const noexcept {
- return (*this + -value);
- }
- [[nodiscard]] constexpr reference operator[](const difference_type value) const noexcept {
- return {it[value].element.first, it[value].element.second};
- }
- [[nodiscard]] constexpr pointer operator->() const noexcept {
- return operator*();
- }
- [[nodiscard]] constexpr reference operator*() const noexcept {
- return operator[](0);
- }
- template<typename Lhs, typename Rhs>
- friend constexpr std::ptrdiff_t operator-(const dense_map_iterator<Lhs> &, const dense_map_iterator<Rhs> &) noexcept;
- template<typename Lhs, typename Rhs>
- friend constexpr bool operator==(const dense_map_iterator<Lhs> &, const dense_map_iterator<Rhs> &) noexcept;
- template<typename Lhs, typename Rhs>
- friend constexpr bool operator<(const dense_map_iterator<Lhs> &, const dense_map_iterator<Rhs> &) noexcept;
- private:
- It it;
- };
- template<typename Lhs, typename Rhs>
- [[nodiscard]] constexpr std::ptrdiff_t operator-(const dense_map_iterator<Lhs> &lhs, const dense_map_iterator<Rhs> &rhs) noexcept {
- return lhs.it - rhs.it;
- }
- template<typename Lhs, typename Rhs>
- [[nodiscard]] constexpr bool operator==(const dense_map_iterator<Lhs> &lhs, const dense_map_iterator<Rhs> &rhs) noexcept {
- return lhs.it == rhs.it;
- }
- template<typename Lhs, typename Rhs>
- [[nodiscard]] constexpr bool operator!=(const dense_map_iterator<Lhs> &lhs, const dense_map_iterator<Rhs> &rhs) noexcept {
- return !(lhs == rhs);
- }
- template<typename Lhs, typename Rhs>
- [[nodiscard]] constexpr bool operator<(const dense_map_iterator<Lhs> &lhs, const dense_map_iterator<Rhs> &rhs) noexcept {
- return lhs.it < rhs.it;
- }
- template<typename Lhs, typename Rhs>
- [[nodiscard]] constexpr bool operator>(const dense_map_iterator<Lhs> &lhs, const dense_map_iterator<Rhs> &rhs) noexcept {
- return rhs < lhs;
- }
- template<typename Lhs, typename Rhs>
- [[nodiscard]] constexpr bool operator<=(const dense_map_iterator<Lhs> &lhs, const dense_map_iterator<Rhs> &rhs) noexcept {
- return !(lhs > rhs);
- }
- template<typename Lhs, typename Rhs>
- [[nodiscard]] constexpr bool operator>=(const dense_map_iterator<Lhs> &lhs, const dense_map_iterator<Rhs> &rhs) noexcept {
- return !(lhs < rhs);
- }
- template<typename It>
- class dense_map_local_iterator final {
- template<typename>
- friend class dense_map_local_iterator;
- using first_type = decltype(std::as_const(std::declval<It>()->element.first));
- using second_type = decltype((std::declval<It>()->element.second));
- public:
- using value_type = std::pair<first_type, second_type>;
- using pointer = input_iterator_pointer<value_type>;
- using reference = value_type;
- using difference_type = std::ptrdiff_t;
- using iterator_category = std::input_iterator_tag;
- using iterator_concept = std::forward_iterator_tag;
- constexpr dense_map_local_iterator() noexcept = default;
- constexpr dense_map_local_iterator(It iter, const std::size_t pos) noexcept
- : it{iter},
- offset{pos} {}
- template<typename Other, typename = std::enable_if_t<!std::is_same_v<It, Other> && std::is_constructible_v<It, Other>>>
- constexpr dense_map_local_iterator(const dense_map_local_iterator<Other> &other) noexcept
- : it{other.it},
- offset{other.offset} {}
- constexpr dense_map_local_iterator &operator++() noexcept {
- return (offset = it[static_cast<typename It::difference_type>(offset)].next), *this;
- }
- constexpr dense_map_local_iterator operator++(int) noexcept {
- const dense_map_local_iterator orig = *this;
- return ++(*this), orig;
- }
- [[nodiscard]] constexpr pointer operator->() const noexcept {
- return operator*();
- }
- [[nodiscard]] constexpr reference operator*() const noexcept {
- const auto idx = static_cast<typename It::difference_type>(offset);
- return {it[idx].element.first, it[idx].element.second};
- }
- [[nodiscard]] constexpr std::size_t index() const noexcept {
- return offset;
- }
- private:
- It it{};
- std::size_t offset{dense_map_placeholder_position};
- };
- template<typename Lhs, typename Rhs>
- [[nodiscard]] constexpr bool operator==(const dense_map_local_iterator<Lhs> &lhs, const dense_map_local_iterator<Rhs> &rhs) noexcept {
- return lhs.index() == rhs.index();
- }
- template<typename Lhs, typename Rhs>
- [[nodiscard]] constexpr bool operator!=(const dense_map_local_iterator<Lhs> &lhs, const dense_map_local_iterator<Rhs> &rhs) noexcept {
- return !(lhs == rhs);
- }
- } // namespace internal
- /*! @endcond */
- /**
- * @brief Associative container for key-value pairs with unique keys.
- *
- * Internally, elements are organized into buckets. Which bucket an element is
- * placed into depends entirely on the hash of its key. Keys with the same hash
- * code appear in the same bucket.
- *
- * @tparam Key Key type of the associative container.
- * @tparam Type Mapped type of the associative container.
- * @tparam Hash Type of function to use to hash the keys.
- * @tparam KeyEqual Type of function to use to compare the keys for equality.
- * @tparam Allocator Type of allocator used to manage memory and elements.
- */
- template<typename Key, typename Type, typename Hash, typename KeyEqual, typename Allocator>
- class dense_map {
- static constexpr float default_threshold = 0.875f;
- static constexpr std::size_t minimum_capacity = 8u;
- static constexpr std::size_t placeholder_position = internal::dense_map_placeholder_position;
- using node_type = internal::dense_map_node<Key, Type>;
- using alloc_traits = std::allocator_traits<Allocator>;
- static_assert(std::is_same_v<typename alloc_traits::value_type, std::pair<const Key, Type>>, "Invalid value type");
- using sparse_container_type = std::vector<std::size_t, typename alloc_traits::template rebind_alloc<std::size_t>>;
- using packed_container_type = std::vector<node_type, typename alloc_traits::template rebind_alloc<node_type>>;
- template<typename Other>
- [[nodiscard]] std::size_t key_to_bucket(const Other &key) const noexcept {
- // NOLINTNEXTLINE(cppcoreguidelines-pro-bounds-array-to-pointer-decay)
- return fast_mod(static_cast<size_type>(sparse.second()(key)), bucket_count());
- }
- template<typename Other>
- [[nodiscard]] auto constrained_find(const Other &key, const std::size_t bucket) {
- for(auto offset = sparse.first()[bucket]; offset != placeholder_position; offset = packed.first()[offset].next) {
- if(packed.second()(packed.first()[offset].element.first, key)) {
- return begin() + static_cast<typename iterator::difference_type>(offset);
- }
- }
- return end();
- }
- template<typename Other>
- [[nodiscard]] auto constrained_find(const Other &key, const std::size_t bucket) const {
- for(auto offset = sparse.first()[bucket]; offset != placeholder_position; offset = packed.first()[offset].next) {
- if(packed.second()(packed.first()[offset].element.first, key)) {
- return cbegin() + static_cast<typename const_iterator::difference_type>(offset);
- }
- }
- return cend();
- }
- template<typename Other, typename... Args>
- [[nodiscard]] auto insert_or_do_nothing(Other &&key, Args &&...args) {
- const auto index = key_to_bucket(key);
- if(auto it = constrained_find(key, index); it != end()) {
- return std::make_pair(it, false);
- }
- packed.first().emplace_back(sparse.first()[index], std::piecewise_construct, std::forward_as_tuple(std::forward<Other>(key)), std::forward_as_tuple(std::forward<Args>(args)...));
- sparse.first()[index] = packed.first().size() - 1u;
- rehash_if_required();
- return std::make_pair(--end(), true);
- }
- template<typename Other, typename Arg>
- [[nodiscard]] auto insert_or_overwrite(Other &&key, Arg &&value) {
- const auto index = key_to_bucket(key);
- if(auto it = constrained_find(key, index); it != end()) {
- it->second = std::forward<Arg>(value);
- return std::make_pair(it, false);
- }
- packed.first().emplace_back(sparse.first()[index], std::forward<Other>(key), std::forward<Arg>(value));
- sparse.first()[index] = packed.first().size() - 1u;
- rehash_if_required();
- return std::make_pair(--end(), true);
- }
- void move_and_pop(const std::size_t pos) {
- if(const auto last = size() - 1u; pos != last) {
- size_type *curr = &sparse.first()[key_to_bucket(packed.first().back().element.first)];
- packed.first()[pos] = std::move(packed.first().back());
- for(; *curr != last; curr = &packed.first()[*curr].next) {}
- *curr = pos;
- }
- packed.first().pop_back();
- }
- void rehash_if_required() {
- if(const auto bc = bucket_count(); size() > static_cast<size_type>(static_cast<float>(bc) * max_load_factor())) {
- rehash(bc * 2u);
- }
- }
- public:
- /*! @brief Allocator type. */
- using allocator_type = Allocator;
- /*! @brief Key type of the container. */
- using key_type = Key;
- /*! @brief Mapped type of the container. */
- using mapped_type = Type;
- /*! @brief Key-value type of the container. */
- using value_type = std::pair<const Key, Type>;
- /*! @brief Unsigned integer type. */
- using size_type = std::size_t;
- /*! @brief Signed integer type. */
- using difference_type = std::ptrdiff_t;
- /*! @brief Type of function to use to hash the keys. */
- using hasher = Hash;
- /*! @brief Type of function to use to compare the keys for equality. */
- using key_equal = KeyEqual;
- /*! @brief Input iterator type. */
- using iterator = internal::dense_map_iterator<typename packed_container_type::iterator>;
- /*! @brief Constant input iterator type. */
- using const_iterator = internal::dense_map_iterator<typename packed_container_type::const_iterator>;
- /*! @brief Input iterator type. */
- using local_iterator = internal::dense_map_local_iterator<typename packed_container_type::iterator>;
- /*! @brief Constant input iterator type. */
- using const_local_iterator = internal::dense_map_local_iterator<typename packed_container_type::const_iterator>;
- /*! @brief Default constructor. */
- dense_map()
- : dense_map{minimum_capacity} {}
- /**
- * @brief Constructs an empty container with a given allocator.
- * @param allocator The allocator to use.
- */
- explicit dense_map(const allocator_type &allocator)
- : dense_map{minimum_capacity, hasher{}, key_equal{}, allocator} {}
- /**
- * @brief Constructs an empty container with a given allocator and user
- * supplied minimal number of buckets.
- * @param cnt Minimal number of buckets.
- * @param allocator The allocator to use.
- */
- dense_map(const size_type cnt, const allocator_type &allocator)
- : dense_map{cnt, hasher{}, key_equal{}, allocator} {}
- /**
- * @brief Constructs an empty container with a given allocator, hash
- * function and user supplied minimal number of buckets.
- * @param cnt Minimal number of buckets.
- * @param hash Hash function to use.
- * @param allocator The allocator to use.
- */
- dense_map(const size_type cnt, const hasher &hash, const allocator_type &allocator)
- : dense_map{cnt, hash, key_equal{}, allocator} {}
- /**
- * @brief Constructs an empty container with a given allocator, hash
- * function, compare function and user supplied minimal number of buckets.
- * @param cnt Minimal number of buckets.
- * @param hash Hash function to use.
- * @param equal Compare function to use.
- * @param allocator The allocator to use.
- */
- explicit dense_map(const size_type cnt, const hasher &hash = hasher{}, const key_equal &equal = key_equal{}, const allocator_type &allocator = allocator_type{})
- : sparse{allocator, hash},
- packed{allocator, equal} {
- rehash(cnt);
- }
- /*! @brief Default copy constructor. */
- dense_map(const dense_map &) = default;
- /**
- * @brief Allocator-extended copy constructor.
- * @param other The instance to copy from.
- * @param allocator The allocator to use.
- */
- dense_map(const dense_map &other, const allocator_type &allocator)
- : sparse{std::piecewise_construct, std::forward_as_tuple(other.sparse.first(), allocator), std::forward_as_tuple(other.sparse.second())},
- packed{std::piecewise_construct, std::forward_as_tuple(other.packed.first(), allocator), std::forward_as_tuple(other.packed.second())},
- threshold{other.threshold} {}
- /*! @brief Default move constructor. */
- dense_map(dense_map &&) noexcept = default;
- /**
- * @brief Allocator-extended move constructor.
- * @param other The instance to move from.
- * @param allocator The allocator to use.
- */
- dense_map(dense_map &&other, const allocator_type &allocator)
- : sparse{std::piecewise_construct, std::forward_as_tuple(std::move(other.sparse.first()), allocator), std::forward_as_tuple(std::move(other.sparse.second()))},
- packed{std::piecewise_construct, std::forward_as_tuple(std::move(other.packed.first()), allocator), std::forward_as_tuple(std::move(other.packed.second()))},
- threshold{other.threshold} {}
- /*! @brief Default destructor. */
- ~dense_map() = default;
- /**
- * @brief Default copy assignment operator.
- * @return This container.
- */
- dense_map &operator=(const dense_map &) = default;
- /**
- * @brief Default move assignment operator.
- * @return This container.
- */
- dense_map &operator=(dense_map &&) noexcept = default;
- /**
- * @brief Exchanges the contents with those of a given container.
- * @param other Container to exchange the content with.
- */
- void swap(dense_map &other) noexcept {
- using std::swap;
- swap(sparse, other.sparse);
- swap(packed, other.packed);
- swap(threshold, other.threshold);
- }
- /**
- * @brief Returns the associated allocator.
- * @return The associated allocator.
- */
- [[nodiscard]] constexpr allocator_type get_allocator() const noexcept {
- return sparse.first().get_allocator();
- }
- /**
- * @brief Returns an iterator to the beginning.
- *
- * If the array is empty, the returned iterator will be equal to `end()`.
- *
- * @return An iterator to the first instance of the internal array.
- */
- [[nodiscard]] const_iterator cbegin() const noexcept {
- return packed.first().begin();
- }
- /*! @copydoc cbegin */
- [[nodiscard]] const_iterator begin() const noexcept {
- return cbegin();
- }
- /*! @copydoc begin */
- [[nodiscard]] iterator begin() noexcept {
- return packed.first().begin();
- }
- /**
- * @brief Returns an iterator to the end.
- * @return An iterator to the element following the last instance of the
- * internal array.
- */
- [[nodiscard]] const_iterator cend() const noexcept {
- return packed.first().end();
- }
- /*! @copydoc cend */
- [[nodiscard]] const_iterator end() const noexcept {
- return cend();
- }
- /*! @copydoc end */
- [[nodiscard]] iterator end() noexcept {
- return packed.first().end();
- }
- /**
- * @brief Checks whether a container is empty.
- * @return True if the container is empty, false otherwise.
- */
- [[nodiscard]] bool empty() const noexcept {
- return packed.first().empty();
- }
- /**
- * @brief Returns the number of elements in a container.
- * @return Number of elements in a container.
- */
- [[nodiscard]] size_type size() const noexcept {
- return packed.first().size();
- }
- /**
- * @brief Returns the maximum possible number of elements.
- * @return Maximum possible number of elements.
- */
- [[nodiscard]] size_type max_size() const noexcept {
- return packed.first().max_size();
- }
- /*! @brief Clears the container. */
- void clear() noexcept {
- sparse.first().clear();
- packed.first().clear();
- rehash(0u);
- }
- /**
- * @brief Inserts an element into the container, if the key does not exist.
- * @param value A key-value pair eventually convertible to the value type.
- * @return A pair consisting of an iterator to the inserted element (or to
- * the element that prevented the insertion) and a bool denoting whether the
- * insertion took place.
- */
- std::pair<iterator, bool> insert(const value_type &value) {
- return insert_or_do_nothing(value.first, value.second);
- }
- /*! @copydoc insert */
- std::pair<iterator, bool> insert(value_type &&value) {
- return insert_or_do_nothing(std::move(value.first), std::move(value.second));
- }
- /**
- * @copydoc insert
- * @tparam Arg Type of the key-value pair to insert into the container.
- */
- template<typename Arg>
- std::enable_if_t<std::is_constructible_v<value_type, Arg &&>, std::pair<iterator, bool>>
- insert(Arg &&value) {
- return insert_or_do_nothing(std::forward<Arg>(value).first, std::forward<Arg>(value).second);
- }
- /**
- * @brief Inserts elements into the container, if their keys do not exist.
- * @tparam It Type of input iterator.
- * @param first An iterator to the first element of the range of elements.
- * @param last An iterator past the last element of the range of elements.
- */
- template<typename It>
- void insert(It first, It last) {
- for(; first != last; ++first) {
- insert(*first);
- }
- }
- /**
- * @brief Inserts an element into the container or assigns to the current
- * element if the key already exists.
- * @tparam Arg Type of the value to insert or assign.
- * @param key A key used both to look up and to insert if not found.
- * @param value A value to insert or assign.
- * @return A pair consisting of an iterator to the element and a bool
- * denoting whether the insertion took place.
- */
- template<typename Arg>
- std::pair<iterator, bool> insert_or_assign(const key_type &key, Arg &&value) {
- return insert_or_overwrite(key, std::forward<Arg>(value));
- }
- /*! @copydoc insert_or_assign */
- template<typename Arg>
- std::pair<iterator, bool> insert_or_assign(key_type &&key, Arg &&value) {
- return insert_or_overwrite(std::move(key), std::forward<Arg>(value));
- }
- /**
- * @brief Constructs an element in-place, if the key does not exist.
- *
- * The element is also constructed when the container already has the key,
- * in which case the newly constructed object is destroyed immediately.
- *
- * @tparam Args Types of arguments to forward to the constructor of the
- * element.
- * @param args Arguments to forward to the constructor of the element.
- * @return A pair consisting of an iterator to the inserted element (or to
- * the element that prevented the insertion) and a bool denoting whether the
- * insertion took place.
- */
- template<typename... Args>
- std::pair<iterator, bool> emplace([[maybe_unused]] Args &&...args) {
- if constexpr(sizeof...(Args) == 0u) {
- return insert_or_do_nothing(key_type{});
- } else if constexpr(sizeof...(Args) == 1u) {
- return insert_or_do_nothing(std::forward<Args>(args).first..., std::forward<Args>(args).second...);
- } else if constexpr(sizeof...(Args) == 2u) {
- return insert_or_do_nothing(std::forward<Args>(args)...);
- } else {
- auto &node = packed.first().emplace_back(packed.first().size(), std::forward<Args>(args)...);
- const auto index = key_to_bucket(node.element.first);
- if(auto it = constrained_find(node.element.first, index); it != end()) {
- packed.first().pop_back();
- return std::make_pair(it, false);
- }
- std::swap(node.next, sparse.first()[index]);
- rehash_if_required();
- return std::make_pair(--end(), true);
- }
- }
- /**
- * @brief Inserts in-place if the key does not exist, does nothing if the
- * key exists.
- * @tparam Args Types of arguments to forward to the constructor of the
- * element.
- * @param key A key used both to look up and to insert if not found.
- * @param args Arguments to forward to the constructor of the element.
- * @return A pair consisting of an iterator to the inserted element (or to
- * the element that prevented the insertion) and a bool denoting whether the
- * insertion took place.
- */
- template<typename... Args>
- std::pair<iterator, bool> try_emplace(const key_type &key, Args &&...args) {
- return insert_or_do_nothing(key, std::forward<Args>(args)...);
- }
- /*! @copydoc try_emplace */
- template<typename... Args>
- std::pair<iterator, bool> try_emplace(key_type &&key, Args &&...args) {
- return insert_or_do_nothing(std::move(key), std::forward<Args>(args)...);
- }
- /**
- * @brief Removes an element from a given position.
- * @param pos An iterator to the element to remove.
- * @return An iterator following the removed element.
- */
- iterator erase(const_iterator pos) {
- const auto diff = pos - cbegin();
- erase(pos->first);
- return begin() + diff;
- }
- /**
- * @brief Removes the given elements from a container.
- * @param first An iterator to the first element of the range of elements.
- * @param last An iterator past the last element of the range of elements.
- * @return An iterator following the last removed element.
- */
- iterator erase(const_iterator first, const_iterator last) {
- const auto dist = first - cbegin();
- for(auto from = last - cbegin(); from != dist; --from) {
- erase(packed.first()[static_cast<size_type>(from) - 1u].element.first);
- }
- return (begin() + dist);
- }
- /**
- * @brief Removes the element associated with a given key.
- * @param key A key value of an element to remove.
- * @return Number of elements removed (either 0 or 1).
- */
- size_type erase(const key_type &key) {
- for(size_type *curr = &sparse.first()[key_to_bucket(key)]; *curr != placeholder_position; curr = &packed.first()[*curr].next) {
- if(packed.second()(packed.first()[*curr].element.first, key)) {
- const auto index = *curr;
- *curr = packed.first()[*curr].next;
- move_and_pop(index);
- return 1u;
- }
- }
- return 0u;
- }
- /**
- * @brief Accesses a given element with bounds checking.
- * @param key A key of an element to find.
- * @return A reference to the mapped value of the requested element.
- */
- [[nodiscard]] mapped_type &at(const key_type &key) {
- auto it = find(key);
- ENTT_ASSERT(it != end(), "Invalid key");
- return it->second;
- }
- /*! @copydoc at */
- [[nodiscard]] const mapped_type &at(const key_type &key) const {
- auto it = find(key);
- ENTT_ASSERT(it != cend(), "Invalid key");
- return it->second;
- }
- /**
- * @brief Accesses a given element with bounds checking.
- * @tparam Other Type of the key of an element to find.
- * @param key A key of an element to find.
- * @return A reference to the mapped value of the requested element.
- */
- template<typename Other>
- [[nodiscard]] std::enable_if_t<is_transparent_v<hasher> && is_transparent_v<key_equal>, std::conditional_t<false, Other, mapped_type const &>>
- at(const Other &key) const {
- auto it = find(key);
- ENTT_ASSERT(it != cend(), "Invalid key");
- return it->second;
- }
- /*! @copydoc at */
- template<typename Other>
- [[nodiscard]] std::enable_if_t<is_transparent_v<hasher> && is_transparent_v<key_equal>, std::conditional_t<false, Other, mapped_type &>>
- at(const Other &key) {
- auto it = find(key);
- ENTT_ASSERT(it != end(), "Invalid key");
- return it->second;
- }
- /**
- * @brief Accesses or inserts a given element.
- * @param key A key of an element to find or insert.
- * @return A reference to the mapped value of the requested element.
- */
- [[nodiscard]] mapped_type &operator[](const key_type &key) {
- return insert_or_do_nothing(key).first->second;
- }
- /**
- * @brief Accesses or inserts a given element.
- * @param key A key of an element to find or insert.
- * @return A reference to the mapped value of the requested element.
- */
- [[nodiscard]] mapped_type &operator[](key_type &&key) {
- return insert_or_do_nothing(std::move(key)).first->second;
- }
- /**
- * @brief Returns the number of elements matching a key (either 1 or 0).
- * @param key Key value of an element to search for.
- * @return Number of elements matching the key (either 1 or 0).
- */
- [[nodiscard]] size_type count(const key_type &key) const {
- return find(key) != end();
- }
- /**
- * @brief Returns the number of elements matching a key (either 1 or 0).
- * @tparam Other Type of the key value of an element to search for.
- * @param key Key value of an element to search for.
- * @return Number of elements matching the key (either 1 or 0).
- */
- template<typename Other>
- [[nodiscard]] std::enable_if_t<is_transparent_v<hasher> && is_transparent_v<key_equal>, std::conditional_t<false, Other, size_type>>
- count(const Other &key) const {
- return find(key) != end();
- }
- /**
- * @brief Finds an element with a given key.
- * @param key Key value of an element to search for.
- * @return An iterator to an element with the given key. If no such element
- * is found, a past-the-end iterator is returned.
- */
- [[nodiscard]] iterator find(const key_type &key) {
- return constrained_find(key, key_to_bucket(key));
- }
- /*! @copydoc find */
- [[nodiscard]] const_iterator find(const key_type &key) const {
- return constrained_find(key, key_to_bucket(key));
- }
- /**
- * @brief Finds an element with a key that compares _equivalent_ to a given
- * key.
- * @tparam Other Type of the key value of an element to search for.
- * @param key Key value of an element to search for.
- * @return An iterator to an element with the given key. If no such element
- * is found, a past-the-end iterator is returned.
- */
- template<typename Other>
- [[nodiscard]] std::enable_if_t<is_transparent_v<hasher> && is_transparent_v<key_equal>, std::conditional_t<false, Other, iterator>>
- find(const Other &key) {
- return constrained_find(key, key_to_bucket(key));
- }
- /*! @copydoc find */
- template<typename Other>
- [[nodiscard]] std::enable_if_t<is_transparent_v<hasher> && is_transparent_v<key_equal>, std::conditional_t<false, Other, const_iterator>>
- find(const Other &key) const {
- return constrained_find(key, key_to_bucket(key));
- }
- /**
- * @brief Returns a range containing all elements with a given key.
- * @param key Key value of an element to search for.
- * @return A pair of iterators pointing to the first element and past the
- * last element of the range.
- */
- [[nodiscard]] std::pair<iterator, iterator> equal_range(const key_type &key) {
- const auto it = find(key);
- return {it, it + !(it == end())};
- }
- /*! @copydoc equal_range */
- [[nodiscard]] std::pair<const_iterator, const_iterator> equal_range(const key_type &key) const {
- const auto it = find(key);
- return {it, it + !(it == cend())};
- }
- /**
- * @brief Returns a range containing all elements that compare _equivalent_
- * to a given key.
- * @tparam Other Type of an element to search for.
- * @param key Key value of an element to search for.
- * @return A pair of iterators pointing to the first element and past the
- * last element of the range.
- */
- template<typename Other>
- [[nodiscard]] std::enable_if_t<is_transparent_v<hasher> && is_transparent_v<key_equal>, std::conditional_t<false, Other, std::pair<iterator, iterator>>>
- equal_range(const Other &key) {
- const auto it = find(key);
- return {it, it + !(it == end())};
- }
- /*! @copydoc equal_range */
- template<typename Other>
- [[nodiscard]] std::enable_if_t<is_transparent_v<hasher> && is_transparent_v<key_equal>, std::conditional_t<false, Other, std::pair<const_iterator, const_iterator>>>
- equal_range(const Other &key) const {
- const auto it = find(key);
- return {it, it + !(it == cend())};
- }
- /**
- * @brief Checks if the container contains an element with a given key.
- * @param key Key value of an element to search for.
- * @return True if there is such an element, false otherwise.
- */
- [[nodiscard]] bool contains(const key_type &key) const {
- return (find(key) != cend());
- }
- /**
- * @brief Checks if the container contains an element with a key that
- * compares _equivalent_ to a given value.
- * @tparam Other Type of the key value of an element to search for.
- * @param key Key value of an element to search for.
- * @return True if there is such an element, false otherwise.
- */
- template<typename Other>
- [[nodiscard]] std::enable_if_t<is_transparent_v<hasher> && is_transparent_v<key_equal>, std::conditional_t<false, Other, bool>>
- contains(const Other &key) const {
- return (find(key) != cend());
- }
- /**
- * @brief Returns an iterator to the beginning of a given bucket.
- * @param index An index of a bucket to access.
- * @return An iterator to the beginning of the given bucket.
- */
- [[nodiscard]] const_local_iterator cbegin(const size_type index) const {
- return {packed.first().begin(), sparse.first()[index]};
- }
- /**
- * @brief Returns an iterator to the beginning of a given bucket.
- * @param index An index of a bucket to access.
- * @return An iterator to the beginning of the given bucket.
- */
- [[nodiscard]] const_local_iterator begin(const size_type index) const {
- return cbegin(index);
- }
- /**
- * @brief Returns an iterator to the beginning of a given bucket.
- * @param index An index of a bucket to access.
- * @return An iterator to the beginning of the given bucket.
- */
- [[nodiscard]] local_iterator begin(const size_type index) {
- return {packed.first().begin(), sparse.first()[index]};
- }
- /**
- * @brief Returns an iterator to the end of a given bucket.
- * @param index An index of a bucket to access.
- * @return An iterator to the end of the given bucket.
- */
- [[nodiscard]] const_local_iterator cend([[maybe_unused]] const size_type index) const {
- return {};
- }
- /**
- * @brief Returns an iterator to the end of a given bucket.
- * @param index An index of a bucket to access.
- * @return An iterator to the end of the given bucket.
- */
- [[nodiscard]] const_local_iterator end(const size_type index) const {
- return cend(index);
- }
- /**
- * @brief Returns an iterator to the end of a given bucket.
- * @param index An index of a bucket to access.
- * @return An iterator to the end of the given bucket.
- */
- [[nodiscard]] local_iterator end([[maybe_unused]] const size_type index) {
- return {};
- }
- /**
- * @brief Returns the number of buckets.
- * @return The number of buckets.
- */
- [[nodiscard]] size_type bucket_count() const {
- return sparse.first().size();
- }
- /**
- * @brief Returns the maximum number of buckets.
- * @return The maximum number of buckets.
- */
- [[nodiscard]] size_type max_bucket_count() const {
- return sparse.first().max_size();
- }
- /**
- * @brief Returns the number of elements in a given bucket.
- * @param index The index of the bucket to examine.
- * @return The number of elements in the given bucket.
- */
- [[nodiscard]] size_type bucket_size(const size_type index) const {
- return static_cast<size_type>(std::distance(begin(index), end(index)));
- }
- /**
- * @brief Returns the bucket for a given key.
- * @param key The value of the key to examine.
- * @return The bucket for the given key.
- */
- [[nodiscard]] size_type bucket(const key_type &key) const {
- return key_to_bucket(key);
- }
- /**
- * @brief Returns the average number of elements per bucket.
- * @return The average number of elements per bucket.
- */
- [[nodiscard]] float load_factor() const {
- return static_cast<float>(size()) / static_cast<float>(bucket_count());
- }
- /**
- * @brief Returns the maximum average number of elements per bucket.
- * @return The maximum average number of elements per bucket.
- */
- [[nodiscard]] float max_load_factor() const {
- return threshold;
- }
- /**
- * @brief Sets the desired maximum average number of elements per bucket.
- * @param value A desired maximum average number of elements per bucket.
- */
- void max_load_factor(const float value) {
- ENTT_ASSERT(value > 0.f, "Invalid load factor");
- threshold = value;
- rehash(0u);
- }
- /**
- * @brief Reserves at least the specified number of buckets and regenerates
- * the hash table.
- * @param cnt New number of buckets.
- */
- void rehash(const size_type cnt) {
- auto value = cnt > minimum_capacity ? cnt : minimum_capacity;
- const auto cap = static_cast<size_type>(static_cast<float>(size()) / max_load_factor());
- value = value > cap ? value : cap;
- if(const auto sz = next_power_of_two(value); sz != bucket_count()) {
- sparse.first().resize(sz);
- for(auto &&elem: sparse.first()) {
- elem = placeholder_position;
- }
- for(size_type pos{}, last = size(); pos < last; ++pos) {
- const auto index = key_to_bucket(packed.first()[pos].element.first);
- packed.first()[pos].next = std::exchange(sparse.first()[index], pos);
- }
- }
- }
- /**
- * @brief Reserves space for at least the specified number of elements and
- * regenerates the hash table.
- * @param cnt New number of elements.
- */
- void reserve(const size_type cnt) {
- packed.first().reserve(cnt);
- rehash(static_cast<size_type>(std::ceil(static_cast<float>(cnt) / max_load_factor())));
- }
- /**
- * @brief Returns the function used to hash the keys.
- * @return The function used to hash the keys.
- */
- [[nodiscard]] hasher hash_function() const {
- return sparse.second();
- }
- /**
- * @brief Returns the function used to compare keys for equality.
- * @return The function used to compare keys for equality.
- */
- [[nodiscard]] key_equal key_eq() const {
- return packed.second();
- }
- private:
- compressed_pair<sparse_container_type, hasher> sparse;
- compressed_pair<packed_container_type, key_equal> packed;
- float threshold{default_threshold};
- };
- } // namespace entt
- /*! @cond TURN_OFF_DOXYGEN */
- namespace std {
- template<typename Key, typename Value, typename Allocator>
- struct uses_allocator<entt::internal::dense_map_node<Key, Value>, Allocator>
- : std::true_type {};
- } // namespace std
- /*! @endcond */
- #endif
- // #include "../container/dense_set.hpp"
- #ifndef ENTT_CONTAINER_DENSE_SET_HPP
- #define ENTT_CONTAINER_DENSE_SET_HPP
- #include <cmath>
- #include <cstddef>
- #include <functional>
- #include <iterator>
- #include <limits>
- #include <memory>
- #include <tuple>
- #include <type_traits>
- #include <utility>
- #include <vector>
- // #include "../config/config.h"
- // #include "../core/bit.hpp"
- // #include "../core/compressed_pair.hpp"
- // #include "../core/type_traits.hpp"
- // #include "fwd.hpp"
- namespace entt {
- /*! @cond TURN_OFF_DOXYGEN */
- namespace internal {
- static constexpr std::size_t dense_set_placeholder_position = (std::numeric_limits<std::size_t>::max)();
- template<typename It>
- class dense_set_iterator final {
- template<typename>
- friend class dense_set_iterator;
- public:
- using value_type = typename It::value_type::second_type;
- using pointer = const value_type *;
- using reference = const value_type &;
- using difference_type = std::ptrdiff_t;
- using iterator_category = std::random_access_iterator_tag;
- constexpr dense_set_iterator() noexcept
- : it{} {}
- constexpr dense_set_iterator(const It iter) noexcept
- : it{iter} {}
- template<typename Other, typename = std::enable_if_t<!std::is_same_v<It, Other> && std::is_constructible_v<It, Other>>>
- constexpr dense_set_iterator(const dense_set_iterator<Other> &other) noexcept
- : it{other.it} {}
- constexpr dense_set_iterator &operator++() noexcept {
- return ++it, *this;
- }
- constexpr dense_set_iterator operator++(int) noexcept {
- const dense_set_iterator orig = *this;
- return ++(*this), orig;
- }
- constexpr dense_set_iterator &operator--() noexcept {
- return --it, *this;
- }
- constexpr dense_set_iterator operator--(int) noexcept {
- const dense_set_iterator orig = *this;
- return operator--(), orig;
- }
- constexpr dense_set_iterator &operator+=(const difference_type value) noexcept {
- it += value;
- return *this;
- }
- constexpr dense_set_iterator operator+(const difference_type value) const noexcept {
- dense_set_iterator copy = *this;
- return (copy += value);
- }
- constexpr dense_set_iterator &operator-=(const difference_type value) noexcept {
- return (*this += -value);
- }
- constexpr dense_set_iterator operator-(const difference_type value) const noexcept {
- return (*this + -value);
- }
- [[nodiscard]] constexpr reference operator[](const difference_type value) const noexcept {
- return it[value].second;
- }
- [[nodiscard]] constexpr pointer operator->() const noexcept {
- return std::addressof(operator[](0));
- }
- [[nodiscard]] constexpr reference operator*() const noexcept {
- return operator[](0);
- }
- template<typename Lhs, typename Rhs>
- friend constexpr std::ptrdiff_t operator-(const dense_set_iterator<Lhs> &, const dense_set_iterator<Rhs> &) noexcept;
- template<typename Lhs, typename Rhs>
- friend constexpr bool operator==(const dense_set_iterator<Lhs> &, const dense_set_iterator<Rhs> &) noexcept;
- template<typename Lhs, typename Rhs>
- friend constexpr bool operator<(const dense_set_iterator<Lhs> &, const dense_set_iterator<Rhs> &) noexcept;
- private:
- It it;
- };
- template<typename Lhs, typename Rhs>
- [[nodiscard]] constexpr std::ptrdiff_t operator-(const dense_set_iterator<Lhs> &lhs, const dense_set_iterator<Rhs> &rhs) noexcept {
- return lhs.it - rhs.it;
- }
- template<typename Lhs, typename Rhs>
- [[nodiscard]] constexpr bool operator==(const dense_set_iterator<Lhs> &lhs, const dense_set_iterator<Rhs> &rhs) noexcept {
- return lhs.it == rhs.it;
- }
- template<typename Lhs, typename Rhs>
- [[nodiscard]] constexpr bool operator!=(const dense_set_iterator<Lhs> &lhs, const dense_set_iterator<Rhs> &rhs) noexcept {
- return !(lhs == rhs);
- }
- template<typename Lhs, typename Rhs>
- [[nodiscard]] constexpr bool operator<(const dense_set_iterator<Lhs> &lhs, const dense_set_iterator<Rhs> &rhs) noexcept {
- return lhs.it < rhs.it;
- }
- template<typename Lhs, typename Rhs>
- [[nodiscard]] constexpr bool operator>(const dense_set_iterator<Lhs> &lhs, const dense_set_iterator<Rhs> &rhs) noexcept {
- return rhs < lhs;
- }
- template<typename Lhs, typename Rhs>
- [[nodiscard]] constexpr bool operator<=(const dense_set_iterator<Lhs> &lhs, const dense_set_iterator<Rhs> &rhs) noexcept {
- return !(lhs > rhs);
- }
- template<typename Lhs, typename Rhs>
- [[nodiscard]] constexpr bool operator>=(const dense_set_iterator<Lhs> &lhs, const dense_set_iterator<Rhs> &rhs) noexcept {
- return !(lhs < rhs);
- }
- template<typename It>
- class dense_set_local_iterator final {
- template<typename>
- friend class dense_set_local_iterator;
- public:
- using value_type = typename It::value_type::second_type;
- using pointer = const value_type *;
- using reference = const value_type &;
- using difference_type = std::ptrdiff_t;
- using iterator_category = std::forward_iterator_tag;
- constexpr dense_set_local_iterator() noexcept = default;
- constexpr dense_set_local_iterator(It iter, const std::size_t pos) noexcept
- : it{iter},
- offset{pos} {}
- template<typename Other, typename = std::enable_if_t<!std::is_same_v<It, Other> && std::is_constructible_v<It, Other>>>
- constexpr dense_set_local_iterator(const dense_set_local_iterator<Other> &other) noexcept
- : it{other.it},
- offset{other.offset} {}
- constexpr dense_set_local_iterator &operator++() noexcept {
- return offset = it[static_cast<typename It::difference_type>(offset)].first, *this;
- }
- constexpr dense_set_local_iterator operator++(int) noexcept {
- const dense_set_local_iterator orig = *this;
- return ++(*this), orig;
- }
- [[nodiscard]] constexpr pointer operator->() const noexcept {
- return std::addressof(it[static_cast<typename It::difference_type>(offset)].second);
- }
- [[nodiscard]] constexpr reference operator*() const noexcept {
- return *operator->();
- }
- [[nodiscard]] constexpr std::size_t index() const noexcept {
- return offset;
- }
- private:
- It it{};
- std::size_t offset{dense_set_placeholder_position};
- };
- template<typename Lhs, typename Rhs>
- [[nodiscard]] constexpr bool operator==(const dense_set_local_iterator<Lhs> &lhs, const dense_set_local_iterator<Rhs> &rhs) noexcept {
- return lhs.index() == rhs.index();
- }
- template<typename Lhs, typename Rhs>
- [[nodiscard]] constexpr bool operator!=(const dense_set_local_iterator<Lhs> &lhs, const dense_set_local_iterator<Rhs> &rhs) noexcept {
- return !(lhs == rhs);
- }
- } // namespace internal
- /*! @endcond */
- /**
- * @brief Associative container for unique objects of a given type.
- *
- * Internally, elements are organized into buckets. Which bucket an element is
- * placed into depends entirely on its hash. Elements with the same hash code
- * appear in the same bucket.
- *
- * @tparam Type Value type of the associative container.
- * @tparam Hash Type of function to use to hash the values.
- * @tparam KeyEqual Type of function to use to compare the values for equality.
- * @tparam Allocator Type of allocator used to manage memory and elements.
- */
- template<typename Type, typename Hash, typename KeyEqual, typename Allocator>
- class dense_set {
- static constexpr float default_threshold = 0.875f;
- static constexpr std::size_t minimum_capacity = 8u;
- static constexpr std::size_t placeholder_position = internal::dense_set_placeholder_position;
- using node_type = std::pair<std::size_t, Type>;
- using alloc_traits = std::allocator_traits<Allocator>;
- static_assert(std::is_same_v<typename alloc_traits::value_type, Type>, "Invalid value type");
- using sparse_container_type = std::vector<std::size_t, typename alloc_traits::template rebind_alloc<std::size_t>>;
- using packed_container_type = std::vector<node_type, typename alloc_traits::template rebind_alloc<node_type>>;
- template<typename Other>
- [[nodiscard]] std::size_t value_to_bucket(const Other &value) const noexcept {
- return fast_mod(static_cast<size_type>(sparse.second()(value)), bucket_count());
- }
- template<typename Other>
- [[nodiscard]] auto constrained_find(const Other &value, const std::size_t bucket) {
- for(auto offset = sparse.first()[bucket]; offset != placeholder_position; offset = packed.first()[offset].first) {
- if(packed.second()(packed.first()[offset].second, value)) {
- return begin() + static_cast<typename iterator::difference_type>(offset);
- }
- }
- return end();
- }
- template<typename Other>
- [[nodiscard]] auto constrained_find(const Other &value, const std::size_t bucket) const {
- for(auto offset = sparse.first()[bucket]; offset != placeholder_position; offset = packed.first()[offset].first) {
- if(packed.second()(packed.first()[offset].second, value)) {
- return cbegin() + static_cast<typename const_iterator::difference_type>(offset);
- }
- }
- return cend();
- }
- template<typename Other>
- [[nodiscard]] auto insert_or_do_nothing(Other &&value) {
- const auto index = value_to_bucket(value);
- if(auto it = constrained_find(value, index); it != end()) {
- return std::make_pair(it, false);
- }
- packed.first().emplace_back(sparse.first()[index], std::forward<Other>(value));
- sparse.first()[index] = packed.first().size() - 1u;
- rehash_if_required();
- return std::make_pair(--end(), true);
- }
- void move_and_pop(const std::size_t pos) {
- if(const auto last = size() - 1u; pos != last) {
- size_type *curr = &sparse.first()[value_to_bucket(packed.first().back().second)];
- packed.first()[pos] = std::move(packed.first().back());
- for(; *curr != last; curr = &packed.first()[*curr].first) {}
- *curr = pos;
- }
- packed.first().pop_back();
- }
- void rehash_if_required() {
- if(const auto bc = bucket_count(); size() > static_cast<size_type>(static_cast<float>(bc) * max_load_factor())) {
- rehash(bc * 2u);
- }
- }
- public:
- /*! @brief Allocator type. */
- using allocator_type = Allocator;
- /*! @brief Key type of the container. */
- using key_type = Type;
- /*! @brief Value type of the container. */
- using value_type = Type;
- /*! @brief Unsigned integer type. */
- using size_type = std::size_t;
- /*! @brief Signed integer type. */
- using difference_type = std::ptrdiff_t;
- /*! @brief Type of function to use to hash the elements. */
- using hasher = Hash;
- /*! @brief Type of function to use to compare the elements for equality. */
- using key_equal = KeyEqual;
- /*! @brief Random access iterator type. */
- using iterator = internal::dense_set_iterator<typename packed_container_type::iterator>;
- /*! @brief Constant random access iterator type. */
- using const_iterator = internal::dense_set_iterator<typename packed_container_type::const_iterator>;
- /*! @brief Reverse iterator type. */
- using reverse_iterator = std::reverse_iterator<iterator>;
- /*! @brief Constant reverse iterator type. */
- using const_reverse_iterator = std::reverse_iterator<const_iterator>;
- /*! @brief Forward iterator type. */
- using local_iterator = internal::dense_set_local_iterator<typename packed_container_type::iterator>;
- /*! @brief Constant forward iterator type. */
- using const_local_iterator = internal::dense_set_local_iterator<typename packed_container_type::const_iterator>;
- /*! @brief Default constructor. */
- dense_set()
- : dense_set{minimum_capacity} {}
- /**
- * @brief Constructs an empty container with a given allocator.
- * @param allocator The allocator to use.
- */
- explicit dense_set(const allocator_type &allocator)
- : dense_set{minimum_capacity, hasher{}, key_equal{}, allocator} {}
- /**
- * @brief Constructs an empty container with a given allocator and user
- * supplied minimal number of buckets.
- * @param cnt Minimal number of buckets.
- * @param allocator The allocator to use.
- */
- dense_set(const size_type cnt, const allocator_type &allocator)
- : dense_set{cnt, hasher{}, key_equal{}, allocator} {}
- /**
- * @brief Constructs an empty container with a given allocator, hash
- * function and user supplied minimal number of buckets.
- * @param cnt Minimal number of buckets.
- * @param hash Hash function to use.
- * @param allocator The allocator to use.
- */
- dense_set(const size_type cnt, const hasher &hash, const allocator_type &allocator)
- : dense_set{cnt, hash, key_equal{}, allocator} {}
- /**
- * @brief Constructs an empty container with a given allocator, hash
- * function, compare function and user supplied minimal number of buckets.
- * @param cnt Minimal number of buckets.
- * @param hash Hash function to use.
- * @param equal Compare function to use.
- * @param allocator The allocator to use.
- */
- explicit dense_set(const size_type cnt, const hasher &hash = hasher{}, const key_equal &equal = key_equal{}, const allocator_type &allocator = allocator_type{})
- : sparse{allocator, hash},
- packed{allocator, equal} {
- rehash(cnt);
- }
- /*! @brief Default copy constructor. */
- dense_set(const dense_set &) = default;
- /**
- * @brief Allocator-extended copy constructor.
- * @param other The instance to copy from.
- * @param allocator The allocator to use.
- */
- dense_set(const dense_set &other, const allocator_type &allocator)
- : sparse{std::piecewise_construct, std::forward_as_tuple(other.sparse.first(), allocator), std::forward_as_tuple(other.sparse.second())},
- packed{std::piecewise_construct, std::forward_as_tuple(other.packed.first(), allocator), std::forward_as_tuple(other.packed.second())},
- threshold{other.threshold} {}
- /*! @brief Default move constructor. */
- dense_set(dense_set &&) noexcept = default;
- /**
- * @brief Allocator-extended move constructor.
- * @param other The instance to move from.
- * @param allocator The allocator to use.
- */
- dense_set(dense_set &&other, const allocator_type &allocator)
- : sparse{std::piecewise_construct, std::forward_as_tuple(std::move(other.sparse.first()), allocator), std::forward_as_tuple(std::move(other.sparse.second()))},
- packed{std::piecewise_construct, std::forward_as_tuple(std::move(other.packed.first()), allocator), std::forward_as_tuple(std::move(other.packed.second()))},
- threshold{other.threshold} {}
- /*! @brief Default destructor. */
- ~dense_set() = default;
- /**
- * @brief Default copy assignment operator.
- * @return This container.
- */
- dense_set &operator=(const dense_set &) = default;
- /**
- * @brief Default move assignment operator.
- * @return This container.
- */
- dense_set &operator=(dense_set &&) noexcept = default;
- /**
- * @brief Exchanges the contents with those of a given container.
- * @param other Container to exchange the content with.
- */
- void swap(dense_set &other) noexcept {
- using std::swap;
- swap(sparse, other.sparse);
- swap(packed, other.packed);
- swap(threshold, other.threshold);
- }
- /**
- * @brief Returns the associated allocator.
- * @return The associated allocator.
- */
- [[nodiscard]] constexpr allocator_type get_allocator() const noexcept {
- return sparse.first().get_allocator();
- }
- /**
- * @brief Returns an iterator to the beginning.
- *
- * If the array is empty, the returned iterator will be equal to `end()`.
- *
- * @return An iterator to the first instance of the internal array.
- */
- [[nodiscard]] const_iterator cbegin() const noexcept {
- return packed.first().begin();
- }
- /*! @copydoc cbegin */
- [[nodiscard]] const_iterator begin() const noexcept {
- return cbegin();
- }
- /*! @copydoc begin */
- [[nodiscard]] iterator begin() noexcept {
- return packed.first().begin();
- }
- /**
- * @brief Returns an iterator to the end.
- * @return An iterator to the element following the last instance of the
- * internal array.
- */
- [[nodiscard]] const_iterator cend() const noexcept {
- return packed.first().end();
- }
- /*! @copydoc cend */
- [[nodiscard]] const_iterator end() const noexcept {
- return cend();
- }
- /*! @copydoc end */
- [[nodiscard]] iterator end() noexcept {
- return packed.first().end();
- }
- /**
- * @brief Returns a reverse iterator to the beginning.
- *
- * If the array is empty, the returned iterator will be equal to `rend()`.
- *
- * @return An iterator to the first instance of the reversed internal array.
- */
- [[nodiscard]] const_reverse_iterator crbegin() const noexcept {
- return std::make_reverse_iterator(cend());
- }
- /*! @copydoc crbegin */
- [[nodiscard]] const_reverse_iterator rbegin() const noexcept {
- return crbegin();
- }
- /*! @copydoc rbegin */
- [[nodiscard]] reverse_iterator rbegin() noexcept {
- return std::make_reverse_iterator(end());
- }
- /**
- * @brief Returns a reverse iterator to the end.
- * @return An iterator to the element following the last instance of the
- * reversed internal array.
- */
- [[nodiscard]] const_reverse_iterator crend() const noexcept {
- return std::make_reverse_iterator(cbegin());
- }
- /*! @copydoc crend */
- [[nodiscard]] const_reverse_iterator rend() const noexcept {
- return crend();
- }
- /*! @copydoc rend */
- [[nodiscard]] reverse_iterator rend() noexcept {
- return std::make_reverse_iterator(begin());
- }
- /**
- * @brief Checks whether a container is empty.
- * @return True if the container is empty, false otherwise.
- */
- [[nodiscard]] bool empty() const noexcept {
- return packed.first().empty();
- }
- /**
- * @brief Returns the number of elements in a container.
- * @return Number of elements in a container.
- */
- [[nodiscard]] size_type size() const noexcept {
- return packed.first().size();
- }
- /**
- * @brief Returns the maximum possible number of elements.
- * @return Maximum possible number of elements.
- */
- [[nodiscard]] size_type max_size() const noexcept {
- return packed.first().max_size();
- }
- /*! @brief Clears the container. */
- void clear() noexcept {
- sparse.first().clear();
- packed.first().clear();
- rehash(0u);
- }
- /**
- * @brief Inserts an element into the container, if it does not exist.
- * @param value An element to insert into the container.
- * @return A pair consisting of an iterator to the inserted element (or to
- * the element that prevented the insertion) and a bool denoting whether the
- * insertion took place.
- */
- std::pair<iterator, bool> insert(const value_type &value) {
- return insert_or_do_nothing(value);
- }
- /*! @copydoc insert */
- std::pair<iterator, bool> insert(value_type &&value) {
- return insert_or_do_nothing(std::move(value));
- }
- /**
- * @brief Inserts elements into the container, if they do not exist.
- * @tparam It Type of input iterator.
- * @param first An iterator to the first element of the range of elements.
- * @param last An iterator past the last element of the range of elements.
- */
- template<typename It>
- void insert(It first, It last) {
- for(; first != last; ++first) {
- insert(*first);
- }
- }
- /**
- * @brief Constructs an element in-place, if it does not exist.
- *
- * The element is also constructed when the container already has the key,
- * in which case the newly constructed object is destroyed immediately.
- *
- * @tparam Args Types of arguments to forward to the constructor of the
- * element.
- * @param args Arguments to forward to the constructor of the element.
- * @return A pair consisting of an iterator to the inserted element (or to
- * the element that prevented the insertion) and a bool denoting whether the
- * insertion took place.
- */
- template<typename... Args>
- std::pair<iterator, bool> emplace(Args &&...args) {
- if constexpr(((sizeof...(Args) == 1u) && ... && std::is_same_v<std::decay_t<Args>, value_type>)) {
- return insert_or_do_nothing(std::forward<Args>(args)...);
- } else {
- auto &node = packed.first().emplace_back(std::piecewise_construct, std::make_tuple(packed.first().size()), std::forward_as_tuple(std::forward<Args>(args)...));
- const auto index = value_to_bucket(node.second);
- if(auto it = constrained_find(node.second, index); it != end()) {
- packed.first().pop_back();
- return std::make_pair(it, false);
- }
- std::swap(node.first, sparse.first()[index]);
- rehash_if_required();
- return std::make_pair(--end(), true);
- }
- }
- /**
- * @brief Removes an element from a given position.
- * @param pos An iterator to the element to remove.
- * @return An iterator following the removed element.
- */
- iterator erase(const_iterator pos) {
- const auto diff = pos - cbegin();
- erase(*pos);
- return begin() + diff;
- }
- /**
- * @brief Removes the given elements from a container.
- * @param first An iterator to the first element of the range of elements.
- * @param last An iterator past the last element of the range of elements.
- * @return An iterator following the last removed element.
- */
- iterator erase(const_iterator first, const_iterator last) {
- const auto dist = first - cbegin();
- for(auto from = last - cbegin(); from != dist; --from) {
- erase(packed.first()[static_cast<size_type>(from) - 1u].second);
- }
- return (begin() + dist);
- }
- /**
- * @brief Removes the element associated with a given value.
- * @param value Value of an element to remove.
- * @return Number of elements removed (either 0 or 1).
- */
- size_type erase(const value_type &value) {
- for(size_type *curr = &sparse.first()[value_to_bucket(value)]; *curr != placeholder_position; curr = &packed.first()[*curr].first) {
- if(packed.second()(packed.first()[*curr].second, value)) {
- const auto index = *curr;
- *curr = packed.first()[*curr].first;
- move_and_pop(index);
- return 1u;
- }
- }
- return 0u;
- }
- /**
- * @brief Returns the number of elements matching a value (either 1 or 0).
- * @param key Key value of an element to search for.
- * @return Number of elements matching the key (either 1 or 0).
- */
- [[nodiscard]] size_type count(const value_type &key) const {
- return find(key) != end();
- }
- /**
- * @brief Returns the number of elements matching a key (either 1 or 0).
- * @tparam Other Type of the key value of an element to search for.
- * @param key Key value of an element to search for.
- * @return Number of elements matching the key (either 1 or 0).
- */
- template<typename Other>
- [[nodiscard]] std::enable_if_t<is_transparent_v<hasher> && is_transparent_v<key_equal>, std::conditional_t<false, Other, size_type>>
- count(const Other &key) const {
- return find(key) != end();
- }
- /**
- * @brief Finds an element with a given value.
- * @param value Value of an element to search for.
- * @return An iterator to an element with the given value. If no such
- * element is found, a past-the-end iterator is returned.
- */
- [[nodiscard]] iterator find(const value_type &value) {
- return constrained_find(value, value_to_bucket(value));
- }
- /*! @copydoc find */
- [[nodiscard]] const_iterator find(const value_type &value) const {
- return constrained_find(value, value_to_bucket(value));
- }
- /**
- * @brief Finds an element that compares _equivalent_ to a given value.
- * @tparam Other Type of an element to search for.
- * @param value Value of an element to search for.
- * @return An iterator to an element with the given value. If no such
- * element is found, a past-the-end iterator is returned.
- */
- template<typename Other>
- [[nodiscard]] std::enable_if_t<is_transparent_v<hasher> && is_transparent_v<key_equal>, std::conditional_t<false, Other, iterator>>
- find(const Other &value) {
- return constrained_find(value, value_to_bucket(value));
- }
- /*! @copydoc find */
- template<typename Other>
- [[nodiscard]] std::enable_if_t<is_transparent_v<hasher> && is_transparent_v<key_equal>, std::conditional_t<false, Other, const_iterator>>
- find(const Other &value) const {
- return constrained_find(value, value_to_bucket(value));
- }
- /**
- * @brief Returns a range containing all elements with a given value.
- * @param value Value of an element to search for.
- * @return A pair of iterators pointing to the first element and past the
- * last element of the range.
- */
- [[nodiscard]] std::pair<iterator, iterator> equal_range(const value_type &value) {
- const auto it = find(value);
- return {it, it + !(it == end())};
- }
- /*! @copydoc equal_range */
- [[nodiscard]] std::pair<const_iterator, const_iterator> equal_range(const value_type &value) const {
- const auto it = find(value);
- return {it, it + !(it == cend())};
- }
- /**
- * @brief Returns a range containing all elements that compare _equivalent_
- * to a given value.
- * @tparam Other Type of an element to search for.
- * @param value Value of an element to search for.
- * @return A pair of iterators pointing to the first element and past the
- * last element of the range.
- */
- template<typename Other>
- [[nodiscard]] std::enable_if_t<is_transparent_v<hasher> && is_transparent_v<key_equal>, std::conditional_t<false, Other, std::pair<iterator, iterator>>>
- equal_range(const Other &value) {
- const auto it = find(value);
- return {it, it + !(it == end())};
- }
- /*! @copydoc equal_range */
- template<typename Other>
- [[nodiscard]] std::enable_if_t<is_transparent_v<hasher> && is_transparent_v<key_equal>, std::conditional_t<false, Other, std::pair<const_iterator, const_iterator>>>
- equal_range(const Other &value) const {
- const auto it = find(value);
- return {it, it + !(it == cend())};
- }
- /**
- * @brief Checks if the container contains an element with a given value.
- * @param value Value of an element to search for.
- * @return True if there is such an element, false otherwise.
- */
- [[nodiscard]] bool contains(const value_type &value) const {
- return (find(value) != cend());
- }
- /**
- * @brief Checks if the container contains an element that compares
- * _equivalent_ to a given value.
- * @tparam Other Type of an element to search for.
- * @param value Value of an element to search for.
- * @return True if there is such an element, false otherwise.
- */
- template<typename Other>
- [[nodiscard]] std::enable_if_t<is_transparent_v<hasher> && is_transparent_v<key_equal>, std::conditional_t<false, Other, bool>>
- contains(const Other &value) const {
- return (find(value) != cend());
- }
- /**
- * @brief Returns an iterator to the beginning of a given bucket.
- * @param index An index of a bucket to access.
- * @return An iterator to the beginning of the given bucket.
- */
- [[nodiscard]] const_local_iterator cbegin(const size_type index) const {
- return {packed.first().begin(), sparse.first()[index]};
- }
- /**
- * @brief Returns an iterator to the beginning of a given bucket.
- * @param index An index of a bucket to access.
- * @return An iterator to the beginning of the given bucket.
- */
- [[nodiscard]] const_local_iterator begin(const size_type index) const {
- return cbegin(index);
- }
- /**
- * @brief Returns an iterator to the beginning of a given bucket.
- * @param index An index of a bucket to access.
- * @return An iterator to the beginning of the given bucket.
- */
- [[nodiscard]] local_iterator begin(const size_type index) {
- return {packed.first().begin(), sparse.first()[index]};
- }
- /**
- * @brief Returns an iterator to the end of a given bucket.
- * @param index An index of a bucket to access.
- * @return An iterator to the end of the given bucket.
- */
- [[nodiscard]] const_local_iterator cend([[maybe_unused]] const size_type index) const {
- return {};
- }
- /**
- * @brief Returns an iterator to the end of a given bucket.
- * @param index An index of a bucket to access.
- * @return An iterator to the end of the given bucket.
- */
- [[nodiscard]] const_local_iterator end(const size_type index) const {
- return cend(index);
- }
- /**
- * @brief Returns an iterator to the end of a given bucket.
- * @param index An index of a bucket to access.
- * @return An iterator to the end of the given bucket.
- */
- [[nodiscard]] local_iterator end([[maybe_unused]] const size_type index) {
- return {};
- }
- /**
- * @brief Returns the number of buckets.
- * @return The number of buckets.
- */
- [[nodiscard]] size_type bucket_count() const {
- return sparse.first().size();
- }
- /**
- * @brief Returns the maximum number of buckets.
- * @return The maximum number of buckets.
- */
- [[nodiscard]] size_type max_bucket_count() const {
- return sparse.first().max_size();
- }
- /**
- * @brief Returns the number of elements in a given bucket.
- * @param index The index of the bucket to examine.
- * @return The number of elements in the given bucket.
- */
- [[nodiscard]] size_type bucket_size(const size_type index) const {
- return static_cast<size_type>(std::distance(begin(index), end(index)));
- }
- /**
- * @brief Returns the bucket for a given element.
- * @param value The value of the element to examine.
- * @return The bucket for the given element.
- */
- [[nodiscard]] size_type bucket(const value_type &value) const {
- return value_to_bucket(value);
- }
- /**
- * @brief Returns the average number of elements per bucket.
- * @return The average number of elements per bucket.
- */
- [[nodiscard]] float load_factor() const {
- return static_cast<float>(size()) / static_cast<float>(bucket_count());
- }
- /**
- * @brief Returns the maximum average number of elements per bucket.
- * @return The maximum average number of elements per bucket.
- */
- [[nodiscard]] float max_load_factor() const {
- return threshold;
- }
- /**
- * @brief Sets the desired maximum average number of elements per bucket.
- * @param value A desired maximum average number of elements per bucket.
- */
- void max_load_factor(const float value) {
- ENTT_ASSERT(value > 0.f, "Invalid load factor");
- threshold = value;
- rehash(0u);
- }
- /**
- * @brief Reserves at least the specified number of buckets and regenerates
- * the hash table.
- * @param cnt New number of buckets.
- */
- void rehash(const size_type cnt) {
- auto value = cnt > minimum_capacity ? cnt : minimum_capacity;
- const auto cap = static_cast<size_type>(static_cast<float>(size()) / max_load_factor());
- value = value > cap ? value : cap;
- if(const auto sz = next_power_of_two(value); sz != bucket_count()) {
- sparse.first().resize(sz);
- for(auto &&elem: sparse.first()) {
- elem = placeholder_position;
- }
- for(size_type pos{}, last = size(); pos < last; ++pos) {
- const auto index = value_to_bucket(packed.first()[pos].second);
- packed.first()[pos].first = std::exchange(sparse.first()[index], pos);
- }
- }
- }
- /**
- * @brief Reserves space for at least the specified number of elements and
- * regenerates the hash table.
- * @param cnt New number of elements.
- */
- void reserve(const size_type cnt) {
- packed.first().reserve(cnt);
- rehash(static_cast<size_type>(std::ceil(static_cast<float>(cnt) / max_load_factor())));
- }
- /**
- * @brief Returns the function used to hash the elements.
- * @return The function used to hash the elements.
- */
- [[nodiscard]] hasher hash_function() const {
- return sparse.second();
- }
- /**
- * @brief Returns the function used to compare elements for equality.
- * @return The function used to compare elements for equality.
- */
- [[nodiscard]] key_equal key_eq() const {
- return packed.second();
- }
- private:
- compressed_pair<sparse_container_type, hasher> sparse;
- compressed_pair<packed_container_type, key_equal> packed;
- float threshold{default_threshold};
- };
- } // namespace entt
- #endif
- // #include "../core/compressed_pair.hpp"
- #ifndef ENTT_CORE_COMPRESSED_PAIR_HPP
- #define ENTT_CORE_COMPRESSED_PAIR_HPP
- #include <cstddef>
- #include <tuple>
- #include <type_traits>
- #include <utility>
- // #include "fwd.hpp"
- #ifndef ENTT_CORE_FWD_HPP
- #define ENTT_CORE_FWD_HPP
- #include <cstddef>
- #include <cstdint>
- // #include "../config/config.h"
- namespace entt {
- /*! @brief Possible modes of an any object. */
- enum class any_policy : std::uint8_t {
- /*! @brief Default mode, no element available. */
- empty,
- /*! @brief Owning mode, dynamically allocated element. */
- dynamic,
- /*! @brief Owning mode, embedded element. */
- embedded,
- /*! @brief Aliasing mode, non-const reference. */
- ref,
- /*! @brief Const aliasing mode, const reference. */
- cref
- };
- // NOLINTNEXTLINE(cppcoreguidelines-avoid-c-arrays, modernize-avoid-c-arrays)
- template<std::size_t Len = sizeof(double[2]), std::size_t = alignof(double[2])>
- class basic_any;
- /*! @brief Alias declaration for type identifiers. */
- using id_type = ENTT_ID_TYPE;
- /*! @brief Alias declaration for the most common use case. */
- using any = basic_any<>;
- template<typename, typename>
- class compressed_pair;
- template<typename>
- class basic_hashed_string;
- /*! @brief Aliases for common character types. */
- using hashed_string = basic_hashed_string<char>;
- /*! @brief Aliases for common character types. */
- using hashed_wstring = basic_hashed_string<wchar_t>;
- // NOLINTNEXTLINE(bugprone-forward-declaration-namespace)
- struct type_info;
- } // namespace entt
- #endif
- // #include "type_traits.hpp"
- #ifndef ENTT_CORE_TYPE_TRAITS_HPP
- #define ENTT_CORE_TYPE_TRAITS_HPP
- #include <cstddef>
- #include <iterator>
- #include <tuple>
- #include <type_traits>
- #include <utility>
- // #include "../config/config.h"
- // #include "fwd.hpp"
- namespace entt {
- /**
- * @brief Utility class to disambiguate overloaded functions.
- * @tparam N Number of choices available.
- */
- template<std::size_t N>
- struct choice_t
- // unfortunately, doxygen cannot parse such a construct
- : /*! @cond TURN_OFF_DOXYGEN */ choice_t<N - 1> /*! @endcond */
- {};
- /*! @copybrief choice_t */
- template<>
- struct choice_t<0> {};
- /**
- * @brief Variable template for the choice trick.
- * @tparam N Number of choices available.
- */
- template<std::size_t N>
- inline constexpr choice_t<N> choice{};
- /**
- * @brief Identity type trait.
- *
- * Useful to establish non-deduced contexts in template argument deduction
- * (waiting for C++20) or to provide types through function arguments.
- *
- * @tparam Type A type.
- */
- template<typename Type>
- struct type_identity {
- /*! @brief Identity type. */
- using type = Type;
- };
- /**
- * @brief Helper type.
- * @tparam Type A type.
- */
- template<typename Type>
- using type_identity_t = typename type_identity<Type>::type;
- /**
- * @brief A type-only `sizeof` wrapper that returns 0 where `sizeof` complains.
- * @tparam Type The type of which to return the size.
- */
- template<typename Type, typename = void>
- struct size_of: std::integral_constant<std::size_t, 0u> {};
- /*! @copydoc size_of */
- template<typename Type>
- struct size_of<Type, std::void_t<decltype(sizeof(Type))>>
- // NOLINTNEXTLINE(bugprone-sizeof-expression)
- : std::integral_constant<std::size_t, sizeof(Type)> {};
- /**
- * @brief Helper variable template.
- * @tparam Type The type of which to return the size.
- */
- template<typename Type>
- inline constexpr std::size_t size_of_v = size_of<Type>::value;
- /**
- * @brief Using declaration to be used to _repeat_ the same type a number of
- * times equal to the size of a given parameter pack.
- * @tparam Type A type to repeat.
- */
- template<typename Type, typename>
- using unpack_as_type = Type;
- /**
- * @brief Helper variable template to be used to _repeat_ the same value a
- * number of times equal to the size of a given parameter pack.
- * @tparam Value A value to repeat.
- */
- template<auto Value, typename>
- inline constexpr auto unpack_as_value = Value;
- /**
- * @brief Wraps a static constant.
- * @tparam Value A static constant.
- */
- template<auto Value>
- using integral_constant = std::integral_constant<decltype(Value), Value>;
- /**
- * @brief Alias template to facilitate the creation of named values.
- * @tparam Value A constant value at least convertible to `id_type`.
- */
- template<id_type Value>
- using tag = integral_constant<Value>;
- /**
- * @brief A class to use to push around lists of types, nothing more.
- * @tparam Type Types provided by the type list.
- */
- template<typename... Type>
- struct type_list {
- /*! @brief Type list type. */
- using type = type_list;
- /*! @brief Compile-time number of elements in the type list. */
- static constexpr auto size = sizeof...(Type);
- };
- /*! @brief Primary template isn't defined on purpose. */
- template<std::size_t, typename>
- struct type_list_element;
- /**
- * @brief Provides compile-time indexed access to the types of a type list.
- * @tparam Index Index of the type to return.
- * @tparam First First type provided by the type list.
- * @tparam Other Other types provided by the type list.
- */
- template<std::size_t Index, typename First, typename... Other>
- struct type_list_element<Index, type_list<First, Other...>>
- : type_list_element<Index - 1u, type_list<Other...>> {};
- /**
- * @brief Provides compile-time indexed access to the types of a type list.
- * @tparam First First type provided by the type list.
- * @tparam Other Other types provided by the type list.
- */
- template<typename First, typename... Other>
- struct type_list_element<0u, type_list<First, Other...>> {
- /*! @brief Searched type. */
- using type = First;
- };
- /**
- * @brief Helper type.
- * @tparam Index Index of the type to return.
- * @tparam List Type list to search into.
- */
- template<std::size_t Index, typename List>
- using type_list_element_t = typename type_list_element<Index, List>::type;
- /*! @brief Primary template isn't defined on purpose. */
- template<typename, typename>
- struct type_list_index;
- /**
- * @brief Provides compile-time type access to the types of a type list.
- * @tparam Type Type to look for and for which to return the index.
- * @tparam First First type provided by the type list.
- * @tparam Other Other types provided by the type list.
- */
- template<typename Type, typename First, typename... Other>
- struct type_list_index<Type, type_list<First, Other...>> {
- /*! @brief Unsigned integer type. */
- using value_type = std::size_t;
- /*! @brief Compile-time position of the given type in the sublist. */
- static constexpr value_type value = 1u + type_list_index<Type, type_list<Other...>>::value;
- };
- /**
- * @brief Provides compile-time type access to the types of a type list.
- * @tparam Type Type to look for and for which to return the index.
- * @tparam Other Other types provided by the type list.
- */
- template<typename Type, typename... Other>
- struct type_list_index<Type, type_list<Type, Other...>> {
- static_assert(type_list_index<Type, type_list<Other...>>::value == sizeof...(Other), "Non-unique type");
- /*! @brief Unsigned integer type. */
- using value_type = std::size_t;
- /*! @brief Compile-time position of the given type in the sublist. */
- static constexpr value_type value = 0u;
- };
- /**
- * @brief Provides compile-time type access to the types of a type list.
- * @tparam Type Type to look for and for which to return the index.
- */
- template<typename Type>
- struct type_list_index<Type, type_list<>> {
- /*! @brief Unsigned integer type. */
- using value_type = std::size_t;
- /*! @brief Compile-time position of the given type in the sublist. */
- static constexpr value_type value = 0u;
- };
- /**
- * @brief Helper variable template.
- * @tparam List Type list.
- * @tparam Type Type to look for and for which to return the index.
- */
- template<typename Type, typename List>
- inline constexpr std::size_t type_list_index_v = type_list_index<Type, List>::value;
- /**
- * @brief Concatenates multiple type lists.
- * @tparam Type Types provided by the first type list.
- * @tparam Other Types provided by the second type list.
- * @return A type list composed by the types of both the type lists.
- */
- template<typename... Type, typename... Other>
- constexpr type_list<Type..., Other...> operator+(type_list<Type...>, type_list<Other...>) {
- return {};
- }
- /*! @brief Primary template isn't defined on purpose. */
- template<typename...>
- struct type_list_cat;
- /*! @brief Concatenates multiple type lists. */
- template<>
- struct type_list_cat<> {
- /*! @brief A type list composed by the types of all the type lists. */
- using type = type_list<>;
- };
- /**
- * @brief Concatenates multiple type lists.
- * @tparam Type Types provided by the first type list.
- * @tparam Other Types provided by the second type list.
- * @tparam List Other type lists, if any.
- */
- template<typename... Type, typename... Other, typename... List>
- struct type_list_cat<type_list<Type...>, type_list<Other...>, List...> {
- /*! @brief A type list composed by the types of all the type lists. */
- using type = typename type_list_cat<type_list<Type..., Other...>, List...>::type;
- };
- /**
- * @brief Concatenates multiple type lists.
- * @tparam Type Types provided by the type list.
- */
- template<typename... Type>
- struct type_list_cat<type_list<Type...>> {
- /*! @brief A type list composed by the types of all the type lists. */
- using type = type_list<Type...>;
- };
- /**
- * @brief Helper type.
- * @tparam List Type lists to concatenate.
- */
- template<typename... List>
- using type_list_cat_t = typename type_list_cat<List...>::type;
- /*! @cond TURN_OFF_DOXYGEN */
- namespace internal {
- template<typename...>
- struct type_list_unique;
- template<typename First, typename... Other, typename... Type>
- struct type_list_unique<type_list<First, Other...>, Type...>
- : std::conditional_t<(std::is_same_v<First, Type> || ...), type_list_unique<type_list<Other...>, Type...>, type_list_unique<type_list<Other...>, Type..., First>> {};
- template<typename... Type>
- struct type_list_unique<type_list<>, Type...> {
- using type = type_list<Type...>;
- };
- } // namespace internal
- /*! @endcond */
- /**
- * @brief Removes duplicates types from a type list.
- * @tparam List Type list.
- */
- template<typename List>
- struct type_list_unique {
- /*! @brief A type list without duplicate types. */
- using type = typename internal::type_list_unique<List>::type;
- };
- /**
- * @brief Helper type.
- * @tparam List Type list.
- */
- template<typename List>
- using type_list_unique_t = typename type_list_unique<List>::type;
- /**
- * @brief Provides the member constant `value` to true if a type list contains a
- * given type, false otherwise.
- * @tparam List Type list.
- * @tparam Type Type to look for.
- */
- template<typename List, typename Type>
- struct type_list_contains;
- /**
- * @copybrief type_list_contains
- * @tparam Type Types provided by the type list.
- * @tparam Other Type to look for.
- */
- template<typename... Type, typename Other>
- struct type_list_contains<type_list<Type...>, Other>
- : std::bool_constant<(std::is_same_v<Type, Other> || ...)> {};
- /**
- * @brief Helper variable template.
- * @tparam List Type list.
- * @tparam Type Type to look for.
- */
- template<typename List, typename Type>
- inline constexpr bool type_list_contains_v = type_list_contains<List, Type>::value;
- /*! @brief Primary template isn't defined on purpose. */
- template<typename...>
- struct type_list_diff;
- /**
- * @brief Computes the difference between two type lists.
- * @tparam Type Types provided by the first type list.
- * @tparam Other Types provided by the second type list.
- */
- template<typename... Type, typename... Other>
- struct type_list_diff<type_list<Type...>, type_list<Other...>> {
- /*! @brief A type list that is the difference between the two type lists. */
- using type = type_list_cat_t<std::conditional_t<type_list_contains_v<type_list<Other...>, Type>, type_list<>, type_list<Type>>...>;
- };
- /**
- * @brief Helper type.
- * @tparam List Type lists between which to compute the difference.
- */
- template<typename... List>
- using type_list_diff_t = typename type_list_diff<List...>::type;
- /*! @brief Primary template isn't defined on purpose. */
- template<typename, template<typename...> class>
- struct type_list_transform;
- /**
- * @brief Applies a given _function_ to a type list and generate a new list.
- * @tparam Type Types provided by the type list.
- * @tparam Op Unary operation as template class with a type member named `type`.
- */
- template<typename... Type, template<typename...> class Op>
- struct type_list_transform<type_list<Type...>, Op> {
- /*! @brief Resulting type list after applying the transform function. */
- // NOLINTNEXTLINE(modernize-type-traits)
- using type = type_list<typename Op<Type>::type...>;
- };
- /**
- * @brief Helper type.
- * @tparam List Type list.
- * @tparam Op Unary operation as template class with a type member named `type`.
- */
- template<typename List, template<typename...> class Op>
- using type_list_transform_t = typename type_list_transform<List, Op>::type;
- /**
- * @brief A class to use to push around lists of constant values, nothing more.
- * @tparam Value Values provided by the value list.
- */
- template<auto... Value>
- struct value_list {
- /*! @brief Value list type. */
- using type = value_list;
- /*! @brief Compile-time number of elements in the value list. */
- static constexpr auto size = sizeof...(Value);
- };
- /*! @brief Primary template isn't defined on purpose. */
- template<std::size_t, typename>
- struct value_list_element;
- /**
- * @brief Provides compile-time indexed access to the values of a value list.
- * @tparam Index Index of the value to return.
- * @tparam Value First value provided by the value list.
- * @tparam Other Other values provided by the value list.
- */
- template<std::size_t Index, auto Value, auto... Other>
- struct value_list_element<Index, value_list<Value, Other...>>
- : value_list_element<Index - 1u, value_list<Other...>> {};
- /**
- * @brief Provides compile-time indexed access to the types of a type list.
- * @tparam Value First value provided by the value list.
- * @tparam Other Other values provided by the value list.
- */
- template<auto Value, auto... Other>
- struct value_list_element<0u, value_list<Value, Other...>> {
- /*! @brief Searched type. */
- using type = decltype(Value);
- /*! @brief Searched value. */
- static constexpr auto value = Value;
- };
- /**
- * @brief Helper type.
- * @tparam Index Index of the type to return.
- * @tparam List Value list to search into.
- */
- template<std::size_t Index, typename List>
- using value_list_element_t = typename value_list_element<Index, List>::type;
- /**
- * @brief Helper type.
- * @tparam Index Index of the value to return.
- * @tparam List Value list to search into.
- */
- template<std::size_t Index, typename List>
- inline constexpr auto value_list_element_v = value_list_element<Index, List>::value;
- /*! @brief Primary template isn't defined on purpose. */
- template<auto, typename>
- struct value_list_index;
- /**
- * @brief Provides compile-time type access to the values of a value list.
- * @tparam Value Value to look for and for which to return the index.
- * @tparam First First value provided by the value list.
- * @tparam Other Other values provided by the value list.
- */
- template<auto Value, auto First, auto... Other>
- struct value_list_index<Value, value_list<First, Other...>> {
- /*! @brief Unsigned integer type. */
- using value_type = std::size_t;
- /*! @brief Compile-time position of the given value in the sublist. */
- static constexpr value_type value = 1u + value_list_index<Value, value_list<Other...>>::value;
- };
- /**
- * @brief Provides compile-time type access to the values of a value list.
- * @tparam Value Value to look for and for which to return the index.
- * @tparam Other Other values provided by the value list.
- */
- template<auto Value, auto... Other>
- struct value_list_index<Value, value_list<Value, Other...>> {
- static_assert(value_list_index<Value, value_list<Other...>>::value == sizeof...(Other), "Non-unique type");
- /*! @brief Unsigned integer type. */
- using value_type = std::size_t;
- /*! @brief Compile-time position of the given value in the sublist. */
- static constexpr value_type value = 0u;
- };
- /**
- * @brief Provides compile-time type access to the values of a value list.
- * @tparam Value Value to look for and for which to return the index.
- */
- template<auto Value>
- struct value_list_index<Value, value_list<>> {
- /*! @brief Unsigned integer type. */
- using value_type = std::size_t;
- /*! @brief Compile-time position of the given type in the sublist. */
- static constexpr value_type value = 0u;
- };
- /**
- * @brief Helper variable template.
- * @tparam List Value list.
- * @tparam Value Value to look for and for which to return the index.
- */
- template<auto Value, typename List>
- inline constexpr std::size_t value_list_index_v = value_list_index<Value, List>::value;
- /**
- * @brief Concatenates multiple value lists.
- * @tparam Value Values provided by the first value list.
- * @tparam Other Values provided by the second value list.
- * @return A value list composed by the values of both the value lists.
- */
- template<auto... Value, auto... Other>
- constexpr value_list<Value..., Other...> operator+(value_list<Value...>, value_list<Other...>) {
- return {};
- }
- /*! @brief Primary template isn't defined on purpose. */
- template<typename...>
- struct value_list_cat;
- /*! @brief Concatenates multiple value lists. */
- template<>
- struct value_list_cat<> {
- /*! @brief A value list composed by the values of all the value lists. */
- using type = value_list<>;
- };
- /**
- * @brief Concatenates multiple value lists.
- * @tparam Value Values provided by the first value list.
- * @tparam Other Values provided by the second value list.
- * @tparam List Other value lists, if any.
- */
- template<auto... Value, auto... Other, typename... List>
- struct value_list_cat<value_list<Value...>, value_list<Other...>, List...> {
- /*! @brief A value list composed by the values of all the value lists. */
- using type = typename value_list_cat<value_list<Value..., Other...>, List...>::type;
- };
- /**
- * @brief Concatenates multiple value lists.
- * @tparam Value Values provided by the value list.
- */
- template<auto... Value>
- struct value_list_cat<value_list<Value...>> {
- /*! @brief A value list composed by the values of all the value lists. */
- using type = value_list<Value...>;
- };
- /**
- * @brief Helper type.
- * @tparam List Value lists to concatenate.
- */
- template<typename... List>
- using value_list_cat_t = typename value_list_cat<List...>::type;
- /*! @brief Primary template isn't defined on purpose. */
- template<typename>
- struct value_list_unique;
- /**
- * @brief Removes duplicates values from a value list.
- * @tparam Value One of the values provided by the given value list.
- * @tparam Other The other values provided by the given value list.
- */
- template<auto Value, auto... Other>
- struct value_list_unique<value_list<Value, Other...>> {
- /*! @brief A value list without duplicate types. */
- using type = std::conditional_t<
- ((Value == Other) || ...),
- typename value_list_unique<value_list<Other...>>::type,
- value_list_cat_t<value_list<Value>, typename value_list_unique<value_list<Other...>>::type>>;
- };
- /*! @brief Removes duplicates values from a value list. */
- template<>
- struct value_list_unique<value_list<>> {
- /*! @brief A value list without duplicate types. */
- using type = value_list<>;
- };
- /**
- * @brief Helper type.
- * @tparam Type A value list.
- */
- template<typename Type>
- using value_list_unique_t = typename value_list_unique<Type>::type;
- /**
- * @brief Provides the member constant `value` to true if a value list contains
- * a given value, false otherwise.
- * @tparam List Value list.
- * @tparam Value Value to look for.
- */
- template<typename List, auto Value>
- struct value_list_contains;
- /**
- * @copybrief value_list_contains
- * @tparam Value Values provided by the value list.
- * @tparam Other Value to look for.
- */
- template<auto... Value, auto Other>
- struct value_list_contains<value_list<Value...>, Other>
- : std::bool_constant<((Value == Other) || ...)> {};
- /**
- * @brief Helper variable template.
- * @tparam List Value list.
- * @tparam Value Value to look for.
- */
- template<typename List, auto Value>
- inline constexpr bool value_list_contains_v = value_list_contains<List, Value>::value;
- /*! @brief Primary template isn't defined on purpose. */
- template<typename...>
- struct value_list_diff;
- /**
- * @brief Computes the difference between two value lists.
- * @tparam Value Values provided by the first value list.
- * @tparam Other Values provided by the second value list.
- */
- template<auto... Value, auto... Other>
- struct value_list_diff<value_list<Value...>, value_list<Other...>> {
- /*! @brief A value list that is the difference between the two value lists. */
- using type = value_list_cat_t<std::conditional_t<value_list_contains_v<value_list<Other...>, Value>, value_list<>, value_list<Value>>...>;
- };
- /**
- * @brief Helper type.
- * @tparam List Value lists between which to compute the difference.
- */
- template<typename... List>
- using value_list_diff_t = typename value_list_diff<List...>::type;
- /*! @brief Same as std::is_invocable, but with tuples. */
- template<typename, typename>
- struct is_applicable: std::false_type {};
- /**
- * @copybrief is_applicable
- * @tparam Func A valid function type.
- * @tparam Tuple Tuple-like type.
- * @tparam Args The list of arguments to use to probe the function type.
- */
- template<typename Func, template<typename...> class Tuple, typename... Args>
- struct is_applicable<Func, Tuple<Args...>>: std::is_invocable<Func, Args...> {};
- /**
- * @copybrief is_applicable
- * @tparam Func A valid function type.
- * @tparam Tuple Tuple-like type.
- * @tparam Args The list of arguments to use to probe the function type.
- */
- template<typename Func, template<typename...> class Tuple, typename... Args>
- struct is_applicable<Func, const Tuple<Args...>>: std::is_invocable<Func, Args...> {};
- /**
- * @brief Helper variable template.
- * @tparam Func A valid function type.
- * @tparam Args The list of arguments to use to probe the function type.
- */
- template<typename Func, typename Args>
- inline constexpr bool is_applicable_v = is_applicable<Func, Args>::value;
- /*! @brief Same as std::is_invocable_r, but with tuples for arguments. */
- template<typename, typename, typename>
- struct is_applicable_r: std::false_type {};
- /**
- * @copybrief is_applicable_r
- * @tparam Ret The type to which the return type of the function should be
- * convertible.
- * @tparam Func A valid function type.
- * @tparam Args The list of arguments to use to probe the function type.
- */
- template<typename Ret, typename Func, typename... Args>
- struct is_applicable_r<Ret, Func, std::tuple<Args...>>: std::is_invocable_r<Ret, Func, Args...> {};
- /**
- * @brief Helper variable template.
- * @tparam Ret The type to which the return type of the function should be
- * convertible.
- * @tparam Func A valid function type.
- * @tparam Args The list of arguments to use to probe the function type.
- */
- template<typename Ret, typename Func, typename Args>
- inline constexpr bool is_applicable_r_v = is_applicable_r<Ret, Func, Args>::value;
- /**
- * @brief Provides the member constant `value` to true if a given type is
- * complete, false otherwise.
- * @tparam Type The type to test.
- */
- template<typename Type, typename = void>
- struct is_complete: std::false_type {};
- /*! @copydoc is_complete */
- template<typename Type>
- struct is_complete<Type, std::void_t<decltype(sizeof(Type))>>: std::true_type {};
- /**
- * @brief Helper variable template.
- * @tparam Type The type to test.
- */
- template<typename Type>
- inline constexpr bool is_complete_v = is_complete<Type>::value;
- /**
- * @brief Provides the member constant `value` to true if a given type is an
- * iterator, false otherwise.
- * @tparam Type The type to test.
- */
- template<typename Type, typename = void>
- struct is_iterator: std::false_type {};
- /*! @cond TURN_OFF_DOXYGEN */
- namespace internal {
- template<typename, typename = void>
- struct has_iterator_category: std::false_type {};
- template<typename Type>
- struct has_iterator_category<Type, std::void_t<typename std::iterator_traits<Type>::iterator_category>>: std::true_type {};
- } // namespace internal
- /*! @endcond */
- /*! @copydoc is_iterator */
- template<typename Type>
- struct is_iterator<Type, std::enable_if_t<!std::is_void_v<std::remove_const_t<std::remove_pointer_t<Type>>>>>
- : internal::has_iterator_category<Type> {};
- /**
- * @brief Helper variable template.
- * @tparam Type The type to test.
- */
- template<typename Type>
- inline constexpr bool is_iterator_v = is_iterator<Type>::value;
- /**
- * @brief Provides the member constant `value` to true if a given type is both
- * an empty and non-final class, false otherwise.
- * @tparam Type The type to test
- */
- template<typename Type>
- struct is_ebco_eligible
- : std::bool_constant<std::is_empty_v<Type> && !std::is_final_v<Type>> {};
- /**
- * @brief Helper variable template.
- * @tparam Type The type to test.
- */
- template<typename Type>
- inline constexpr bool is_ebco_eligible_v = is_ebco_eligible<Type>::value;
- /**
- * @brief Provides the member constant `value` to true if `Type::is_transparent`
- * is valid and denotes a type, false otherwise.
- * @tparam Type The type to test.
- */
- template<typename Type, typename = void>
- struct is_transparent: std::false_type {};
- /*! @copydoc is_transparent */
- template<typename Type>
- struct is_transparent<Type, std::void_t<typename Type::is_transparent>>: std::true_type {};
- /**
- * @brief Helper variable template.
- * @tparam Type The type to test.
- */
- template<typename Type>
- inline constexpr bool is_transparent_v = is_transparent<Type>::value;
- /*! @cond TURN_OFF_DOXYGEN */
- namespace internal {
- template<typename, typename = void>
- struct has_tuple_size_value: std::false_type {};
- template<typename Type>
- struct has_tuple_size_value<Type, std::void_t<decltype(std::tuple_size<const Type>::value)>>: std::true_type {};
- template<typename, typename = void>
- struct has_value_type: std::false_type {};
- template<typename Type>
- struct has_value_type<Type, std::void_t<typename Type::value_type>>: std::true_type {};
- template<typename>
- [[nodiscard]] constexpr bool dispatch_is_equality_comparable();
- template<typename Type, std::size_t... Index>
- [[nodiscard]] constexpr bool unpack_maybe_equality_comparable(std::index_sequence<Index...>) {
- return (dispatch_is_equality_comparable<std::tuple_element_t<Index, Type>>() && ...);
- }
- template<typename>
- [[nodiscard]] constexpr bool maybe_equality_comparable(char) {
- return false;
- }
- template<typename Type>
- [[nodiscard]] constexpr auto maybe_equality_comparable(int) -> decltype(std::declval<Type>() == std::declval<Type>()) {
- return true;
- }
- template<typename Type>
- [[nodiscard]] constexpr bool dispatch_is_equality_comparable() {
- // NOLINTBEGIN(modernize-use-transparent-functors)
- if constexpr(std::is_array_v<Type>) {
- return false;
- } else if constexpr(is_complete_v<std::tuple_size<std::remove_const_t<Type>>>) {
- if constexpr(has_tuple_size_value<Type>::value) {
- return maybe_equality_comparable<Type>(0) && unpack_maybe_equality_comparable<Type>(std::make_index_sequence<std::tuple_size<Type>::value>{});
- } else {
- return maybe_equality_comparable<Type>(0);
- }
- } else if constexpr(has_value_type<Type>::value) {
- if constexpr(is_iterator_v<Type> || std::is_same_v<typename Type::value_type, Type> || dispatch_is_equality_comparable<typename Type::value_type>()) {
- return maybe_equality_comparable<Type>(0);
- } else {
- return false;
- }
- } else {
- return maybe_equality_comparable<Type>(0);
- }
- // NOLINTEND(modernize-use-transparent-functors)
- }
- } // namespace internal
- /*! @endcond */
- /**
- * @brief Provides the member constant `value` to true if a given type is
- * equality comparable, false otherwise.
- * @tparam Type The type to test.
- */
- template<typename Type>
- struct is_equality_comparable: std::bool_constant<internal::dispatch_is_equality_comparable<Type>()> {};
- /*! @copydoc is_equality_comparable */
- template<typename Type>
- struct is_equality_comparable<const Type>: is_equality_comparable<Type> {};
- /**
- * @brief Helper variable template.
- * @tparam Type The type to test.
- */
- template<typename Type>
- inline constexpr bool is_equality_comparable_v = is_equality_comparable<Type>::value;
- /**
- * @brief Transcribes the constness of a type to another type.
- * @tparam To The type to which to transcribe the constness.
- * @tparam From The type from which to transcribe the constness.
- */
- template<typename To, typename From>
- struct constness_as {
- /*! @brief The type resulting from the transcription of the constness. */
- using type = std::remove_const_t<To>;
- };
- /*! @copydoc constness_as */
- template<typename To, typename From>
- struct constness_as<To, const From> {
- /*! @brief The type resulting from the transcription of the constness. */
- using type = const To;
- };
- /**
- * @brief Alias template to facilitate the transcription of the constness.
- * @tparam To The type to which to transcribe the constness.
- * @tparam From The type from which to transcribe the constness.
- */
- template<typename To, typename From>
- using constness_as_t = typename constness_as<To, From>::type;
- /**
- * @brief Extracts the class of a non-static member object or function.
- * @tparam Member A pointer to a non-static member object or function.
- */
- template<typename Member>
- class member_class {
- static_assert(std::is_member_pointer_v<Member>, "Invalid pointer type to non-static member object or function");
- template<typename Class, typename Ret, typename... Args>
- static Class *clazz(Ret (Class::*)(Args...));
- template<typename Class, typename Ret, typename... Args>
- static Class *clazz(Ret (Class::*)(Args...) const);
- template<typename Class, typename Type>
- static Class *clazz(Type Class::*);
- public:
- /*! @brief The class of the given non-static member object or function. */
- using type = std::remove_pointer_t<decltype(clazz(std::declval<Member>()))>;
- };
- /**
- * @brief Helper type.
- * @tparam Member A pointer to a non-static member object or function.
- */
- template<typename Member>
- using member_class_t = typename member_class<Member>::type;
- /**
- * @brief Extracts the n-th argument of a _callable_ type.
- * @tparam Index The index of the argument to extract.
- * @tparam Candidate A valid _callable_ type.
- */
- template<std::size_t Index, typename Candidate>
- class nth_argument {
- template<typename Ret, typename... Args>
- static constexpr type_list<Args...> pick_up(Ret (*)(Args...));
- template<typename Ret, typename Class, typename... Args>
- static constexpr type_list<Args...> pick_up(Ret (Class ::*)(Args...));
- template<typename Ret, typename Class, typename... Args>
- static constexpr type_list<Args...> pick_up(Ret (Class ::*)(Args...) const);
- template<typename Type, typename Class>
- static constexpr type_list<Type> pick_up(Type Class ::*);
- template<typename Type>
- static constexpr decltype(pick_up(&Type::operator())) pick_up(Type &&);
- public:
- /*! @brief N-th argument of the _callable_ type. */
- using type = type_list_element_t<Index, decltype(pick_up(std::declval<Candidate>()))>;
- };
- /**
- * @brief Helper type.
- * @tparam Index The index of the argument to extract.
- * @tparam Candidate A valid function, member function or data member type.
- */
- template<std::size_t Index, typename Candidate>
- using nth_argument_t = typename nth_argument<Index, Candidate>::type;
- } // namespace entt
- template<typename... Type>
- struct std::tuple_size<entt::type_list<Type...>>: std::integral_constant<std::size_t, entt::type_list<Type...>::size> {};
- template<std::size_t Index, typename... Type>
- struct std::tuple_element<Index, entt::type_list<Type...>>: entt::type_list_element<Index, entt::type_list<Type...>> {};
- template<auto... Value>
- struct std::tuple_size<entt::value_list<Value...>>: std::integral_constant<std::size_t, entt::value_list<Value...>::size> {};
- template<std::size_t Index, auto... Value>
- struct std::tuple_element<Index, entt::value_list<Value...>>: entt::value_list_element<Index, entt::value_list<Value...>> {};
- #endif
- namespace entt {
- /*! @cond TURN_OFF_DOXYGEN */
- namespace internal {
- template<typename Type, std::size_t, typename = void>
- struct compressed_pair_element {
- using reference = Type &;
- using const_reference = const Type &;
- template<typename Dummy = Type, typename = std::enable_if_t<std::is_default_constructible_v<Dummy>>>
- // NOLINTNEXTLINE(modernize-use-equals-default)
- constexpr compressed_pair_element() noexcept(std::is_nothrow_default_constructible_v<Type>) {}
- template<typename Arg, typename = std::enable_if_t<!std::is_same_v<std::remove_const_t<std::remove_reference_t<Arg>>, compressed_pair_element>>>
- constexpr compressed_pair_element(Arg &&arg) noexcept(std::is_nothrow_constructible_v<Type, Arg>)
- : value{std::forward<Arg>(arg)} {}
- template<typename... Args, std::size_t... Index>
- constexpr compressed_pair_element(std::tuple<Args...> args, std::index_sequence<Index...>) noexcept(std::is_nothrow_constructible_v<Type, Args...>)
- : value{std::forward<Args>(std::get<Index>(args))...} {}
- [[nodiscard]] constexpr reference get() noexcept {
- return value;
- }
- [[nodiscard]] constexpr const_reference get() const noexcept {
- return value;
- }
- private:
- Type value{};
- };
- template<typename Type, std::size_t Tag>
- struct compressed_pair_element<Type, Tag, std::enable_if_t<is_ebco_eligible_v<Type>>>: Type {
- using reference = Type &;
- using const_reference = const Type &;
- using base_type = Type;
- template<typename Dummy = Type, typename = std::enable_if_t<std::is_default_constructible_v<Dummy>>>
- constexpr compressed_pair_element() noexcept(std::is_nothrow_default_constructible_v<base_type>)
- : base_type{} {}
- template<typename Arg, typename = std::enable_if_t<!std::is_same_v<std::remove_const_t<std::remove_reference_t<Arg>>, compressed_pair_element>>>
- constexpr compressed_pair_element(Arg &&arg) noexcept(std::is_nothrow_constructible_v<base_type, Arg>)
- : base_type{std::forward<Arg>(arg)} {}
- template<typename... Args, std::size_t... Index>
- constexpr compressed_pair_element(std::tuple<Args...> args, std::index_sequence<Index...>) noexcept(std::is_nothrow_constructible_v<base_type, Args...>)
- : base_type{std::forward<Args>(std::get<Index>(args))...} {}
- [[nodiscard]] constexpr reference get() noexcept {
- return *this;
- }
- [[nodiscard]] constexpr const_reference get() const noexcept {
- return *this;
- }
- };
- } // namespace internal
- /*! @endcond */
- /**
- * @brief A compressed pair.
- *
- * A pair that exploits the _Empty Base Class Optimization_ (or _EBCO_) to
- * reduce its final size to a minimum.
- *
- * @tparam First The type of the first element that the pair stores.
- * @tparam Second The type of the second element that the pair stores.
- */
- template<typename First, typename Second>
- class compressed_pair final
- : internal::compressed_pair_element<First, 0u>,
- internal::compressed_pair_element<Second, 1u> {
- using first_base = internal::compressed_pair_element<First, 0u>;
- using second_base = internal::compressed_pair_element<Second, 1u>;
- public:
- /*! @brief The type of the first element that the pair stores. */
- using first_type = First;
- /*! @brief The type of the second element that the pair stores. */
- using second_type = Second;
- /**
- * @brief Default constructor, conditionally enabled.
- *
- * This constructor is only available when the types that the pair stores
- * are both at least default constructible.
- *
- * @tparam Dummy Dummy template parameter used for internal purposes.
- */
- template<bool Dummy = true, typename = std::enable_if_t<Dummy && std::is_default_constructible_v<first_type> && std::is_default_constructible_v<second_type>>>
- constexpr compressed_pair() noexcept(std::is_nothrow_default_constructible_v<first_base> && std::is_nothrow_default_constructible_v<second_base>)
- : first_base{},
- second_base{} {}
- /**
- * @brief Copy constructor.
- * @param other The instance to copy from.
- */
- constexpr compressed_pair(const compressed_pair &other) = default;
- /**
- * @brief Move constructor.
- * @param other The instance to move from.
- */
- constexpr compressed_pair(compressed_pair &&other) noexcept = default;
- /**
- * @brief Constructs a pair from its values.
- * @tparam Arg Type of value to use to initialize the first element.
- * @tparam Other Type of value to use to initialize the second element.
- * @param arg Value to use to initialize the first element.
- * @param other Value to use to initialize the second element.
- */
- template<typename Arg, typename Other>
- constexpr compressed_pair(Arg &&arg, Other &&other) noexcept(std::is_nothrow_constructible_v<first_base, Arg> && std::is_nothrow_constructible_v<second_base, Other>)
- : first_base{std::forward<Arg>(arg)},
- second_base{std::forward<Other>(other)} {}
- /**
- * @brief Constructs a pair by forwarding the arguments to its parts.
- * @tparam Args Types of arguments to use to initialize the first element.
- * @tparam Other Types of arguments to use to initialize the second element.
- * @param args Arguments to use to initialize the first element.
- * @param other Arguments to use to initialize the second element.
- */
- template<typename... Args, typename... Other>
- constexpr compressed_pair(std::piecewise_construct_t, std::tuple<Args...> args, std::tuple<Other...> other) noexcept(std::is_nothrow_constructible_v<first_base, Args...> && std::is_nothrow_constructible_v<second_base, Other...>)
- : first_base{std::move(args), std::index_sequence_for<Args...>{}},
- second_base{std::move(other), std::index_sequence_for<Other...>{}} {}
- /*! @brief Default destructor. */
- ~compressed_pair() = default;
- /**
- * @brief Copy assignment operator.
- * @param other The instance to copy from.
- * @return This compressed pair object.
- */
- constexpr compressed_pair &operator=(const compressed_pair &other) = default;
- /**
- * @brief Move assignment operator.
- * @param other The instance to move from.
- * @return This compressed pair object.
- */
- constexpr compressed_pair &operator=(compressed_pair &&other) noexcept = default;
- /**
- * @brief Returns the first element that a pair stores.
- * @return The first element that a pair stores.
- */
- [[nodiscard]] constexpr first_type &first() noexcept {
- return static_cast<first_base &>(*this).get();
- }
- /*! @copydoc first */
- [[nodiscard]] constexpr const first_type &first() const noexcept {
- return static_cast<const first_base &>(*this).get();
- }
- /**
- * @brief Returns the second element that a pair stores.
- * @return The second element that a pair stores.
- */
- [[nodiscard]] constexpr second_type &second() noexcept {
- return static_cast<second_base &>(*this).get();
- }
- /*! @copydoc second */
- [[nodiscard]] constexpr const second_type &second() const noexcept {
- return static_cast<const second_base &>(*this).get();
- }
- /**
- * @brief Swaps two compressed pair objects.
- * @param other The compressed pair to swap with.
- */
- constexpr void swap(compressed_pair &other) noexcept {
- using std::swap;
- swap(first(), other.first());
- swap(second(), other.second());
- }
- /**
- * @brief Extracts an element from the compressed pair.
- * @tparam Index An integer value that is either 0 or 1.
- * @return Returns a reference to the first element if `Index` is 0 and a
- * reference to the second element if `Index` is 1.
- */
- template<std::size_t Index>
- [[nodiscard]] constexpr decltype(auto) get() noexcept {
- if constexpr(Index == 0u) {
- return first();
- } else {
- static_assert(Index == 1u, "Index out of bounds");
- return second();
- }
- }
- /*! @copydoc get */
- template<std::size_t Index>
- [[nodiscard]] constexpr decltype(auto) get() const noexcept {
- if constexpr(Index == 0u) {
- return first();
- } else {
- static_assert(Index == 1u, "Index out of bounds");
- return second();
- }
- }
- };
- /**
- * @brief Deduction guide.
- * @tparam Type Type of value to use to initialize the first element.
- * @tparam Other Type of value to use to initialize the second element.
- */
- template<typename Type, typename Other>
- compressed_pair(Type &&, Other &&) -> compressed_pair<std::decay_t<Type>, std::decay_t<Other>>;
- /**
- * @brief Swaps two compressed pair objects.
- * @tparam First The type of the first element that the pairs store.
- * @tparam Second The type of the second element that the pairs store.
- * @param lhs A valid compressed pair object.
- * @param rhs A valid compressed pair object.
- */
- template<typename First, typename Second>
- constexpr void swap(compressed_pair<First, Second> &lhs, compressed_pair<First, Second> &rhs) noexcept {
- lhs.swap(rhs);
- }
- } // namespace entt
- namespace std {
- /**
- * @brief `std::tuple_size` specialization for `compressed_pair`s.
- * @tparam First The type of the first element that the pair stores.
- * @tparam Second The type of the second element that the pair stores.
- */
- template<typename First, typename Second>
- struct tuple_size<entt::compressed_pair<First, Second>>: integral_constant<size_t, 2u> {};
- /**
- * @brief `std::tuple_element` specialization for `compressed_pair`s.
- * @tparam Index The index of the type to return.
- * @tparam First The type of the first element that the pair stores.
- * @tparam Second The type of the second element that the pair stores.
- */
- template<size_t Index, typename First, typename Second>
- struct tuple_element<Index, entt::compressed_pair<First, Second>>: conditional<Index == 0u, First, Second> {
- static_assert(Index < 2u, "Index out of bounds");
- };
- } // namespace std
- #endif
- // #include "../core/fwd.hpp"
- // #include "../core/iterator.hpp"
- // #include "../core/utility.hpp"
- #ifndef ENTT_CORE_UTILITY_HPP
- #define ENTT_CORE_UTILITY_HPP
- #include <type_traits>
- #include <utility>
- namespace entt {
- /*! @brief Identity function object (waiting for C++20). */
- struct identity {
- /*! @brief Indicates that this is a transparent function object. */
- using is_transparent = void;
- /**
- * @brief Returns its argument unchanged.
- * @tparam Type Type of the argument.
- * @param value The actual argument.
- * @return The submitted value as-is.
- */
- template<typename Type>
- [[nodiscard]] constexpr Type &&operator()(Type &&value) const noexcept {
- return std::forward<Type>(value);
- }
- };
- /**
- * @brief Constant utility to disambiguate overloaded members of a class.
- * @tparam Type Type of the desired overload.
- * @tparam Class Type of class to which the member belongs.
- * @param member A valid pointer to a member.
- * @return Pointer to the member.
- */
- template<typename Type, typename Class>
- [[nodiscard]] constexpr auto overload(Type Class::*member) noexcept {
- return member;
- }
- /**
- * @brief Constant utility to disambiguate overloaded functions.
- * @tparam Func Function type of the desired overload.
- * @param func A valid pointer to a function.
- * @return Pointer to the function.
- */
- template<typename Func>
- [[nodiscard]] constexpr auto overload(Func *func) noexcept {
- return func;
- }
- /**
- * @brief Helper type for visitors.
- * @tparam Func Types of function objects.
- */
- template<typename... Func>
- struct overloaded: Func... {
- using Func::operator()...;
- };
- /**
- * @brief Deduction guide.
- * @tparam Func Types of function objects.
- */
- template<typename... Func>
- overloaded(Func...) -> overloaded<Func...>;
- /**
- * @brief Basic implementation of a y-combinator.
- * @tparam Func Type of a potentially recursive function.
- */
- template<typename Func>
- struct y_combinator {
- /**
- * @brief Constructs a y-combinator from a given function.
- * @param recursive A potentially recursive function.
- */
- constexpr y_combinator(Func recursive) noexcept(std::is_nothrow_move_constructible_v<Func>)
- : func{std::move(recursive)} {}
- /**
- * @brief Invokes a y-combinator and therefore its underlying function.
- * @tparam Args Types of arguments to use to invoke the underlying function.
- * @param args Parameters to use to invoke the underlying function.
- * @return Return value of the underlying function, if any.
- */
- template<typename... Args>
- constexpr decltype(auto) operator()(Args &&...args) const noexcept(std::is_nothrow_invocable_v<Func, const y_combinator &, Args...>) {
- return func(*this, std::forward<Args>(args)...);
- }
- /*! @copydoc operator()() */
- template<typename... Args>
- constexpr decltype(auto) operator()(Args &&...args) noexcept(std::is_nothrow_invocable_v<Func, y_combinator &, Args...>) {
- return func(*this, std::forward<Args>(args)...);
- }
- private:
- Func func;
- };
- } // namespace entt
- #endif
- // #include "adjacency_matrix.hpp"
- #ifndef ENTT_GRAPH_ADJACENCY_MATRIX_HPP
- #define ENTT_GRAPH_ADJACENCY_MATRIX_HPP
- #include <cstddef>
- #include <iterator>
- #include <memory>
- #include <type_traits>
- #include <utility>
- #include <vector>
- // #include "../config/config.h"
- // #include "../core/iterator.hpp"
- // #include "fwd.hpp"
- namespace entt {
- /*! @cond TURN_OFF_DOXYGEN */
- namespace internal {
- template<typename It>
- class edge_iterator {
- using size_type = std::size_t;
- void find_next() noexcept {
- for(; pos != last && !it[static_cast<typename It::difference_type>(pos)]; pos += offset) {}
- }
- public:
- using value_type = std::pair<size_type, size_type>;
- using pointer = input_iterator_pointer<value_type>;
- using reference = value_type;
- using difference_type = std::ptrdiff_t;
- using iterator_category = std::input_iterator_tag;
- using iterator_concept = std::forward_iterator_tag;
- constexpr edge_iterator() noexcept = default;
- // NOLINTNEXTLINE(bugprone-easily-swappable-parameters)
- constexpr edge_iterator(It base, const size_type vertices, const size_type from, const size_type to, const size_type step) noexcept
- : it{std::move(base)},
- vert{vertices},
- pos{from},
- last{to},
- offset{step} {
- find_next();
- }
- constexpr edge_iterator &operator++() noexcept {
- pos += offset;
- find_next();
- return *this;
- }
- constexpr edge_iterator operator++(int) noexcept {
- const edge_iterator orig = *this;
- return ++(*this), orig;
- }
- [[nodiscard]] constexpr reference operator*() const noexcept {
- return *operator->();
- }
- [[nodiscard]] constexpr pointer operator->() const noexcept {
- return std::make_pair<size_type>(pos / vert, pos % vert);
- }
- template<typename Type>
- friend constexpr bool operator==(const edge_iterator<Type> &, const edge_iterator<Type> &) noexcept;
- private:
- It it{};
- size_type vert{};
- size_type pos{};
- size_type last{};
- size_type offset{};
- };
- template<typename Container>
- [[nodiscard]] constexpr bool operator==(const edge_iterator<Container> &lhs, const edge_iterator<Container> &rhs) noexcept {
- return lhs.pos == rhs.pos;
- }
- template<typename Container>
- [[nodiscard]] constexpr bool operator!=(const edge_iterator<Container> &lhs, const edge_iterator<Container> &rhs) noexcept {
- return !(lhs == rhs);
- }
- } // namespace internal
- /*! @endcond */
- /**
- * @brief Basic implementation of a directed adjacency matrix.
- * @tparam Category Either a directed or undirected category tag.
- * @tparam Allocator Type of allocator used to manage memory and elements.
- */
- template<typename Category, typename Allocator>
- class adjacency_matrix {
- using alloc_traits = std::allocator_traits<Allocator>;
- static_assert(std::is_base_of_v<directed_tag, Category>, "Invalid graph category");
- static_assert(std::is_same_v<typename alloc_traits::value_type, std::size_t>, "Invalid value type");
- using container_type = std::vector<std::size_t, typename alloc_traits::template rebind_alloc<std::size_t>>;
- public:
- /*! @brief Allocator type. */
- using allocator_type = Allocator;
- /*! @brief Unsigned integer type. */
- using size_type = std::size_t;
- /*! @brief Vertex type. */
- using vertex_type = size_type;
- /*! @brief Edge type. */
- using edge_type = std::pair<vertex_type, vertex_type>;
- /*! @brief Vertex iterator type. */
- using vertex_iterator = iota_iterator<vertex_type>;
- /*! @brief Edge iterator type. */
- using edge_iterator = internal::edge_iterator<typename container_type::const_iterator>;
- /*! @brief Out-edge iterator type. */
- using out_edge_iterator = edge_iterator;
- /*! @brief In-edge iterator type. */
- using in_edge_iterator = edge_iterator;
- /*! @brief Graph category tag. */
- using graph_category = Category;
- /*! @brief Default constructor. */
- adjacency_matrix() noexcept(noexcept(allocator_type{}))
- : adjacency_matrix{0u} {
- }
- /**
- * @brief Constructs an empty container with a given allocator.
- * @param allocator The allocator to use.
- */
- explicit adjacency_matrix(const allocator_type &allocator) noexcept
- : adjacency_matrix{0u, allocator} {}
- /**
- * @brief Constructs an empty container with a given allocator and user
- * supplied number of vertices.
- * @param vertices Number of vertices.
- * @param allocator The allocator to use.
- */
- adjacency_matrix(const size_type vertices, const allocator_type &allocator = allocator_type{})
- : matrix{vertices * vertices, allocator},
- vert{vertices} {}
- /*! @brief Default copy constructor. */
- adjacency_matrix(const adjacency_matrix &) = default;
- /**
- * @brief Allocator-extended copy constructor.
- * @param other The instance to copy from.
- * @param allocator The allocator to use.
- */
- adjacency_matrix(const adjacency_matrix &other, const allocator_type &allocator)
- : matrix{other.matrix, allocator},
- vert{other.vert} {}
- /*! @brief Default move constructor. */
- adjacency_matrix(adjacency_matrix &&) noexcept = default;
- /**
- * @brief Allocator-extended move constructor.
- * @param other The instance to move from.
- * @param allocator The allocator to use.
- */
- adjacency_matrix(adjacency_matrix &&other, const allocator_type &allocator)
- : matrix{std::move(other.matrix), allocator},
- vert{other.vert} {}
- /*! @brief Default destructor. */
- ~adjacency_matrix() = default;
- /**
- * @brief Default copy assignment operator.
- * @return This container.
- */
- adjacency_matrix &operator=(const adjacency_matrix &) = default;
- /**
- * @brief Default move assignment operator.
- * @return This container.
- */
- adjacency_matrix &operator=(adjacency_matrix &&) noexcept = default;
- /**
- * @brief Exchanges the contents with those of a given adjacency matrix.
- * @param other Adjacency matrix to exchange the content with.
- */
- void swap(adjacency_matrix &other) noexcept {
- using std::swap;
- swap(matrix, other.matrix);
- swap(vert, other.vert);
- }
- /**
- * @brief Returns the associated allocator.
- * @return The associated allocator.
- */
- [[nodiscard]] constexpr allocator_type get_allocator() const noexcept {
- return matrix.get_allocator();
- }
- /*! @brief Clears the adjacency matrix. */
- void clear() noexcept {
- matrix.clear();
- vert = {};
- }
- /**
- * @brief Returns true if an adjacency matrix is empty, false otherwise.
- *
- * @warning
- * Potentially expensive, try to avoid it on hot paths.
- *
- * @return True if the adjacency matrix is empty, false otherwise.
- */
- [[nodiscard]] bool empty() const noexcept {
- const auto iterable = edges();
- return (iterable.begin() == iterable.end());
- }
- /**
- * @brief Returns the number of vertices.
- * @return The number of vertices.
- */
- [[nodiscard]] size_type size() const noexcept {
- return vert;
- }
- /**
- * @brief Returns an iterable object to visit all vertices of a matrix.
- * @return An iterable object to visit all vertices of a matrix.
- */
- [[nodiscard]] iterable_adaptor<vertex_iterator> vertices() const noexcept {
- return {0u, vert};
- }
- /**
- * @brief Returns an iterable object to visit all edges of a matrix.
- * @return An iterable object to visit all edges of a matrix.
- */
- [[nodiscard]] iterable_adaptor<edge_iterator> edges() const noexcept {
- const auto it = matrix.cbegin();
- const auto sz = matrix.size();
- return {{it, vert, 0u, sz, 1u}, {it, vert, sz, sz, 1u}};
- }
- /**
- * @brief Returns an iterable object to visit all out-edges of a vertex.
- * @param vertex The vertex of which to return all out-edges.
- * @return An iterable object to visit all out-edges of a vertex.
- */
- [[nodiscard]] iterable_adaptor<out_edge_iterator> out_edges(const vertex_type vertex) const noexcept {
- const auto it = matrix.cbegin();
- const auto from = vertex * vert;
- const auto to = from + vert;
- return {{it, vert, from, to, 1u}, {it, vert, to, to, 1u}};
- }
- /**
- * @brief Returns an iterable object to visit all in-edges of a vertex.
- * @param vertex The vertex of which to return all in-edges.
- * @return An iterable object to visit all in-edges of a vertex.
- */
- [[nodiscard]] iterable_adaptor<in_edge_iterator> in_edges(const vertex_type vertex) const noexcept {
- const auto it = matrix.cbegin();
- const auto from = vertex;
- const auto to = vert * vert + from;
- return {{it, vert, from, to, vert}, {it, vert, to, to, vert}};
- }
- /**
- * @brief Resizes an adjacency matrix.
- * @param vertices The new number of vertices.
- */
- void resize(const size_type vertices) {
- adjacency_matrix other{vertices, get_allocator()};
- for(auto [lhs, rhs]: edges()) {
- other.insert(lhs, rhs);
- }
- other.swap(*this);
- }
- /**
- * @brief Inserts an edge into the adjacency matrix, if it does not exist.
- * @param lhs The left hand vertex of the edge.
- * @param rhs The right hand vertex of the edge.
- * @return A pair consisting of an iterator to the inserted element (or to
- * the element that prevented the insertion) and a bool denoting whether the
- * insertion took place.
- */
- std::pair<edge_iterator, bool> insert(const vertex_type lhs, const vertex_type rhs) {
- const auto pos = lhs * vert + rhs;
- if constexpr(std::is_same_v<graph_category, undirected_tag>) {
- const auto rev = rhs * vert + lhs;
- ENTT_ASSERT(matrix[pos] == matrix[rev], "Something went really wrong");
- matrix[rev] = 1u;
- }
- const auto inserted = !std::exchange(matrix[pos], 1u);
- return {edge_iterator{matrix.cbegin(), vert, pos, matrix.size(), 1u}, inserted};
- }
- /**
- * @brief Removes the edge associated with a pair of given vertices.
- * @param lhs The left hand vertex of the edge.
- * @param rhs The right hand vertex of the edge.
- * @return Number of elements removed (either 0 or 1).
- */
- size_type erase(const vertex_type lhs, const vertex_type rhs) {
- const auto pos = lhs * vert + rhs;
- if constexpr(std::is_same_v<graph_category, undirected_tag>) {
- const auto rev = rhs * vert + lhs;
- ENTT_ASSERT(matrix[pos] == matrix[rev], "Something went really wrong");
- matrix[rev] = 0u;
- }
- return std::exchange(matrix[pos], 0u);
- }
- /**
- * @brief Checks if an adjacency matrix contains a given edge.
- * @param lhs The left hand vertex of the edge.
- * @param rhs The right hand vertex of the edge.
- * @return True if there is such an edge, false otherwise.
- */
- [[nodiscard]] bool contains(const vertex_type lhs, const vertex_type rhs) const {
- const auto pos = lhs * vert + rhs;
- return pos < matrix.size() && matrix[pos];
- }
- private:
- container_type matrix;
- size_type vert;
- };
- } // namespace entt
- #endif
- // #include "fwd.hpp"
- namespace entt {
- /**
- * @brief Utility class for creating task graphs.
- * @tparam Allocator Type of allocator used to manage memory and elements.
- */
- template<typename Allocator>
- class basic_flow {
- using alloc_traits = std::allocator_traits<Allocator>;
- static_assert(std::is_same_v<typename alloc_traits::value_type, id_type>, "Invalid value type");
- using task_container_type = dense_set<id_type, identity, std::equal_to<>, typename alloc_traits::template rebind_alloc<id_type>>;
- using ro_rw_container_type = std::vector<std::pair<std::size_t, bool>, typename alloc_traits::template rebind_alloc<std::pair<std::size_t, bool>>>;
- using deps_container_type = dense_map<id_type, ro_rw_container_type, identity, std::equal_to<>, typename alloc_traits::template rebind_alloc<std::pair<const id_type, ro_rw_container_type>>>;
- using adjacency_matrix_type = adjacency_matrix<directed_tag, typename alloc_traits::template rebind_alloc<std::size_t>>;
- void emplace(const id_type res, const bool is_rw) {
- ENTT_ASSERT(index.first() < vertices.size(), "Invalid node");
- if(!deps.contains(res) && sync_on != vertices.size()) {
- deps[res].emplace_back(sync_on, true);
- }
- deps[res].emplace_back(index.first(), is_rw);
- }
- void setup_graph(adjacency_matrix_type &matrix) const {
- for(const auto &elem: deps) {
- const auto last = elem.second.cend();
- auto it = elem.second.cbegin();
- while(it != last) {
- if(it->second) {
- // rw item
- if(auto curr = it++; it != last) {
- if(it->second) {
- matrix.insert(curr->first, it->first);
- } else if(const auto next = std::find_if(it, last, [](const auto &value) { return value.second; }); next != last) {
- for(; it != next; ++it) {
- matrix.insert(curr->first, it->first);
- matrix.insert(it->first, next->first);
- }
- } else {
- for(; it != next; ++it) {
- matrix.insert(curr->first, it->first);
- }
- }
- }
- } else {
- // ro item (first iteration only)
- if(const auto next = std::find_if(it, last, [](const auto &value) { return value.second; }); next != last) {
- for(; it != next; ++it) {
- matrix.insert(it->first, next->first);
- }
- } else {
- it = last;
- }
- }
- }
- }
- }
- void transitive_closure(adjacency_matrix_type &matrix) const {
- const auto length = matrix.size();
- for(std::size_t vk{}; vk < length; ++vk) {
- for(std::size_t vi{}; vi < length; ++vi) {
- for(std::size_t vj{}; vj < length; ++vj) {
- if(matrix.contains(vi, vk) && matrix.contains(vk, vj)) {
- matrix.insert(vi, vj);
- }
- }
- }
- }
- }
- void transitive_reduction(adjacency_matrix_type &matrix) const {
- const auto length = matrix.size();
- for(std::size_t vert{}; vert < length; ++vert) {
- matrix.erase(vert, vert);
- }
- for(std::size_t vj{}; vj < length; ++vj) {
- for(std::size_t vi{}; vi < length; ++vi) {
- if(matrix.contains(vi, vj)) {
- for(std::size_t vk{}; vk < length; ++vk) {
- if(matrix.contains(vj, vk)) {
- matrix.erase(vi, vk);
- }
- }
- }
- }
- }
- }
- public:
- /*! @brief Allocator type. */
- using allocator_type = Allocator;
- /*! @brief Unsigned integer type. */
- using size_type = std::size_t;
- /*! @brief Iterable task list. */
- using iterable = iterable_adaptor<typename task_container_type::const_iterator>;
- /*! @brief Adjacency matrix type. */
- using graph_type = adjacency_matrix_type;
- /*! @brief Default constructor. */
- basic_flow()
- : basic_flow{allocator_type{}} {}
- /**
- * @brief Constructs a flow builder with a given allocator.
- * @param allocator The allocator to use.
- */
- explicit basic_flow(const allocator_type &allocator)
- : index{0u, allocator},
- vertices{allocator},
- deps{allocator} {}
- /*! @brief Default copy constructor. */
- basic_flow(const basic_flow &) = default;
- /**
- * @brief Allocator-extended copy constructor.
- * @param other The instance to copy from.
- * @param allocator The allocator to use.
- */
- basic_flow(const basic_flow &other, const allocator_type &allocator)
- : index{other.index.first(), allocator},
- vertices{other.vertices, allocator},
- deps{other.deps, allocator},
- sync_on{other.sync_on} {}
- /*! @brief Default move constructor. */
- basic_flow(basic_flow &&) noexcept = default;
- /**
- * @brief Allocator-extended move constructor.
- * @param other The instance to move from.
- * @param allocator The allocator to use.
- */
- basic_flow(basic_flow &&other, const allocator_type &allocator)
- : index{other.index.first(), allocator},
- vertices{std::move(other.vertices), allocator},
- deps{std::move(other.deps), allocator},
- sync_on{other.sync_on} {}
- /*! @brief Default destructor. */
- ~basic_flow() = default;
- /**
- * @brief Default copy assignment operator.
- * @return This flow builder.
- */
- basic_flow &operator=(const basic_flow &) = default;
- /**
- * @brief Default move assignment operator.
- * @return This flow builder.
- */
- basic_flow &operator=(basic_flow &&) noexcept = default;
- /**
- * @brief Exchanges the contents with those of a given flow builder.
- * @param other Flow builder to exchange the content with.
- */
- void swap(basic_flow &other) noexcept {
- using std::swap;
- std::swap(index, other.index);
- std::swap(vertices, other.vertices);
- std::swap(deps, other.deps);
- std::swap(sync_on, other.sync_on);
- }
- /**
- * @brief Returns the associated allocator.
- * @return The associated allocator.
- */
- [[nodiscard]] constexpr allocator_type get_allocator() const noexcept {
- return allocator_type{index.second()};
- }
- /**
- * @brief Returns the identifier at specified location.
- * @param pos Position of the identifier to return.
- * @return The requested identifier.
- */
- [[nodiscard]] id_type operator[](const size_type pos) const {
- return vertices.cbegin()[static_cast<typename task_container_type::difference_type>(pos)];
- }
- /*! @brief Clears the flow builder. */
- void clear() noexcept {
- index.first() = {};
- vertices.clear();
- deps.clear();
- sync_on = {};
- }
- /**
- * @brief Returns true if a flow builder contains no tasks, false otherwise.
- * @return True if the flow builder contains no tasks, false otherwise.
- */
- [[nodiscard]] bool empty() const noexcept {
- return vertices.empty();
- }
- /**
- * @brief Returns the number of tasks.
- * @return The number of tasks.
- */
- [[nodiscard]] size_type size() const noexcept {
- return vertices.size();
- }
- /**
- * @brief Binds a task to a flow builder.
- * @param value Task identifier.
- * @return This flow builder.
- */
- basic_flow &bind(const id_type value) {
- sync_on += (sync_on == vertices.size());
- const auto it = vertices.emplace(value).first;
- index.first() = size_type(it - vertices.begin());
- return *this;
- }
- /**
- * @brief Turns the current task into a sync point.
- * @return This flow builder.
- */
- basic_flow &sync() {
- ENTT_ASSERT(index.first() < vertices.size(), "Invalid node");
- sync_on = index.first();
- for(const auto &elem: deps) {
- elem.second.emplace_back(sync_on, true);
- }
- return *this;
- }
- /**
- * @brief Assigns a resource to the current task with a given access mode.
- * @param res Resource identifier.
- * @param is_rw Access mode.
- * @return This flow builder.
- */
- basic_flow &set(const id_type res, bool is_rw = false) {
- emplace(res, is_rw);
- return *this;
- }
- /**
- * @brief Assigns a read-only resource to the current task.
- * @param res Resource identifier.
- * @return This flow builder.
- */
- basic_flow &ro(const id_type res) {
- emplace(res, false);
- return *this;
- }
- /**
- * @brief Assigns a range of read-only resources to the current task.
- * @tparam It Type of input iterator.
- * @param first An iterator to the first element of the range of elements.
- * @param last An iterator past the last element of the range of elements.
- * @return This flow builder.
- */
- template<typename It>
- std::enable_if_t<std::is_same_v<std::remove_const_t<typename std::iterator_traits<It>::value_type>, id_type>, basic_flow &>
- ro(It first, It last) {
- for(; first != last; ++first) {
- emplace(*first, false);
- }
- return *this;
- }
- /**
- * @brief Assigns a writable resource to the current task.
- * @param res Resource identifier.
- * @return This flow builder.
- */
- basic_flow &rw(const id_type res) {
- emplace(res, true);
- return *this;
- }
- /**
- * @brief Assigns a range of writable resources to the current task.
- * @tparam It Type of input iterator.
- * @param first An iterator to the first element of the range of elements.
- * @param last An iterator past the last element of the range of elements.
- * @return This flow builder.
- */
- template<typename It>
- std::enable_if_t<std::is_same_v<std::remove_const_t<typename std::iterator_traits<It>::value_type>, id_type>, basic_flow &>
- rw(It first, It last) {
- for(; first != last; ++first) {
- emplace(*first, true);
- }
- return *this;
- }
- /**
- * @brief Generates a task graph for the current content.
- * @return The adjacency matrix of the task graph.
- */
- [[nodiscard]] graph_type graph() const {
- graph_type matrix{vertices.size(), get_allocator()};
- setup_graph(matrix);
- transitive_closure(matrix);
- transitive_reduction(matrix);
- return matrix;
- }
- private:
- compressed_pair<size_type, allocator_type> index;
- task_container_type vertices;
- deps_container_type deps;
- size_type sync_on{};
- };
- } // namespace entt
- #endif
- // #include "locator/locator.hpp"
- #ifndef ENTT_LOCATOR_LOCATOR_HPP
- #define ENTT_LOCATOR_LOCATOR_HPP
- #include <memory>
- #include <utility>
- // #include "../config/config.h"
- #ifndef ENTT_CONFIG_CONFIG_H
- #define ENTT_CONFIG_CONFIG_H
- // #include "version.h"
- #ifndef ENTT_CONFIG_VERSION_H
- #define ENTT_CONFIG_VERSION_H
- // #include "macro.h"
- #ifndef ENTT_CONFIG_MACRO_H
- #define ENTT_CONFIG_MACRO_H
- // NOLINTBEGIN(cppcoreguidelines-macro-usage)
- #define ENTT_STR(arg) #arg
- #define ENTT_XSTR(arg) ENTT_STR(arg)
- // NOLINTEND(cppcoreguidelines-macro-usage)
- #endif
- // NOLINTBEGIN(cppcoreguidelines-macro-*,modernize-macro-*)
- #define ENTT_VERSION_MAJOR 3
- #define ENTT_VERSION_MINOR 16
- #define ENTT_VERSION_PATCH 0
- #define ENTT_VERSION \
- ENTT_XSTR(ENTT_VERSION_MAJOR) \
- "." ENTT_XSTR(ENTT_VERSION_MINOR) "." ENTT_XSTR(ENTT_VERSION_PATCH)
- // NOLINTEND(cppcoreguidelines-macro-*,modernize-macro-*)
- #endif
- // NOLINTBEGIN(cppcoreguidelines-macro-usage)
- #if defined(__cpp_exceptions) && !defined(ENTT_NOEXCEPTION)
- # define ENTT_CONSTEXPR
- # define ENTT_THROW throw
- # define ENTT_TRY try
- # define ENTT_CATCH catch(...)
- #else
- # define ENTT_CONSTEXPR constexpr // use only with throwing functions (waiting for C++20)
- # define ENTT_THROW
- # define ENTT_TRY if(true)
- # define ENTT_CATCH if(false)
- #endif
- #if __has_include(<version>)
- # include <version>
- #
- # if defined(__cpp_consteval)
- # define ENTT_CONSTEVAL consteval
- # endif
- #endif
- #ifndef ENTT_CONSTEVAL
- # define ENTT_CONSTEVAL constexpr
- #endif
- #ifdef ENTT_USE_ATOMIC
- # include <atomic>
- # define ENTT_MAYBE_ATOMIC(Type) std::atomic<Type>
- #else
- # define ENTT_MAYBE_ATOMIC(Type) Type
- #endif
- #ifndef ENTT_ID_TYPE
- # include <cstdint>
- # define ENTT_ID_TYPE std::uint32_t
- #else
- # include <cstdint> // provides coverage for types in the std namespace
- #endif
- #ifndef ENTT_SPARSE_PAGE
- # define ENTT_SPARSE_PAGE 4096
- #endif
- #ifndef ENTT_PACKED_PAGE
- # define ENTT_PACKED_PAGE 1024
- #endif
- #ifdef ENTT_DISABLE_ASSERT
- # undef ENTT_ASSERT
- # define ENTT_ASSERT(condition, msg) (void(0))
- #elif !defined ENTT_ASSERT
- # include <cassert>
- # define ENTT_ASSERT(condition, msg) assert(((condition) && (msg)))
- #endif
- #ifdef ENTT_DISABLE_ASSERT
- # undef ENTT_ASSERT_CONSTEXPR
- # define ENTT_ASSERT_CONSTEXPR(condition, msg) (void(0))
- #elif !defined ENTT_ASSERT_CONSTEXPR
- # define ENTT_ASSERT_CONSTEXPR(condition, msg) ENTT_ASSERT(condition, msg)
- #endif
- #define ENTT_FAIL(msg) ENTT_ASSERT(false, msg);
- #ifdef ENTT_NO_ETO
- # define ENTT_ETO_TYPE(Type) void
- #else
- # define ENTT_ETO_TYPE(Type) Type
- #endif
- #ifdef ENTT_NO_MIXIN
- # define ENTT_STORAGE(Mixin, ...) __VA_ARGS__
- #else
- # define ENTT_STORAGE(Mixin, ...) Mixin<__VA_ARGS__>
- #endif
- #ifdef ENTT_STANDARD_CPP
- # define ENTT_NONSTD false
- #else
- # define ENTT_NONSTD true
- # if defined __clang__ || defined __GNUC__
- # define ENTT_PRETTY_FUNCTION __PRETTY_FUNCTION__
- # define ENTT_PRETTY_FUNCTION_PREFIX '='
- # define ENTT_PRETTY_FUNCTION_SUFFIX ']'
- # elif defined _MSC_VER
- # define ENTT_PRETTY_FUNCTION __FUNCSIG__
- # define ENTT_PRETTY_FUNCTION_PREFIX '<'
- # define ENTT_PRETTY_FUNCTION_SUFFIX '>'
- # endif
- #endif
- #ifndef ENTT_EXPORT
- # if defined _WIN32 || defined __CYGWIN__ || defined _MSC_VER
- # define ENTT_EXPORT __declspec(dllexport)
- # define ENTT_IMPORT __declspec(dllimport)
- # define ENTT_HIDDEN
- # elif defined __GNUC__ && __GNUC__ >= 4
- # define ENTT_EXPORT __attribute__((visibility("default")))
- # define ENTT_IMPORT __attribute__((visibility("default")))
- # define ENTT_HIDDEN __attribute__((visibility("hidden")))
- # else /* Unsupported compiler */
- # define ENTT_EXPORT
- # define ENTT_IMPORT
- # define ENTT_HIDDEN
- # endif
- #endif
- #ifndef ENTT_API
- # if defined ENTT_API_EXPORT
- # define ENTT_API ENTT_EXPORT
- # elif defined ENTT_API_IMPORT
- # define ENTT_API ENTT_IMPORT
- # else /* No API */
- # define ENTT_API
- # endif
- #endif
- #if defined _MSC_VER
- # pragma detect_mismatch("entt.version", ENTT_VERSION)
- # pragma detect_mismatch("entt.noexcept", ENTT_XSTR(ENTT_TRY))
- # pragma detect_mismatch("entt.id", ENTT_XSTR(ENTT_ID_TYPE))
- # pragma detect_mismatch("entt.nonstd", ENTT_XSTR(ENTT_NONSTD))
- #endif
- // NOLINTEND(cppcoreguidelines-macro-usage)
- #endif
- namespace entt {
- /**
- * @brief Service locator, nothing more.
- *
- * A service locator is used to do what it promises: locate services.<br/>
- * Usually service locators are tightly bound to the services they expose and
- * thus it's hard to define a general purpose class to do that. This tiny class
- * tries to fill the gap and to get rid of the burden of defining a different
- * specific locator for each application.
- *
- * @note
- * Users shouldn't retain references to a service. The recommended way is to
- * retrieve the service implementation currently set each and every time the
- * need for it arises. The risk is to incur in unexpected behaviors otherwise.
- *
- * @tparam Service Service type.
- */
- template<typename Service>
- class locator final {
- class service_handle {
- friend class locator<Service>;
- std::shared_ptr<Service> value{};
- };
- public:
- /*! @brief Service type. */
- using type = Service;
- /*! @brief Service node type. */
- using node_type = service_handle;
- /*! @brief Default constructor, deleted on purpose. */
- locator() = delete;
- /*! @brief Default copy constructor, deleted on purpose. */
- locator(const locator &) = delete;
- /*! @brief Default destructor, deleted on purpose. */
- ~locator() = delete;
- /**
- * @brief Default copy assignment operator, deleted on purpose.
- * @return This locator.
- */
- locator &operator=(const locator &) = delete;
- /**
- * @brief Checks whether a service locator contains a value.
- * @return True if the service locator contains a value, false otherwise.
- */
- [[nodiscard]] static bool has_value() noexcept {
- return (service != nullptr);
- }
- /**
- * @brief Returns a reference to a valid service, if any.
- *
- * @warning
- * Invoking this function can result in undefined behavior if the service
- * hasn't been set yet.
- *
- * @return A reference to the service currently set, if any.
- */
- [[nodiscard]] static Service &value() noexcept {
- ENTT_ASSERT(has_value(), "Service not available");
- return *service;
- }
- /**
- * @brief Returns a service if available or sets it from a fallback type.
- *
- * Arguments are used only if a service doesn't already exist. In all other
- * cases, they are discarded.
- *
- * @tparam Args Types of arguments to use to construct the fallback service.
- * @tparam Type Fallback service type.
- * @param args Parameters to use to construct the fallback service.
- * @return A reference to a valid service.
- */
- template<typename Type = Service, typename... Args>
- [[nodiscard]] static Service &value_or(Args &&...args) {
- return service ? *service : emplace<Type>(std::forward<Args>(args)...);
- }
- /**
- * @brief Sets or replaces a service.
- * @tparam Type Service type.
- * @tparam Args Types of arguments to use to construct the service.
- * @param args Parameters to use to construct the service.
- * @return A reference to a valid service.
- */
- template<typename Type = Service, typename... Args>
- static Service &emplace(Args &&...args) {
- service = std::make_shared<Type>(std::forward<Args>(args)...);
- return *service;
- }
- /**
- * @brief Sets or replaces a service using a given allocator.
- * @tparam Type Service type.
- * @tparam Allocator Type of allocator used to manage memory and elements.
- * @tparam Args Types of arguments to use to construct the service.
- * @param alloc The allocator to use.
- * @param args Parameters to use to construct the service.
- * @return A reference to a valid service.
- */
- template<typename Type = Service, typename Allocator, typename... Args>
- static Service &emplace(std::allocator_arg_t, Allocator alloc, Args &&...args) {
- service = std::allocate_shared<Type>(alloc, std::forward<Args>(args)...);
- return *service;
- }
- /**
- * @brief Returns a handle to the underlying service.
- * @return A handle to the underlying service.
- */
- static node_type handle() noexcept {
- node_type node{};
- node.value = service;
- return node;
- }
- /**
- * @brief Resets or replaces a service.
- * @param other Optional handle with which to replace the service.
- */
- static void reset(const node_type &other = {}) noexcept {
- service = other.value;
- }
- /**
- * @brief Resets or replaces a service.
- * @tparam Type Service type.
- * @tparam Deleter Deleter type.
- * @param elem A pointer to a service to manage.
- * @param deleter A deleter to use to destroy the service.
- */
- template<typename Type, typename Deleter = std::default_delete<Type>>
- static void reset(Type *elem, Deleter deleter = {}) {
- service = std::shared_ptr<Service>{elem, std::move(deleter)};
- }
- private:
- // std::shared_ptr because of its type erased allocator which is useful here
- // NOLINTNEXTLINE(cppcoreguidelines-avoid-non-const-global-variables)
- inline static std::shared_ptr<Service> service{};
- };
- } // namespace entt
- #endif
- // #include "meta/adl_pointer.hpp"
- #ifndef ENTT_META_ADL_POINTER_HPP
- #define ENTT_META_ADL_POINTER_HPP
- namespace entt {
- /**
- * @brief ADL based lookup function for dereferencing meta pointer-like types.
- * @tparam Type Element type.
- * @param value A pointer-like object.
- * @return The value returned from the dereferenced pointer.
- */
- template<typename Type>
- decltype(auto) dereference_meta_pointer_like(const Type &value) {
- return *value;
- }
- /**
- * @brief Fake ADL based lookup function for meta pointer-like types.
- * @tparam Type Element type.
- */
- template<typename Type>
- struct adl_meta_pointer_like {
- /**
- * @brief Uses the default ADL based lookup method to resolve the call.
- * @param value A pointer-like object.
- * @return The value returned from the dereferenced pointer.
- */
- static decltype(auto) dereference(const Type &value) {
- return dereference_meta_pointer_like(value);
- }
- };
- } // namespace entt
- #endif
- // #include "meta/container.hpp"
- // IWYU pragma: always_keep
- #ifndef ENTT_META_CONTAINER_HPP
- #define ENTT_META_CONTAINER_HPP
- #include <array>
- #include <cstddef>
- #include <deque>
- #include <iterator>
- #include <list>
- #include <map>
- #include <set>
- #include <type_traits>
- #include <unordered_map>
- #include <unordered_set>
- #include <vector>
- // #include "../container/dense_map.hpp"
- #ifndef ENTT_CONTAINER_DENSE_MAP_HPP
- #define ENTT_CONTAINER_DENSE_MAP_HPP
- #include <cmath>
- #include <cstddef>
- #include <functional>
- #include <iterator>
- #include <limits>
- #include <memory>
- #include <tuple>
- #include <type_traits>
- #include <utility>
- #include <vector>
- // #include "../config/config.h"
- #ifndef ENTT_CONFIG_CONFIG_H
- #define ENTT_CONFIG_CONFIG_H
- // #include "version.h"
- #ifndef ENTT_CONFIG_VERSION_H
- #define ENTT_CONFIG_VERSION_H
- // #include "macro.h"
- #ifndef ENTT_CONFIG_MACRO_H
- #define ENTT_CONFIG_MACRO_H
- // NOLINTBEGIN(cppcoreguidelines-macro-usage)
- #define ENTT_STR(arg) #arg
- #define ENTT_XSTR(arg) ENTT_STR(arg)
- // NOLINTEND(cppcoreguidelines-macro-usage)
- #endif
- // NOLINTBEGIN(cppcoreguidelines-macro-*,modernize-macro-*)
- #define ENTT_VERSION_MAJOR 3
- #define ENTT_VERSION_MINOR 16
- #define ENTT_VERSION_PATCH 0
- #define ENTT_VERSION \
- ENTT_XSTR(ENTT_VERSION_MAJOR) \
- "." ENTT_XSTR(ENTT_VERSION_MINOR) "." ENTT_XSTR(ENTT_VERSION_PATCH)
- // NOLINTEND(cppcoreguidelines-macro-*,modernize-macro-*)
- #endif
- // NOLINTBEGIN(cppcoreguidelines-macro-usage)
- #if defined(__cpp_exceptions) && !defined(ENTT_NOEXCEPTION)
- # define ENTT_CONSTEXPR
- # define ENTT_THROW throw
- # define ENTT_TRY try
- # define ENTT_CATCH catch(...)
- #else
- # define ENTT_CONSTEXPR constexpr // use only with throwing functions (waiting for C++20)
- # define ENTT_THROW
- # define ENTT_TRY if(true)
- # define ENTT_CATCH if(false)
- #endif
- #if __has_include(<version>)
- # include <version>
- #
- # if defined(__cpp_consteval)
- # define ENTT_CONSTEVAL consteval
- # endif
- #endif
- #ifndef ENTT_CONSTEVAL
- # define ENTT_CONSTEVAL constexpr
- #endif
- #ifdef ENTT_USE_ATOMIC
- # include <atomic>
- # define ENTT_MAYBE_ATOMIC(Type) std::atomic<Type>
- #else
- # define ENTT_MAYBE_ATOMIC(Type) Type
- #endif
- #ifndef ENTT_ID_TYPE
- # include <cstdint>
- # define ENTT_ID_TYPE std::uint32_t
- #else
- # include <cstdint> // provides coverage for types in the std namespace
- #endif
- #ifndef ENTT_SPARSE_PAGE
- # define ENTT_SPARSE_PAGE 4096
- #endif
- #ifndef ENTT_PACKED_PAGE
- # define ENTT_PACKED_PAGE 1024
- #endif
- #ifdef ENTT_DISABLE_ASSERT
- # undef ENTT_ASSERT
- # define ENTT_ASSERT(condition, msg) (void(0))
- #elif !defined ENTT_ASSERT
- # include <cassert>
- # define ENTT_ASSERT(condition, msg) assert(((condition) && (msg)))
- #endif
- #ifdef ENTT_DISABLE_ASSERT
- # undef ENTT_ASSERT_CONSTEXPR
- # define ENTT_ASSERT_CONSTEXPR(condition, msg) (void(0))
- #elif !defined ENTT_ASSERT_CONSTEXPR
- # define ENTT_ASSERT_CONSTEXPR(condition, msg) ENTT_ASSERT(condition, msg)
- #endif
- #define ENTT_FAIL(msg) ENTT_ASSERT(false, msg);
- #ifdef ENTT_NO_ETO
- # define ENTT_ETO_TYPE(Type) void
- #else
- # define ENTT_ETO_TYPE(Type) Type
- #endif
- #ifdef ENTT_NO_MIXIN
- # define ENTT_STORAGE(Mixin, ...) __VA_ARGS__
- #else
- # define ENTT_STORAGE(Mixin, ...) Mixin<__VA_ARGS__>
- #endif
- #ifdef ENTT_STANDARD_CPP
- # define ENTT_NONSTD false
- #else
- # define ENTT_NONSTD true
- # if defined __clang__ || defined __GNUC__
- # define ENTT_PRETTY_FUNCTION __PRETTY_FUNCTION__
- # define ENTT_PRETTY_FUNCTION_PREFIX '='
- # define ENTT_PRETTY_FUNCTION_SUFFIX ']'
- # elif defined _MSC_VER
- # define ENTT_PRETTY_FUNCTION __FUNCSIG__
- # define ENTT_PRETTY_FUNCTION_PREFIX '<'
- # define ENTT_PRETTY_FUNCTION_SUFFIX '>'
- # endif
- #endif
- #ifndef ENTT_EXPORT
- # if defined _WIN32 || defined __CYGWIN__ || defined _MSC_VER
- # define ENTT_EXPORT __declspec(dllexport)
- # define ENTT_IMPORT __declspec(dllimport)
- # define ENTT_HIDDEN
- # elif defined __GNUC__ && __GNUC__ >= 4
- # define ENTT_EXPORT __attribute__((visibility("default")))
- # define ENTT_IMPORT __attribute__((visibility("default")))
- # define ENTT_HIDDEN __attribute__((visibility("hidden")))
- # else /* Unsupported compiler */
- # define ENTT_EXPORT
- # define ENTT_IMPORT
- # define ENTT_HIDDEN
- # endif
- #endif
- #ifndef ENTT_API
- # if defined ENTT_API_EXPORT
- # define ENTT_API ENTT_EXPORT
- # elif defined ENTT_API_IMPORT
- # define ENTT_API ENTT_IMPORT
- # else /* No API */
- # define ENTT_API
- # endif
- #endif
- #if defined _MSC_VER
- # pragma detect_mismatch("entt.version", ENTT_VERSION)
- # pragma detect_mismatch("entt.noexcept", ENTT_XSTR(ENTT_TRY))
- # pragma detect_mismatch("entt.id", ENTT_XSTR(ENTT_ID_TYPE))
- # pragma detect_mismatch("entt.nonstd", ENTT_XSTR(ENTT_NONSTD))
- #endif
- // NOLINTEND(cppcoreguidelines-macro-usage)
- #endif
- // #include "../core/bit.hpp"
- #ifndef ENTT_CORE_BIT_HPP
- #define ENTT_CORE_BIT_HPP
- #include <cstddef>
- #include <limits>
- #include <type_traits>
- // #include "../config/config.h"
- #ifndef ENTT_CONFIG_CONFIG_H
- #define ENTT_CONFIG_CONFIG_H
- // #include "version.h"
- #ifndef ENTT_CONFIG_VERSION_H
- #define ENTT_CONFIG_VERSION_H
- // #include "macro.h"
- #ifndef ENTT_CONFIG_MACRO_H
- #define ENTT_CONFIG_MACRO_H
- // NOLINTBEGIN(cppcoreguidelines-macro-usage)
- #define ENTT_STR(arg) #arg
- #define ENTT_XSTR(arg) ENTT_STR(arg)
- // NOLINTEND(cppcoreguidelines-macro-usage)
- #endif
- // NOLINTBEGIN(cppcoreguidelines-macro-*,modernize-macro-*)
- #define ENTT_VERSION_MAJOR 3
- #define ENTT_VERSION_MINOR 16
- #define ENTT_VERSION_PATCH 0
- #define ENTT_VERSION \
- ENTT_XSTR(ENTT_VERSION_MAJOR) \
- "." ENTT_XSTR(ENTT_VERSION_MINOR) "." ENTT_XSTR(ENTT_VERSION_PATCH)
- // NOLINTEND(cppcoreguidelines-macro-*,modernize-macro-*)
- #endif
- // NOLINTBEGIN(cppcoreguidelines-macro-usage)
- #if defined(__cpp_exceptions) && !defined(ENTT_NOEXCEPTION)
- # define ENTT_CONSTEXPR
- # define ENTT_THROW throw
- # define ENTT_TRY try
- # define ENTT_CATCH catch(...)
- #else
- # define ENTT_CONSTEXPR constexpr // use only with throwing functions (waiting for C++20)
- # define ENTT_THROW
- # define ENTT_TRY if(true)
- # define ENTT_CATCH if(false)
- #endif
- #if __has_include(<version>)
- # include <version>
- #
- # if defined(__cpp_consteval)
- # define ENTT_CONSTEVAL consteval
- # endif
- #endif
- #ifndef ENTT_CONSTEVAL
- # define ENTT_CONSTEVAL constexpr
- #endif
- #ifdef ENTT_USE_ATOMIC
- # include <atomic>
- # define ENTT_MAYBE_ATOMIC(Type) std::atomic<Type>
- #else
- # define ENTT_MAYBE_ATOMIC(Type) Type
- #endif
- #ifndef ENTT_ID_TYPE
- # include <cstdint>
- # define ENTT_ID_TYPE std::uint32_t
- #else
- # include <cstdint> // provides coverage for types in the std namespace
- #endif
- #ifndef ENTT_SPARSE_PAGE
- # define ENTT_SPARSE_PAGE 4096
- #endif
- #ifndef ENTT_PACKED_PAGE
- # define ENTT_PACKED_PAGE 1024
- #endif
- #ifdef ENTT_DISABLE_ASSERT
- # undef ENTT_ASSERT
- # define ENTT_ASSERT(condition, msg) (void(0))
- #elif !defined ENTT_ASSERT
- # include <cassert>
- # define ENTT_ASSERT(condition, msg) assert(((condition) && (msg)))
- #endif
- #ifdef ENTT_DISABLE_ASSERT
- # undef ENTT_ASSERT_CONSTEXPR
- # define ENTT_ASSERT_CONSTEXPR(condition, msg) (void(0))
- #elif !defined ENTT_ASSERT_CONSTEXPR
- # define ENTT_ASSERT_CONSTEXPR(condition, msg) ENTT_ASSERT(condition, msg)
- #endif
- #define ENTT_FAIL(msg) ENTT_ASSERT(false, msg);
- #ifdef ENTT_NO_ETO
- # define ENTT_ETO_TYPE(Type) void
- #else
- # define ENTT_ETO_TYPE(Type) Type
- #endif
- #ifdef ENTT_NO_MIXIN
- # define ENTT_STORAGE(Mixin, ...) __VA_ARGS__
- #else
- # define ENTT_STORAGE(Mixin, ...) Mixin<__VA_ARGS__>
- #endif
- #ifdef ENTT_STANDARD_CPP
- # define ENTT_NONSTD false
- #else
- # define ENTT_NONSTD true
- # if defined __clang__ || defined __GNUC__
- # define ENTT_PRETTY_FUNCTION __PRETTY_FUNCTION__
- # define ENTT_PRETTY_FUNCTION_PREFIX '='
- # define ENTT_PRETTY_FUNCTION_SUFFIX ']'
- # elif defined _MSC_VER
- # define ENTT_PRETTY_FUNCTION __FUNCSIG__
- # define ENTT_PRETTY_FUNCTION_PREFIX '<'
- # define ENTT_PRETTY_FUNCTION_SUFFIX '>'
- # endif
- #endif
- #ifndef ENTT_EXPORT
- # if defined _WIN32 || defined __CYGWIN__ || defined _MSC_VER
- # define ENTT_EXPORT __declspec(dllexport)
- # define ENTT_IMPORT __declspec(dllimport)
- # define ENTT_HIDDEN
- # elif defined __GNUC__ && __GNUC__ >= 4
- # define ENTT_EXPORT __attribute__((visibility("default")))
- # define ENTT_IMPORT __attribute__((visibility("default")))
- # define ENTT_HIDDEN __attribute__((visibility("hidden")))
- # else /* Unsupported compiler */
- # define ENTT_EXPORT
- # define ENTT_IMPORT
- # define ENTT_HIDDEN
- # endif
- #endif
- #ifndef ENTT_API
- # if defined ENTT_API_EXPORT
- # define ENTT_API ENTT_EXPORT
- # elif defined ENTT_API_IMPORT
- # define ENTT_API ENTT_IMPORT
- # else /* No API */
- # define ENTT_API
- # endif
- #endif
- #if defined _MSC_VER
- # pragma detect_mismatch("entt.version", ENTT_VERSION)
- # pragma detect_mismatch("entt.noexcept", ENTT_XSTR(ENTT_TRY))
- # pragma detect_mismatch("entt.id", ENTT_XSTR(ENTT_ID_TYPE))
- # pragma detect_mismatch("entt.nonstd", ENTT_XSTR(ENTT_NONSTD))
- #endif
- // NOLINTEND(cppcoreguidelines-macro-usage)
- #endif
- namespace entt {
- /**
- * @brief Returns the number of set bits in a value (waiting for C++20 and
- * `std::popcount`).
- * @tparam Type Unsigned integer type.
- * @param value A value of unsigned integer type.
- * @return The number of set bits in the value.
- */
- template<typename Type>
- [[nodiscard]] constexpr std::enable_if_t<std::is_unsigned_v<Type>, int> popcount(const Type value) noexcept {
- return value ? (int(value & 1) + popcount(static_cast<Type>(value >> 1))) : 0;
- }
- /**
- * @brief Checks whether a value is a power of two or not (waiting for C++20 and
- * `std::has_single_bit`).
- * @tparam Type Unsigned integer type.
- * @param value A value of unsigned integer type.
- * @return True if the value is a power of two, false otherwise.
- */
- template<typename Type>
- [[nodiscard]] constexpr std::enable_if_t<std::is_unsigned_v<Type>, bool> has_single_bit(const Type value) noexcept {
- return value && ((value & (value - 1)) == 0);
- }
- /**
- * @brief Computes the smallest power of two greater than or equal to a value
- * (waiting for C++20 and `std::bit_ceil`).
- * @tparam Type Unsigned integer type.
- * @param value A value of unsigned integer type.
- * @return The smallest power of two greater than or equal to the given value.
- */
- template<typename Type>
- [[nodiscard]] constexpr std::enable_if_t<std::is_unsigned_v<Type>, Type> next_power_of_two(const Type value) noexcept {
- // NOLINTNEXTLINE(bugprone-assert-side-effect)
- ENTT_ASSERT_CONSTEXPR(value < (Type{1u} << (std::numeric_limits<Type>::digits - 1)), "Numeric limits exceeded");
- Type curr = value - (value != 0u);
- for(int next = 1; next < std::numeric_limits<Type>::digits; next = next * 2) {
- curr |= (curr >> next);
- }
- return ++curr;
- }
- /**
- * @brief Fast module utility function (powers of two only).
- * @tparam Type Unsigned integer type.
- * @param value A value of unsigned integer type.
- * @param mod _Modulus_, it must be a power of two.
- * @return The common remainder.
- */
- template<typename Type>
- [[nodiscard]] constexpr std::enable_if_t<std::is_unsigned_v<Type>, Type> fast_mod(const Type value, const std::size_t mod) noexcept {
- ENTT_ASSERT_CONSTEXPR(has_single_bit(mod), "Value must be a power of two");
- return static_cast<Type>(value & (mod - 1u));
- }
- } // namespace entt
- #endif
- // #include "../core/compressed_pair.hpp"
- #ifndef ENTT_CORE_COMPRESSED_PAIR_HPP
- #define ENTT_CORE_COMPRESSED_PAIR_HPP
- #include <cstddef>
- #include <tuple>
- #include <type_traits>
- #include <utility>
- // #include "fwd.hpp"
- #ifndef ENTT_CORE_FWD_HPP
- #define ENTT_CORE_FWD_HPP
- #include <cstddef>
- #include <cstdint>
- // #include "../config/config.h"
- namespace entt {
- /*! @brief Possible modes of an any object. */
- enum class any_policy : std::uint8_t {
- /*! @brief Default mode, no element available. */
- empty,
- /*! @brief Owning mode, dynamically allocated element. */
- dynamic,
- /*! @brief Owning mode, embedded element. */
- embedded,
- /*! @brief Aliasing mode, non-const reference. */
- ref,
- /*! @brief Const aliasing mode, const reference. */
- cref
- };
- // NOLINTNEXTLINE(cppcoreguidelines-avoid-c-arrays, modernize-avoid-c-arrays)
- template<std::size_t Len = sizeof(double[2]), std::size_t = alignof(double[2])>
- class basic_any;
- /*! @brief Alias declaration for type identifiers. */
- using id_type = ENTT_ID_TYPE;
- /*! @brief Alias declaration for the most common use case. */
- using any = basic_any<>;
- template<typename, typename>
- class compressed_pair;
- template<typename>
- class basic_hashed_string;
- /*! @brief Aliases for common character types. */
- using hashed_string = basic_hashed_string<char>;
- /*! @brief Aliases for common character types. */
- using hashed_wstring = basic_hashed_string<wchar_t>;
- // NOLINTNEXTLINE(bugprone-forward-declaration-namespace)
- struct type_info;
- } // namespace entt
- #endif
- // #include "type_traits.hpp"
- #ifndef ENTT_CORE_TYPE_TRAITS_HPP
- #define ENTT_CORE_TYPE_TRAITS_HPP
- #include <cstddef>
- #include <iterator>
- #include <tuple>
- #include <type_traits>
- #include <utility>
- // #include "../config/config.h"
- // #include "fwd.hpp"
- namespace entt {
- /**
- * @brief Utility class to disambiguate overloaded functions.
- * @tparam N Number of choices available.
- */
- template<std::size_t N>
- struct choice_t
- // unfortunately, doxygen cannot parse such a construct
- : /*! @cond TURN_OFF_DOXYGEN */ choice_t<N - 1> /*! @endcond */
- {};
- /*! @copybrief choice_t */
- template<>
- struct choice_t<0> {};
- /**
- * @brief Variable template for the choice trick.
- * @tparam N Number of choices available.
- */
- template<std::size_t N>
- inline constexpr choice_t<N> choice{};
- /**
- * @brief Identity type trait.
- *
- * Useful to establish non-deduced contexts in template argument deduction
- * (waiting for C++20) or to provide types through function arguments.
- *
- * @tparam Type A type.
- */
- template<typename Type>
- struct type_identity {
- /*! @brief Identity type. */
- using type = Type;
- };
- /**
- * @brief Helper type.
- * @tparam Type A type.
- */
- template<typename Type>
- using type_identity_t = typename type_identity<Type>::type;
- /**
- * @brief A type-only `sizeof` wrapper that returns 0 where `sizeof` complains.
- * @tparam Type The type of which to return the size.
- */
- template<typename Type, typename = void>
- struct size_of: std::integral_constant<std::size_t, 0u> {};
- /*! @copydoc size_of */
- template<typename Type>
- struct size_of<Type, std::void_t<decltype(sizeof(Type))>>
- // NOLINTNEXTLINE(bugprone-sizeof-expression)
- : std::integral_constant<std::size_t, sizeof(Type)> {};
- /**
- * @brief Helper variable template.
- * @tparam Type The type of which to return the size.
- */
- template<typename Type>
- inline constexpr std::size_t size_of_v = size_of<Type>::value;
- /**
- * @brief Using declaration to be used to _repeat_ the same type a number of
- * times equal to the size of a given parameter pack.
- * @tparam Type A type to repeat.
- */
- template<typename Type, typename>
- using unpack_as_type = Type;
- /**
- * @brief Helper variable template to be used to _repeat_ the same value a
- * number of times equal to the size of a given parameter pack.
- * @tparam Value A value to repeat.
- */
- template<auto Value, typename>
- inline constexpr auto unpack_as_value = Value;
- /**
- * @brief Wraps a static constant.
- * @tparam Value A static constant.
- */
- template<auto Value>
- using integral_constant = std::integral_constant<decltype(Value), Value>;
- /**
- * @brief Alias template to facilitate the creation of named values.
- * @tparam Value A constant value at least convertible to `id_type`.
- */
- template<id_type Value>
- using tag = integral_constant<Value>;
- /**
- * @brief A class to use to push around lists of types, nothing more.
- * @tparam Type Types provided by the type list.
- */
- template<typename... Type>
- struct type_list {
- /*! @brief Type list type. */
- using type = type_list;
- /*! @brief Compile-time number of elements in the type list. */
- static constexpr auto size = sizeof...(Type);
- };
- /*! @brief Primary template isn't defined on purpose. */
- template<std::size_t, typename>
- struct type_list_element;
- /**
- * @brief Provides compile-time indexed access to the types of a type list.
- * @tparam Index Index of the type to return.
- * @tparam First First type provided by the type list.
- * @tparam Other Other types provided by the type list.
- */
- template<std::size_t Index, typename First, typename... Other>
- struct type_list_element<Index, type_list<First, Other...>>
- : type_list_element<Index - 1u, type_list<Other...>> {};
- /**
- * @brief Provides compile-time indexed access to the types of a type list.
- * @tparam First First type provided by the type list.
- * @tparam Other Other types provided by the type list.
- */
- template<typename First, typename... Other>
- struct type_list_element<0u, type_list<First, Other...>> {
- /*! @brief Searched type. */
- using type = First;
- };
- /**
- * @brief Helper type.
- * @tparam Index Index of the type to return.
- * @tparam List Type list to search into.
- */
- template<std::size_t Index, typename List>
- using type_list_element_t = typename type_list_element<Index, List>::type;
- /*! @brief Primary template isn't defined on purpose. */
- template<typename, typename>
- struct type_list_index;
- /**
- * @brief Provides compile-time type access to the types of a type list.
- * @tparam Type Type to look for and for which to return the index.
- * @tparam First First type provided by the type list.
- * @tparam Other Other types provided by the type list.
- */
- template<typename Type, typename First, typename... Other>
- struct type_list_index<Type, type_list<First, Other...>> {
- /*! @brief Unsigned integer type. */
- using value_type = std::size_t;
- /*! @brief Compile-time position of the given type in the sublist. */
- static constexpr value_type value = 1u + type_list_index<Type, type_list<Other...>>::value;
- };
- /**
- * @brief Provides compile-time type access to the types of a type list.
- * @tparam Type Type to look for and for which to return the index.
- * @tparam Other Other types provided by the type list.
- */
- template<typename Type, typename... Other>
- struct type_list_index<Type, type_list<Type, Other...>> {
- static_assert(type_list_index<Type, type_list<Other...>>::value == sizeof...(Other), "Non-unique type");
- /*! @brief Unsigned integer type. */
- using value_type = std::size_t;
- /*! @brief Compile-time position of the given type in the sublist. */
- static constexpr value_type value = 0u;
- };
- /**
- * @brief Provides compile-time type access to the types of a type list.
- * @tparam Type Type to look for and for which to return the index.
- */
- template<typename Type>
- struct type_list_index<Type, type_list<>> {
- /*! @brief Unsigned integer type. */
- using value_type = std::size_t;
- /*! @brief Compile-time position of the given type in the sublist. */
- static constexpr value_type value = 0u;
- };
- /**
- * @brief Helper variable template.
- * @tparam List Type list.
- * @tparam Type Type to look for and for which to return the index.
- */
- template<typename Type, typename List>
- inline constexpr std::size_t type_list_index_v = type_list_index<Type, List>::value;
- /**
- * @brief Concatenates multiple type lists.
- * @tparam Type Types provided by the first type list.
- * @tparam Other Types provided by the second type list.
- * @return A type list composed by the types of both the type lists.
- */
- template<typename... Type, typename... Other>
- constexpr type_list<Type..., Other...> operator+(type_list<Type...>, type_list<Other...>) {
- return {};
- }
- /*! @brief Primary template isn't defined on purpose. */
- template<typename...>
- struct type_list_cat;
- /*! @brief Concatenates multiple type lists. */
- template<>
- struct type_list_cat<> {
- /*! @brief A type list composed by the types of all the type lists. */
- using type = type_list<>;
- };
- /**
- * @brief Concatenates multiple type lists.
- * @tparam Type Types provided by the first type list.
- * @tparam Other Types provided by the second type list.
- * @tparam List Other type lists, if any.
- */
- template<typename... Type, typename... Other, typename... List>
- struct type_list_cat<type_list<Type...>, type_list<Other...>, List...> {
- /*! @brief A type list composed by the types of all the type lists. */
- using type = typename type_list_cat<type_list<Type..., Other...>, List...>::type;
- };
- /**
- * @brief Concatenates multiple type lists.
- * @tparam Type Types provided by the type list.
- */
- template<typename... Type>
- struct type_list_cat<type_list<Type...>> {
- /*! @brief A type list composed by the types of all the type lists. */
- using type = type_list<Type...>;
- };
- /**
- * @brief Helper type.
- * @tparam List Type lists to concatenate.
- */
- template<typename... List>
- using type_list_cat_t = typename type_list_cat<List...>::type;
- /*! @cond TURN_OFF_DOXYGEN */
- namespace internal {
- template<typename...>
- struct type_list_unique;
- template<typename First, typename... Other, typename... Type>
- struct type_list_unique<type_list<First, Other...>, Type...>
- : std::conditional_t<(std::is_same_v<First, Type> || ...), type_list_unique<type_list<Other...>, Type...>, type_list_unique<type_list<Other...>, Type..., First>> {};
- template<typename... Type>
- struct type_list_unique<type_list<>, Type...> {
- using type = type_list<Type...>;
- };
- } // namespace internal
- /*! @endcond */
- /**
- * @brief Removes duplicates types from a type list.
- * @tparam List Type list.
- */
- template<typename List>
- struct type_list_unique {
- /*! @brief A type list without duplicate types. */
- using type = typename internal::type_list_unique<List>::type;
- };
- /**
- * @brief Helper type.
- * @tparam List Type list.
- */
- template<typename List>
- using type_list_unique_t = typename type_list_unique<List>::type;
- /**
- * @brief Provides the member constant `value` to true if a type list contains a
- * given type, false otherwise.
- * @tparam List Type list.
- * @tparam Type Type to look for.
- */
- template<typename List, typename Type>
- struct type_list_contains;
- /**
- * @copybrief type_list_contains
- * @tparam Type Types provided by the type list.
- * @tparam Other Type to look for.
- */
- template<typename... Type, typename Other>
- struct type_list_contains<type_list<Type...>, Other>
- : std::bool_constant<(std::is_same_v<Type, Other> || ...)> {};
- /**
- * @brief Helper variable template.
- * @tparam List Type list.
- * @tparam Type Type to look for.
- */
- template<typename List, typename Type>
- inline constexpr bool type_list_contains_v = type_list_contains<List, Type>::value;
- /*! @brief Primary template isn't defined on purpose. */
- template<typename...>
- struct type_list_diff;
- /**
- * @brief Computes the difference between two type lists.
- * @tparam Type Types provided by the first type list.
- * @tparam Other Types provided by the second type list.
- */
- template<typename... Type, typename... Other>
- struct type_list_diff<type_list<Type...>, type_list<Other...>> {
- /*! @brief A type list that is the difference between the two type lists. */
- using type = type_list_cat_t<std::conditional_t<type_list_contains_v<type_list<Other...>, Type>, type_list<>, type_list<Type>>...>;
- };
- /**
- * @brief Helper type.
- * @tparam List Type lists between which to compute the difference.
- */
- template<typename... List>
- using type_list_diff_t = typename type_list_diff<List...>::type;
- /*! @brief Primary template isn't defined on purpose. */
- template<typename, template<typename...> class>
- struct type_list_transform;
- /**
- * @brief Applies a given _function_ to a type list and generate a new list.
- * @tparam Type Types provided by the type list.
- * @tparam Op Unary operation as template class with a type member named `type`.
- */
- template<typename... Type, template<typename...> class Op>
- struct type_list_transform<type_list<Type...>, Op> {
- /*! @brief Resulting type list after applying the transform function. */
- // NOLINTNEXTLINE(modernize-type-traits)
- using type = type_list<typename Op<Type>::type...>;
- };
- /**
- * @brief Helper type.
- * @tparam List Type list.
- * @tparam Op Unary operation as template class with a type member named `type`.
- */
- template<typename List, template<typename...> class Op>
- using type_list_transform_t = typename type_list_transform<List, Op>::type;
- /**
- * @brief A class to use to push around lists of constant values, nothing more.
- * @tparam Value Values provided by the value list.
- */
- template<auto... Value>
- struct value_list {
- /*! @brief Value list type. */
- using type = value_list;
- /*! @brief Compile-time number of elements in the value list. */
- static constexpr auto size = sizeof...(Value);
- };
- /*! @brief Primary template isn't defined on purpose. */
- template<std::size_t, typename>
- struct value_list_element;
- /**
- * @brief Provides compile-time indexed access to the values of a value list.
- * @tparam Index Index of the value to return.
- * @tparam Value First value provided by the value list.
- * @tparam Other Other values provided by the value list.
- */
- template<std::size_t Index, auto Value, auto... Other>
- struct value_list_element<Index, value_list<Value, Other...>>
- : value_list_element<Index - 1u, value_list<Other...>> {};
- /**
- * @brief Provides compile-time indexed access to the types of a type list.
- * @tparam Value First value provided by the value list.
- * @tparam Other Other values provided by the value list.
- */
- template<auto Value, auto... Other>
- struct value_list_element<0u, value_list<Value, Other...>> {
- /*! @brief Searched type. */
- using type = decltype(Value);
- /*! @brief Searched value. */
- static constexpr auto value = Value;
- };
- /**
- * @brief Helper type.
- * @tparam Index Index of the type to return.
- * @tparam List Value list to search into.
- */
- template<std::size_t Index, typename List>
- using value_list_element_t = typename value_list_element<Index, List>::type;
- /**
- * @brief Helper type.
- * @tparam Index Index of the value to return.
- * @tparam List Value list to search into.
- */
- template<std::size_t Index, typename List>
- inline constexpr auto value_list_element_v = value_list_element<Index, List>::value;
- /*! @brief Primary template isn't defined on purpose. */
- template<auto, typename>
- struct value_list_index;
- /**
- * @brief Provides compile-time type access to the values of a value list.
- * @tparam Value Value to look for and for which to return the index.
- * @tparam First First value provided by the value list.
- * @tparam Other Other values provided by the value list.
- */
- template<auto Value, auto First, auto... Other>
- struct value_list_index<Value, value_list<First, Other...>> {
- /*! @brief Unsigned integer type. */
- using value_type = std::size_t;
- /*! @brief Compile-time position of the given value in the sublist. */
- static constexpr value_type value = 1u + value_list_index<Value, value_list<Other...>>::value;
- };
- /**
- * @brief Provides compile-time type access to the values of a value list.
- * @tparam Value Value to look for and for which to return the index.
- * @tparam Other Other values provided by the value list.
- */
- template<auto Value, auto... Other>
- struct value_list_index<Value, value_list<Value, Other...>> {
- static_assert(value_list_index<Value, value_list<Other...>>::value == sizeof...(Other), "Non-unique type");
- /*! @brief Unsigned integer type. */
- using value_type = std::size_t;
- /*! @brief Compile-time position of the given value in the sublist. */
- static constexpr value_type value = 0u;
- };
- /**
- * @brief Provides compile-time type access to the values of a value list.
- * @tparam Value Value to look for and for which to return the index.
- */
- template<auto Value>
- struct value_list_index<Value, value_list<>> {
- /*! @brief Unsigned integer type. */
- using value_type = std::size_t;
- /*! @brief Compile-time position of the given type in the sublist. */
- static constexpr value_type value = 0u;
- };
- /**
- * @brief Helper variable template.
- * @tparam List Value list.
- * @tparam Value Value to look for and for which to return the index.
- */
- template<auto Value, typename List>
- inline constexpr std::size_t value_list_index_v = value_list_index<Value, List>::value;
- /**
- * @brief Concatenates multiple value lists.
- * @tparam Value Values provided by the first value list.
- * @tparam Other Values provided by the second value list.
- * @return A value list composed by the values of both the value lists.
- */
- template<auto... Value, auto... Other>
- constexpr value_list<Value..., Other...> operator+(value_list<Value...>, value_list<Other...>) {
- return {};
- }
- /*! @brief Primary template isn't defined on purpose. */
- template<typename...>
- struct value_list_cat;
- /*! @brief Concatenates multiple value lists. */
- template<>
- struct value_list_cat<> {
- /*! @brief A value list composed by the values of all the value lists. */
- using type = value_list<>;
- };
- /**
- * @brief Concatenates multiple value lists.
- * @tparam Value Values provided by the first value list.
- * @tparam Other Values provided by the second value list.
- * @tparam List Other value lists, if any.
- */
- template<auto... Value, auto... Other, typename... List>
- struct value_list_cat<value_list<Value...>, value_list<Other...>, List...> {
- /*! @brief A value list composed by the values of all the value lists. */
- using type = typename value_list_cat<value_list<Value..., Other...>, List...>::type;
- };
- /**
- * @brief Concatenates multiple value lists.
- * @tparam Value Values provided by the value list.
- */
- template<auto... Value>
- struct value_list_cat<value_list<Value...>> {
- /*! @brief A value list composed by the values of all the value lists. */
- using type = value_list<Value...>;
- };
- /**
- * @brief Helper type.
- * @tparam List Value lists to concatenate.
- */
- template<typename... List>
- using value_list_cat_t = typename value_list_cat<List...>::type;
- /*! @brief Primary template isn't defined on purpose. */
- template<typename>
- struct value_list_unique;
- /**
- * @brief Removes duplicates values from a value list.
- * @tparam Value One of the values provided by the given value list.
- * @tparam Other The other values provided by the given value list.
- */
- template<auto Value, auto... Other>
- struct value_list_unique<value_list<Value, Other...>> {
- /*! @brief A value list without duplicate types. */
- using type = std::conditional_t<
- ((Value == Other) || ...),
- typename value_list_unique<value_list<Other...>>::type,
- value_list_cat_t<value_list<Value>, typename value_list_unique<value_list<Other...>>::type>>;
- };
- /*! @brief Removes duplicates values from a value list. */
- template<>
- struct value_list_unique<value_list<>> {
- /*! @brief A value list without duplicate types. */
- using type = value_list<>;
- };
- /**
- * @brief Helper type.
- * @tparam Type A value list.
- */
- template<typename Type>
- using value_list_unique_t = typename value_list_unique<Type>::type;
- /**
- * @brief Provides the member constant `value` to true if a value list contains
- * a given value, false otherwise.
- * @tparam List Value list.
- * @tparam Value Value to look for.
- */
- template<typename List, auto Value>
- struct value_list_contains;
- /**
- * @copybrief value_list_contains
- * @tparam Value Values provided by the value list.
- * @tparam Other Value to look for.
- */
- template<auto... Value, auto Other>
- struct value_list_contains<value_list<Value...>, Other>
- : std::bool_constant<((Value == Other) || ...)> {};
- /**
- * @brief Helper variable template.
- * @tparam List Value list.
- * @tparam Value Value to look for.
- */
- template<typename List, auto Value>
- inline constexpr bool value_list_contains_v = value_list_contains<List, Value>::value;
- /*! @brief Primary template isn't defined on purpose. */
- template<typename...>
- struct value_list_diff;
- /**
- * @brief Computes the difference between two value lists.
- * @tparam Value Values provided by the first value list.
- * @tparam Other Values provided by the second value list.
- */
- template<auto... Value, auto... Other>
- struct value_list_diff<value_list<Value...>, value_list<Other...>> {
- /*! @brief A value list that is the difference between the two value lists. */
- using type = value_list_cat_t<std::conditional_t<value_list_contains_v<value_list<Other...>, Value>, value_list<>, value_list<Value>>...>;
- };
- /**
- * @brief Helper type.
- * @tparam List Value lists between which to compute the difference.
- */
- template<typename... List>
- using value_list_diff_t = typename value_list_diff<List...>::type;
- /*! @brief Same as std::is_invocable, but with tuples. */
- template<typename, typename>
- struct is_applicable: std::false_type {};
- /**
- * @copybrief is_applicable
- * @tparam Func A valid function type.
- * @tparam Tuple Tuple-like type.
- * @tparam Args The list of arguments to use to probe the function type.
- */
- template<typename Func, template<typename...> class Tuple, typename... Args>
- struct is_applicable<Func, Tuple<Args...>>: std::is_invocable<Func, Args...> {};
- /**
- * @copybrief is_applicable
- * @tparam Func A valid function type.
- * @tparam Tuple Tuple-like type.
- * @tparam Args The list of arguments to use to probe the function type.
- */
- template<typename Func, template<typename...> class Tuple, typename... Args>
- struct is_applicable<Func, const Tuple<Args...>>: std::is_invocable<Func, Args...> {};
- /**
- * @brief Helper variable template.
- * @tparam Func A valid function type.
- * @tparam Args The list of arguments to use to probe the function type.
- */
- template<typename Func, typename Args>
- inline constexpr bool is_applicable_v = is_applicable<Func, Args>::value;
- /*! @brief Same as std::is_invocable_r, but with tuples for arguments. */
- template<typename, typename, typename>
- struct is_applicable_r: std::false_type {};
- /**
- * @copybrief is_applicable_r
- * @tparam Ret The type to which the return type of the function should be
- * convertible.
- * @tparam Func A valid function type.
- * @tparam Args The list of arguments to use to probe the function type.
- */
- template<typename Ret, typename Func, typename... Args>
- struct is_applicable_r<Ret, Func, std::tuple<Args...>>: std::is_invocable_r<Ret, Func, Args...> {};
- /**
- * @brief Helper variable template.
- * @tparam Ret The type to which the return type of the function should be
- * convertible.
- * @tparam Func A valid function type.
- * @tparam Args The list of arguments to use to probe the function type.
- */
- template<typename Ret, typename Func, typename Args>
- inline constexpr bool is_applicable_r_v = is_applicable_r<Ret, Func, Args>::value;
- /**
- * @brief Provides the member constant `value` to true if a given type is
- * complete, false otherwise.
- * @tparam Type The type to test.
- */
- template<typename Type, typename = void>
- struct is_complete: std::false_type {};
- /*! @copydoc is_complete */
- template<typename Type>
- struct is_complete<Type, std::void_t<decltype(sizeof(Type))>>: std::true_type {};
- /**
- * @brief Helper variable template.
- * @tparam Type The type to test.
- */
- template<typename Type>
- inline constexpr bool is_complete_v = is_complete<Type>::value;
- /**
- * @brief Provides the member constant `value` to true if a given type is an
- * iterator, false otherwise.
- * @tparam Type The type to test.
- */
- template<typename Type, typename = void>
- struct is_iterator: std::false_type {};
- /*! @cond TURN_OFF_DOXYGEN */
- namespace internal {
- template<typename, typename = void>
- struct has_iterator_category: std::false_type {};
- template<typename Type>
- struct has_iterator_category<Type, std::void_t<typename std::iterator_traits<Type>::iterator_category>>: std::true_type {};
- } // namespace internal
- /*! @endcond */
- /*! @copydoc is_iterator */
- template<typename Type>
- struct is_iterator<Type, std::enable_if_t<!std::is_void_v<std::remove_const_t<std::remove_pointer_t<Type>>>>>
- : internal::has_iterator_category<Type> {};
- /**
- * @brief Helper variable template.
- * @tparam Type The type to test.
- */
- template<typename Type>
- inline constexpr bool is_iterator_v = is_iterator<Type>::value;
- /**
- * @brief Provides the member constant `value` to true if a given type is both
- * an empty and non-final class, false otherwise.
- * @tparam Type The type to test
- */
- template<typename Type>
- struct is_ebco_eligible
- : std::bool_constant<std::is_empty_v<Type> && !std::is_final_v<Type>> {};
- /**
- * @brief Helper variable template.
- * @tparam Type The type to test.
- */
- template<typename Type>
- inline constexpr bool is_ebco_eligible_v = is_ebco_eligible<Type>::value;
- /**
- * @brief Provides the member constant `value` to true if `Type::is_transparent`
- * is valid and denotes a type, false otherwise.
- * @tparam Type The type to test.
- */
- template<typename Type, typename = void>
- struct is_transparent: std::false_type {};
- /*! @copydoc is_transparent */
- template<typename Type>
- struct is_transparent<Type, std::void_t<typename Type::is_transparent>>: std::true_type {};
- /**
- * @brief Helper variable template.
- * @tparam Type The type to test.
- */
- template<typename Type>
- inline constexpr bool is_transparent_v = is_transparent<Type>::value;
- /*! @cond TURN_OFF_DOXYGEN */
- namespace internal {
- template<typename, typename = void>
- struct has_tuple_size_value: std::false_type {};
- template<typename Type>
- struct has_tuple_size_value<Type, std::void_t<decltype(std::tuple_size<const Type>::value)>>: std::true_type {};
- template<typename, typename = void>
- struct has_value_type: std::false_type {};
- template<typename Type>
- struct has_value_type<Type, std::void_t<typename Type::value_type>>: std::true_type {};
- template<typename>
- [[nodiscard]] constexpr bool dispatch_is_equality_comparable();
- template<typename Type, std::size_t... Index>
- [[nodiscard]] constexpr bool unpack_maybe_equality_comparable(std::index_sequence<Index...>) {
- return (dispatch_is_equality_comparable<std::tuple_element_t<Index, Type>>() && ...);
- }
- template<typename>
- [[nodiscard]] constexpr bool maybe_equality_comparable(char) {
- return false;
- }
- template<typename Type>
- [[nodiscard]] constexpr auto maybe_equality_comparable(int) -> decltype(std::declval<Type>() == std::declval<Type>()) {
- return true;
- }
- template<typename Type>
- [[nodiscard]] constexpr bool dispatch_is_equality_comparable() {
- // NOLINTBEGIN(modernize-use-transparent-functors)
- if constexpr(std::is_array_v<Type>) {
- return false;
- } else if constexpr(is_complete_v<std::tuple_size<std::remove_const_t<Type>>>) {
- if constexpr(has_tuple_size_value<Type>::value) {
- return maybe_equality_comparable<Type>(0) && unpack_maybe_equality_comparable<Type>(std::make_index_sequence<std::tuple_size<Type>::value>{});
- } else {
- return maybe_equality_comparable<Type>(0);
- }
- } else if constexpr(has_value_type<Type>::value) {
- if constexpr(is_iterator_v<Type> || std::is_same_v<typename Type::value_type, Type> || dispatch_is_equality_comparable<typename Type::value_type>()) {
- return maybe_equality_comparable<Type>(0);
- } else {
- return false;
- }
- } else {
- return maybe_equality_comparable<Type>(0);
- }
- // NOLINTEND(modernize-use-transparent-functors)
- }
- } // namespace internal
- /*! @endcond */
- /**
- * @brief Provides the member constant `value` to true if a given type is
- * equality comparable, false otherwise.
- * @tparam Type The type to test.
- */
- template<typename Type>
- struct is_equality_comparable: std::bool_constant<internal::dispatch_is_equality_comparable<Type>()> {};
- /*! @copydoc is_equality_comparable */
- template<typename Type>
- struct is_equality_comparable<const Type>: is_equality_comparable<Type> {};
- /**
- * @brief Helper variable template.
- * @tparam Type The type to test.
- */
- template<typename Type>
- inline constexpr bool is_equality_comparable_v = is_equality_comparable<Type>::value;
- /**
- * @brief Transcribes the constness of a type to another type.
- * @tparam To The type to which to transcribe the constness.
- * @tparam From The type from which to transcribe the constness.
- */
- template<typename To, typename From>
- struct constness_as {
- /*! @brief The type resulting from the transcription of the constness. */
- using type = std::remove_const_t<To>;
- };
- /*! @copydoc constness_as */
- template<typename To, typename From>
- struct constness_as<To, const From> {
- /*! @brief The type resulting from the transcription of the constness. */
- using type = const To;
- };
- /**
- * @brief Alias template to facilitate the transcription of the constness.
- * @tparam To The type to which to transcribe the constness.
- * @tparam From The type from which to transcribe the constness.
- */
- template<typename To, typename From>
- using constness_as_t = typename constness_as<To, From>::type;
- /**
- * @brief Extracts the class of a non-static member object or function.
- * @tparam Member A pointer to a non-static member object or function.
- */
- template<typename Member>
- class member_class {
- static_assert(std::is_member_pointer_v<Member>, "Invalid pointer type to non-static member object or function");
- template<typename Class, typename Ret, typename... Args>
- static Class *clazz(Ret (Class::*)(Args...));
- template<typename Class, typename Ret, typename... Args>
- static Class *clazz(Ret (Class::*)(Args...) const);
- template<typename Class, typename Type>
- static Class *clazz(Type Class::*);
- public:
- /*! @brief The class of the given non-static member object or function. */
- using type = std::remove_pointer_t<decltype(clazz(std::declval<Member>()))>;
- };
- /**
- * @brief Helper type.
- * @tparam Member A pointer to a non-static member object or function.
- */
- template<typename Member>
- using member_class_t = typename member_class<Member>::type;
- /**
- * @brief Extracts the n-th argument of a _callable_ type.
- * @tparam Index The index of the argument to extract.
- * @tparam Candidate A valid _callable_ type.
- */
- template<std::size_t Index, typename Candidate>
- class nth_argument {
- template<typename Ret, typename... Args>
- static constexpr type_list<Args...> pick_up(Ret (*)(Args...));
- template<typename Ret, typename Class, typename... Args>
- static constexpr type_list<Args...> pick_up(Ret (Class ::*)(Args...));
- template<typename Ret, typename Class, typename... Args>
- static constexpr type_list<Args...> pick_up(Ret (Class ::*)(Args...) const);
- template<typename Type, typename Class>
- static constexpr type_list<Type> pick_up(Type Class ::*);
- template<typename Type>
- static constexpr decltype(pick_up(&Type::operator())) pick_up(Type &&);
- public:
- /*! @brief N-th argument of the _callable_ type. */
- using type = type_list_element_t<Index, decltype(pick_up(std::declval<Candidate>()))>;
- };
- /**
- * @brief Helper type.
- * @tparam Index The index of the argument to extract.
- * @tparam Candidate A valid function, member function or data member type.
- */
- template<std::size_t Index, typename Candidate>
- using nth_argument_t = typename nth_argument<Index, Candidate>::type;
- } // namespace entt
- template<typename... Type>
- struct std::tuple_size<entt::type_list<Type...>>: std::integral_constant<std::size_t, entt::type_list<Type...>::size> {};
- template<std::size_t Index, typename... Type>
- struct std::tuple_element<Index, entt::type_list<Type...>>: entt::type_list_element<Index, entt::type_list<Type...>> {};
- template<auto... Value>
- struct std::tuple_size<entt::value_list<Value...>>: std::integral_constant<std::size_t, entt::value_list<Value...>::size> {};
- template<std::size_t Index, auto... Value>
- struct std::tuple_element<Index, entt::value_list<Value...>>: entt::value_list_element<Index, entt::value_list<Value...>> {};
- #endif
- namespace entt {
- /*! @cond TURN_OFF_DOXYGEN */
- namespace internal {
- template<typename Type, std::size_t, typename = void>
- struct compressed_pair_element {
- using reference = Type &;
- using const_reference = const Type &;
- template<typename Dummy = Type, typename = std::enable_if_t<std::is_default_constructible_v<Dummy>>>
- // NOLINTNEXTLINE(modernize-use-equals-default)
- constexpr compressed_pair_element() noexcept(std::is_nothrow_default_constructible_v<Type>) {}
- template<typename Arg, typename = std::enable_if_t<!std::is_same_v<std::remove_const_t<std::remove_reference_t<Arg>>, compressed_pair_element>>>
- constexpr compressed_pair_element(Arg &&arg) noexcept(std::is_nothrow_constructible_v<Type, Arg>)
- : value{std::forward<Arg>(arg)} {}
- template<typename... Args, std::size_t... Index>
- constexpr compressed_pair_element(std::tuple<Args...> args, std::index_sequence<Index...>) noexcept(std::is_nothrow_constructible_v<Type, Args...>)
- : value{std::forward<Args>(std::get<Index>(args))...} {}
- [[nodiscard]] constexpr reference get() noexcept {
- return value;
- }
- [[nodiscard]] constexpr const_reference get() const noexcept {
- return value;
- }
- private:
- Type value{};
- };
- template<typename Type, std::size_t Tag>
- struct compressed_pair_element<Type, Tag, std::enable_if_t<is_ebco_eligible_v<Type>>>: Type {
- using reference = Type &;
- using const_reference = const Type &;
- using base_type = Type;
- template<typename Dummy = Type, typename = std::enable_if_t<std::is_default_constructible_v<Dummy>>>
- constexpr compressed_pair_element() noexcept(std::is_nothrow_default_constructible_v<base_type>)
- : base_type{} {}
- template<typename Arg, typename = std::enable_if_t<!std::is_same_v<std::remove_const_t<std::remove_reference_t<Arg>>, compressed_pair_element>>>
- constexpr compressed_pair_element(Arg &&arg) noexcept(std::is_nothrow_constructible_v<base_type, Arg>)
- : base_type{std::forward<Arg>(arg)} {}
- template<typename... Args, std::size_t... Index>
- constexpr compressed_pair_element(std::tuple<Args...> args, std::index_sequence<Index...>) noexcept(std::is_nothrow_constructible_v<base_type, Args...>)
- : base_type{std::forward<Args>(std::get<Index>(args))...} {}
- [[nodiscard]] constexpr reference get() noexcept {
- return *this;
- }
- [[nodiscard]] constexpr const_reference get() const noexcept {
- return *this;
- }
- };
- } // namespace internal
- /*! @endcond */
- /**
- * @brief A compressed pair.
- *
- * A pair that exploits the _Empty Base Class Optimization_ (or _EBCO_) to
- * reduce its final size to a minimum.
- *
- * @tparam First The type of the first element that the pair stores.
- * @tparam Second The type of the second element that the pair stores.
- */
- template<typename First, typename Second>
- class compressed_pair final
- : internal::compressed_pair_element<First, 0u>,
- internal::compressed_pair_element<Second, 1u> {
- using first_base = internal::compressed_pair_element<First, 0u>;
- using second_base = internal::compressed_pair_element<Second, 1u>;
- public:
- /*! @brief The type of the first element that the pair stores. */
- using first_type = First;
- /*! @brief The type of the second element that the pair stores. */
- using second_type = Second;
- /**
- * @brief Default constructor, conditionally enabled.
- *
- * This constructor is only available when the types that the pair stores
- * are both at least default constructible.
- *
- * @tparam Dummy Dummy template parameter used for internal purposes.
- */
- template<bool Dummy = true, typename = std::enable_if_t<Dummy && std::is_default_constructible_v<first_type> && std::is_default_constructible_v<second_type>>>
- constexpr compressed_pair() noexcept(std::is_nothrow_default_constructible_v<first_base> && std::is_nothrow_default_constructible_v<second_base>)
- : first_base{},
- second_base{} {}
- /**
- * @brief Copy constructor.
- * @param other The instance to copy from.
- */
- constexpr compressed_pair(const compressed_pair &other) = default;
- /**
- * @brief Move constructor.
- * @param other The instance to move from.
- */
- constexpr compressed_pair(compressed_pair &&other) noexcept = default;
- /**
- * @brief Constructs a pair from its values.
- * @tparam Arg Type of value to use to initialize the first element.
- * @tparam Other Type of value to use to initialize the second element.
- * @param arg Value to use to initialize the first element.
- * @param other Value to use to initialize the second element.
- */
- template<typename Arg, typename Other>
- constexpr compressed_pair(Arg &&arg, Other &&other) noexcept(std::is_nothrow_constructible_v<first_base, Arg> && std::is_nothrow_constructible_v<second_base, Other>)
- : first_base{std::forward<Arg>(arg)},
- second_base{std::forward<Other>(other)} {}
- /**
- * @brief Constructs a pair by forwarding the arguments to its parts.
- * @tparam Args Types of arguments to use to initialize the first element.
- * @tparam Other Types of arguments to use to initialize the second element.
- * @param args Arguments to use to initialize the first element.
- * @param other Arguments to use to initialize the second element.
- */
- template<typename... Args, typename... Other>
- constexpr compressed_pair(std::piecewise_construct_t, std::tuple<Args...> args, std::tuple<Other...> other) noexcept(std::is_nothrow_constructible_v<first_base, Args...> && std::is_nothrow_constructible_v<second_base, Other...>)
- : first_base{std::move(args), std::index_sequence_for<Args...>{}},
- second_base{std::move(other), std::index_sequence_for<Other...>{}} {}
- /*! @brief Default destructor. */
- ~compressed_pair() = default;
- /**
- * @brief Copy assignment operator.
- * @param other The instance to copy from.
- * @return This compressed pair object.
- */
- constexpr compressed_pair &operator=(const compressed_pair &other) = default;
- /**
- * @brief Move assignment operator.
- * @param other The instance to move from.
- * @return This compressed pair object.
- */
- constexpr compressed_pair &operator=(compressed_pair &&other) noexcept = default;
- /**
- * @brief Returns the first element that a pair stores.
- * @return The first element that a pair stores.
- */
- [[nodiscard]] constexpr first_type &first() noexcept {
- return static_cast<first_base &>(*this).get();
- }
- /*! @copydoc first */
- [[nodiscard]] constexpr const first_type &first() const noexcept {
- return static_cast<const first_base &>(*this).get();
- }
- /**
- * @brief Returns the second element that a pair stores.
- * @return The second element that a pair stores.
- */
- [[nodiscard]] constexpr second_type &second() noexcept {
- return static_cast<second_base &>(*this).get();
- }
- /*! @copydoc second */
- [[nodiscard]] constexpr const second_type &second() const noexcept {
- return static_cast<const second_base &>(*this).get();
- }
- /**
- * @brief Swaps two compressed pair objects.
- * @param other The compressed pair to swap with.
- */
- constexpr void swap(compressed_pair &other) noexcept {
- using std::swap;
- swap(first(), other.first());
- swap(second(), other.second());
- }
- /**
- * @brief Extracts an element from the compressed pair.
- * @tparam Index An integer value that is either 0 or 1.
- * @return Returns a reference to the first element if `Index` is 0 and a
- * reference to the second element if `Index` is 1.
- */
- template<std::size_t Index>
- [[nodiscard]] constexpr decltype(auto) get() noexcept {
- if constexpr(Index == 0u) {
- return first();
- } else {
- static_assert(Index == 1u, "Index out of bounds");
- return second();
- }
- }
- /*! @copydoc get */
- template<std::size_t Index>
- [[nodiscard]] constexpr decltype(auto) get() const noexcept {
- if constexpr(Index == 0u) {
- return first();
- } else {
- static_assert(Index == 1u, "Index out of bounds");
- return second();
- }
- }
- };
- /**
- * @brief Deduction guide.
- * @tparam Type Type of value to use to initialize the first element.
- * @tparam Other Type of value to use to initialize the second element.
- */
- template<typename Type, typename Other>
- compressed_pair(Type &&, Other &&) -> compressed_pair<std::decay_t<Type>, std::decay_t<Other>>;
- /**
- * @brief Swaps two compressed pair objects.
- * @tparam First The type of the first element that the pairs store.
- * @tparam Second The type of the second element that the pairs store.
- * @param lhs A valid compressed pair object.
- * @param rhs A valid compressed pair object.
- */
- template<typename First, typename Second>
- constexpr void swap(compressed_pair<First, Second> &lhs, compressed_pair<First, Second> &rhs) noexcept {
- lhs.swap(rhs);
- }
- } // namespace entt
- namespace std {
- /**
- * @brief `std::tuple_size` specialization for `compressed_pair`s.
- * @tparam First The type of the first element that the pair stores.
- * @tparam Second The type of the second element that the pair stores.
- */
- template<typename First, typename Second>
- struct tuple_size<entt::compressed_pair<First, Second>>: integral_constant<size_t, 2u> {};
- /**
- * @brief `std::tuple_element` specialization for `compressed_pair`s.
- * @tparam Index The index of the type to return.
- * @tparam First The type of the first element that the pair stores.
- * @tparam Second The type of the second element that the pair stores.
- */
- template<size_t Index, typename First, typename Second>
- struct tuple_element<Index, entt::compressed_pair<First, Second>>: conditional<Index == 0u, First, Second> {
- static_assert(Index < 2u, "Index out of bounds");
- };
- } // namespace std
- #endif
- // #include "../core/iterator.hpp"
- #ifndef ENTT_CORE_ITERATOR_HPP
- #define ENTT_CORE_ITERATOR_HPP
- #include <iterator>
- #include <memory>
- #include <type_traits>
- #include <utility>
- namespace entt {
- /**
- * @brief Helper type to use as pointer with input iterators.
- * @tparam Type of wrapped value.
- */
- template<typename Type>
- struct input_iterator_pointer final {
- /*! @brief Value type. */
- using value_type = Type;
- /*! @brief Pointer type. */
- using pointer = Type *;
- /*! @brief Reference type. */
- using reference = Type &;
- /**
- * @brief Constructs a proxy object by move.
- * @param val Value to use to initialize the proxy object.
- */
- constexpr input_iterator_pointer(value_type &&val) noexcept(std::is_nothrow_move_constructible_v<value_type>)
- : value{std::move(val)} {}
- /**
- * @brief Access operator for accessing wrapped values.
- * @return A pointer to the wrapped value.
- */
- [[nodiscard]] constexpr pointer operator->() noexcept {
- return std::addressof(value);
- }
- /**
- * @brief Dereference operator for accessing wrapped values.
- * @return A reference to the wrapped value.
- */
- [[nodiscard]] constexpr reference operator*() noexcept {
- return value;
- }
- private:
- Type value;
- };
- /**
- * @brief Plain iota iterator (waiting for C++20).
- * @tparam Type Value type.
- */
- template<typename Type>
- class iota_iterator final {
- static_assert(std::is_integral_v<Type>, "Not an integral type");
- public:
- /*! @brief Value type, likely an integral one. */
- using value_type = Type;
- /*! @brief Invalid pointer type. */
- using pointer = void;
- /*! @brief Non-reference type, same as value type. */
- using reference = value_type;
- /*! @brief Difference type. */
- using difference_type = std::ptrdiff_t;
- /*! @brief Iterator category. */
- using iterator_category = std::input_iterator_tag;
- /*! @brief Default constructor. */
- constexpr iota_iterator() noexcept
- : current{} {}
- /**
- * @brief Constructs an iota iterator from a given value.
- * @param init The initial value assigned to the iota iterator.
- */
- constexpr iota_iterator(const value_type init) noexcept
- : current{init} {}
- /**
- * @brief Pre-increment operator.
- * @return This iota iterator.
- */
- constexpr iota_iterator &operator++() noexcept {
- return ++current, *this;
- }
- /**
- * @brief Post-increment operator.
- * @return This iota iterator.
- */
- constexpr iota_iterator operator++(int) noexcept {
- const iota_iterator orig = *this;
- return ++(*this), orig;
- }
- /**
- * @brief Dereference operator.
- * @return The underlying value.
- */
- [[nodiscard]] constexpr reference operator*() const noexcept {
- return current;
- }
- private:
- value_type current;
- };
- /**
- * @brief Comparison operator.
- * @tparam Type Value type of the iota iterator.
- * @param lhs A properly initialized iota iterator.
- * @param rhs A properly initialized iota iterator.
- * @return True if the two iterators are identical, false otherwise.
- */
- template<typename Type>
- [[nodiscard]] constexpr bool operator==(const iota_iterator<Type> &lhs, const iota_iterator<Type> &rhs) noexcept {
- return *lhs == *rhs;
- }
- /**
- * @brief Comparison operator.
- * @tparam Type Value type of the iota iterator.
- * @param lhs A properly initialized iota iterator.
- * @param rhs A properly initialized iota iterator.
- * @return True if the two iterators differ, false otherwise.
- */
- template<typename Type>
- [[nodiscard]] constexpr bool operator!=(const iota_iterator<Type> &lhs, const iota_iterator<Type> &rhs) noexcept {
- return !(lhs == rhs);
- }
- /**
- * @brief Utility class to create an iterable object from a pair of iterators.
- * @tparam It Type of iterator.
- * @tparam Sentinel Type of sentinel.
- */
- template<typename It, typename Sentinel = It>
- struct iterable_adaptor final {
- /*! @brief Value type. */
- using value_type = typename std::iterator_traits<It>::value_type;
- /*! @brief Iterator type. */
- using iterator = It;
- /*! @brief Sentinel type. */
- using sentinel = Sentinel;
- /*! @brief Default constructor. */
- constexpr iterable_adaptor() noexcept(std::is_nothrow_default_constructible_v<iterator> && std::is_nothrow_default_constructible_v<sentinel>)
- : first{},
- last{} {}
- /**
- * @brief Creates an iterable object from a pair of iterators.
- * @param from Begin iterator.
- * @param to End iterator.
- */
- constexpr iterable_adaptor(iterator from, sentinel to) noexcept(std::is_nothrow_move_constructible_v<iterator> && std::is_nothrow_move_constructible_v<sentinel>)
- : first{std::move(from)},
- last{std::move(to)} {}
- /**
- * @brief Returns an iterator to the beginning.
- * @return An iterator to the first element of the range.
- */
- [[nodiscard]] constexpr iterator begin() const noexcept {
- return first;
- }
- /**
- * @brief Returns an iterator to the end.
- * @return An iterator to the element following the last element of the
- * range.
- */
- [[nodiscard]] constexpr sentinel end() const noexcept {
- return last;
- }
- /*! @copydoc begin */
- [[nodiscard]] constexpr iterator cbegin() const noexcept {
- return begin();
- }
- /*! @copydoc end */
- [[nodiscard]] constexpr sentinel cend() const noexcept {
- return end();
- }
- private:
- It first;
- Sentinel last;
- };
- } // namespace entt
- #endif
- // #include "../core/memory.hpp"
- #ifndef ENTT_CORE_MEMORY_HPP
- #define ENTT_CORE_MEMORY_HPP
- #include <cstddef>
- #include <memory>
- #include <tuple>
- #include <type_traits>
- #include <utility>
- // #include "../config/config.h"
- namespace entt {
- /**
- * @brief Unwraps fancy pointers, does nothing otherwise (waiting for C++20).
- * @tparam Type Pointer type.
- * @param ptr Fancy or raw pointer.
- * @return A raw pointer that represents the address of the original pointer.
- */
- template<typename Type>
- [[nodiscard]] constexpr auto to_address(Type &&ptr) noexcept {
- if constexpr(std::is_pointer_v<std::decay_t<Type>>) {
- return ptr;
- } else {
- return to_address(std::forward<Type>(ptr).operator->());
- }
- }
- /**
- * @brief Utility function to design allocation-aware containers.
- * @tparam Allocator Type of allocator.
- * @param lhs A valid allocator.
- * @param rhs Another valid allocator.
- */
- template<typename Allocator>
- constexpr void propagate_on_container_copy_assignment([[maybe_unused]] Allocator &lhs, [[maybe_unused]] Allocator &rhs) noexcept {
- if constexpr(std::allocator_traits<Allocator>::propagate_on_container_copy_assignment::value) {
- lhs = rhs;
- }
- }
- /**
- * @brief Utility function to design allocation-aware containers.
- * @tparam Allocator Type of allocator.
- * @param lhs A valid allocator.
- * @param rhs Another valid allocator.
- */
- template<typename Allocator>
- constexpr void propagate_on_container_move_assignment([[maybe_unused]] Allocator &lhs, [[maybe_unused]] Allocator &rhs) noexcept {
- if constexpr(std::allocator_traits<Allocator>::propagate_on_container_move_assignment::value) {
- lhs = std::move(rhs);
- }
- }
- /**
- * @brief Utility function to design allocation-aware containers.
- * @tparam Allocator Type of allocator.
- * @param lhs A valid allocator.
- * @param rhs Another valid allocator.
- */
- template<typename Allocator>
- constexpr void propagate_on_container_swap([[maybe_unused]] Allocator &lhs, [[maybe_unused]] Allocator &rhs) noexcept {
- if constexpr(std::allocator_traits<Allocator>::propagate_on_container_swap::value) {
- using std::swap;
- swap(lhs, rhs);
- } else {
- ENTT_ASSERT_CONSTEXPR(lhs == rhs, "Cannot swap the containers");
- }
- }
- /**
- * @brief Deleter for allocator-aware unique pointers (waiting for C++20).
- * @tparam Allocator Type of allocator used to manage memory and elements.
- */
- template<typename Allocator>
- struct allocation_deleter: private Allocator {
- /*! @brief Allocator type. */
- using allocator_type = Allocator;
- /*! @brief Pointer type. */
- using pointer = typename std::allocator_traits<Allocator>::pointer;
- /**
- * @brief Inherited constructors.
- * @param alloc The allocator to use.
- */
- constexpr allocation_deleter(const allocator_type &alloc) noexcept(std::is_nothrow_copy_constructible_v<allocator_type>)
- : Allocator{alloc} {}
- /**
- * @brief Destroys the pointed object and deallocates its memory.
- * @param ptr A valid pointer to an object of the given type.
- */
- constexpr void operator()(pointer ptr) noexcept(std::is_nothrow_destructible_v<typename allocator_type::value_type>) {
- using alloc_traits = std::allocator_traits<Allocator>;
- alloc_traits::destroy(*this, to_address(ptr));
- alloc_traits::deallocate(*this, ptr, 1u);
- }
- };
- /**
- * @brief Allows `std::unique_ptr` to use allocators (waiting for C++20).
- * @tparam Type Type of object to allocate for and to construct.
- * @tparam Allocator Type of allocator used to manage memory and elements.
- * @tparam Args Types of arguments to use to construct the object.
- * @param allocator The allocator to use.
- * @param args Parameters to use to construct the object.
- * @return A properly initialized unique pointer with a custom deleter.
- */
- template<typename Type, typename Allocator, typename... Args>
- ENTT_CONSTEXPR auto allocate_unique(Allocator &allocator, Args &&...args) {
- static_assert(!std::is_array_v<Type>, "Array types are not supported");
- using alloc_traits = typename std::allocator_traits<Allocator>::template rebind_traits<Type>;
- using allocator_type = typename alloc_traits::allocator_type;
- allocator_type alloc{allocator};
- auto ptr = alloc_traits::allocate(alloc, 1u);
- ENTT_TRY {
- alloc_traits::construct(alloc, to_address(ptr), std::forward<Args>(args)...);
- }
- ENTT_CATCH {
- alloc_traits::deallocate(alloc, ptr, 1u);
- ENTT_THROW;
- }
- return std::unique_ptr<Type, allocation_deleter<allocator_type>>{ptr, alloc};
- }
- /*! @cond TURN_OFF_DOXYGEN */
- namespace internal {
- template<typename Type>
- struct uses_allocator_construction {
- template<typename Allocator, typename... Params>
- static constexpr auto args([[maybe_unused]] const Allocator &allocator, Params &&...params) noexcept {
- if constexpr(!std::uses_allocator_v<Type, Allocator> && std::is_constructible_v<Type, Params...>) {
- return std::forward_as_tuple(std::forward<Params>(params)...);
- } else {
- static_assert(std::uses_allocator_v<Type, Allocator>, "Ill-formed request");
- if constexpr(std::is_constructible_v<Type, std::allocator_arg_t, const Allocator &, Params...>) {
- return std::tuple<std::allocator_arg_t, const Allocator &, Params &&...>{std::allocator_arg, allocator, std::forward<Params>(params)...};
- } else {
- static_assert(std::is_constructible_v<Type, Params..., const Allocator &>, "Ill-formed request");
- return std::forward_as_tuple(std::forward<Params>(params)..., allocator);
- }
- }
- }
- };
- template<typename Type, typename Other>
- struct uses_allocator_construction<std::pair<Type, Other>> {
- using type = std::pair<Type, Other>;
- template<typename Allocator, typename First, typename Second>
- static constexpr auto args(const Allocator &allocator, std::piecewise_construct_t, First &&first, Second &&second) noexcept {
- return std::make_tuple(
- std::piecewise_construct,
- std::apply([&allocator](auto &&...curr) { return uses_allocator_construction<Type>::args(allocator, std::forward<decltype(curr)>(curr)...); }, std::forward<First>(first)),
- std::apply([&allocator](auto &&...curr) { return uses_allocator_construction<Other>::args(allocator, std::forward<decltype(curr)>(curr)...); }, std::forward<Second>(second)));
- }
- template<typename Allocator>
- static constexpr auto args(const Allocator &allocator) noexcept {
- return uses_allocator_construction<type>::args(allocator, std::piecewise_construct, std::tuple<>{}, std::tuple<>{});
- }
- template<typename Allocator, typename First, typename Second>
- static constexpr auto args(const Allocator &allocator, First &&first, Second &&second) noexcept {
- return uses_allocator_construction<type>::args(allocator, std::piecewise_construct, std::forward_as_tuple(std::forward<First>(first)), std::forward_as_tuple(std::forward<Second>(second)));
- }
- template<typename Allocator, typename First, typename Second>
- static constexpr auto args(const Allocator &allocator, const std::pair<First, Second> &value) noexcept {
- return uses_allocator_construction<type>::args(allocator, std::piecewise_construct, std::forward_as_tuple(value.first), std::forward_as_tuple(value.second));
- }
- template<typename Allocator, typename First, typename Second>
- static constexpr auto args(const Allocator &allocator, std::pair<First, Second> &&value) noexcept {
- return uses_allocator_construction<type>::args(allocator, std::piecewise_construct, std::forward_as_tuple(std::move(value.first)), std::forward_as_tuple(std::move(value.second)));
- }
- };
- } // namespace internal
- /*! @endcond */
- /**
- * @brief Uses-allocator construction utility (waiting for C++20).
- *
- * Primarily intended for internal use. Prepares the argument list needed to
- * create an object of a given type by means of uses-allocator construction.
- *
- * @tparam Type Type to return arguments for.
- * @tparam Allocator Type of allocator used to manage memory and elements.
- * @tparam Args Types of arguments to use to construct the object.
- * @param allocator The allocator to use.
- * @param args Parameters to use to construct the object.
- * @return The arguments needed to create an object of the given type.
- */
- template<typename Type, typename Allocator, typename... Args>
- constexpr auto uses_allocator_construction_args(const Allocator &allocator, Args &&...args) noexcept {
- return internal::uses_allocator_construction<Type>::args(allocator, std::forward<Args>(args)...);
- }
- /**
- * @brief Uses-allocator construction utility (waiting for C++20).
- *
- * Primarily intended for internal use. Creates an object of a given type by
- * means of uses-allocator construction.
- *
- * @tparam Type Type of object to create.
- * @tparam Allocator Type of allocator used to manage memory and elements.
- * @tparam Args Types of arguments to use to construct the object.
- * @param allocator The allocator to use.
- * @param args Parameters to use to construct the object.
- * @return A newly created object of the given type.
- */
- template<typename Type, typename Allocator, typename... Args>
- constexpr Type make_obj_using_allocator(const Allocator &allocator, Args &&...args) {
- return std::make_from_tuple<Type>(internal::uses_allocator_construction<Type>::args(allocator, std::forward<Args>(args)...));
- }
- /**
- * @brief Uses-allocator construction utility (waiting for C++20).
- *
- * Primarily intended for internal use. Creates an object of a given type by
- * means of uses-allocator construction at an uninitialized memory location.
- *
- * @tparam Type Type of object to create.
- * @tparam Allocator Type of allocator used to manage memory and elements.
- * @tparam Args Types of arguments to use to construct the object.
- * @param value Memory location in which to place the object.
- * @param allocator The allocator to use.
- * @param args Parameters to use to construct the object.
- * @return A pointer to the newly created object of the given type.
- */
- template<typename Type, typename Allocator, typename... Args>
- constexpr Type *uninitialized_construct_using_allocator(Type *value, const Allocator &allocator, Args &&...args) {
- return std::apply([value](auto &&...curr) { return ::new(value) Type(std::forward<decltype(curr)>(curr)...); }, internal::uses_allocator_construction<Type>::args(allocator, std::forward<Args>(args)...));
- }
- } // namespace entt
- #endif
- // #include "../core/type_traits.hpp"
- #ifndef ENTT_CORE_TYPE_TRAITS_HPP
- #define ENTT_CORE_TYPE_TRAITS_HPP
- #include <cstddef>
- #include <iterator>
- #include <tuple>
- #include <type_traits>
- #include <utility>
- // #include "../config/config.h"
- // #include "fwd.hpp"
- namespace entt {
- /**
- * @brief Utility class to disambiguate overloaded functions.
- * @tparam N Number of choices available.
- */
- template<std::size_t N>
- struct choice_t
- // unfortunately, doxygen cannot parse such a construct
- : /*! @cond TURN_OFF_DOXYGEN */ choice_t<N - 1> /*! @endcond */
- {};
- /*! @copybrief choice_t */
- template<>
- struct choice_t<0> {};
- /**
- * @brief Variable template for the choice trick.
- * @tparam N Number of choices available.
- */
- template<std::size_t N>
- inline constexpr choice_t<N> choice{};
- /**
- * @brief Identity type trait.
- *
- * Useful to establish non-deduced contexts in template argument deduction
- * (waiting for C++20) or to provide types through function arguments.
- *
- * @tparam Type A type.
- */
- template<typename Type>
- struct type_identity {
- /*! @brief Identity type. */
- using type = Type;
- };
- /**
- * @brief Helper type.
- * @tparam Type A type.
- */
- template<typename Type>
- using type_identity_t = typename type_identity<Type>::type;
- /**
- * @brief A type-only `sizeof` wrapper that returns 0 where `sizeof` complains.
- * @tparam Type The type of which to return the size.
- */
- template<typename Type, typename = void>
- struct size_of: std::integral_constant<std::size_t, 0u> {};
- /*! @copydoc size_of */
- template<typename Type>
- struct size_of<Type, std::void_t<decltype(sizeof(Type))>>
- // NOLINTNEXTLINE(bugprone-sizeof-expression)
- : std::integral_constant<std::size_t, sizeof(Type)> {};
- /**
- * @brief Helper variable template.
- * @tparam Type The type of which to return the size.
- */
- template<typename Type>
- inline constexpr std::size_t size_of_v = size_of<Type>::value;
- /**
- * @brief Using declaration to be used to _repeat_ the same type a number of
- * times equal to the size of a given parameter pack.
- * @tparam Type A type to repeat.
- */
- template<typename Type, typename>
- using unpack_as_type = Type;
- /**
- * @brief Helper variable template to be used to _repeat_ the same value a
- * number of times equal to the size of a given parameter pack.
- * @tparam Value A value to repeat.
- */
- template<auto Value, typename>
- inline constexpr auto unpack_as_value = Value;
- /**
- * @brief Wraps a static constant.
- * @tparam Value A static constant.
- */
- template<auto Value>
- using integral_constant = std::integral_constant<decltype(Value), Value>;
- /**
- * @brief Alias template to facilitate the creation of named values.
- * @tparam Value A constant value at least convertible to `id_type`.
- */
- template<id_type Value>
- using tag = integral_constant<Value>;
- /**
- * @brief A class to use to push around lists of types, nothing more.
- * @tparam Type Types provided by the type list.
- */
- template<typename... Type>
- struct type_list {
- /*! @brief Type list type. */
- using type = type_list;
- /*! @brief Compile-time number of elements in the type list. */
- static constexpr auto size = sizeof...(Type);
- };
- /*! @brief Primary template isn't defined on purpose. */
- template<std::size_t, typename>
- struct type_list_element;
- /**
- * @brief Provides compile-time indexed access to the types of a type list.
- * @tparam Index Index of the type to return.
- * @tparam First First type provided by the type list.
- * @tparam Other Other types provided by the type list.
- */
- template<std::size_t Index, typename First, typename... Other>
- struct type_list_element<Index, type_list<First, Other...>>
- : type_list_element<Index - 1u, type_list<Other...>> {};
- /**
- * @brief Provides compile-time indexed access to the types of a type list.
- * @tparam First First type provided by the type list.
- * @tparam Other Other types provided by the type list.
- */
- template<typename First, typename... Other>
- struct type_list_element<0u, type_list<First, Other...>> {
- /*! @brief Searched type. */
- using type = First;
- };
- /**
- * @brief Helper type.
- * @tparam Index Index of the type to return.
- * @tparam List Type list to search into.
- */
- template<std::size_t Index, typename List>
- using type_list_element_t = typename type_list_element<Index, List>::type;
- /*! @brief Primary template isn't defined on purpose. */
- template<typename, typename>
- struct type_list_index;
- /**
- * @brief Provides compile-time type access to the types of a type list.
- * @tparam Type Type to look for and for which to return the index.
- * @tparam First First type provided by the type list.
- * @tparam Other Other types provided by the type list.
- */
- template<typename Type, typename First, typename... Other>
- struct type_list_index<Type, type_list<First, Other...>> {
- /*! @brief Unsigned integer type. */
- using value_type = std::size_t;
- /*! @brief Compile-time position of the given type in the sublist. */
- static constexpr value_type value = 1u + type_list_index<Type, type_list<Other...>>::value;
- };
- /**
- * @brief Provides compile-time type access to the types of a type list.
- * @tparam Type Type to look for and for which to return the index.
- * @tparam Other Other types provided by the type list.
- */
- template<typename Type, typename... Other>
- struct type_list_index<Type, type_list<Type, Other...>> {
- static_assert(type_list_index<Type, type_list<Other...>>::value == sizeof...(Other), "Non-unique type");
- /*! @brief Unsigned integer type. */
- using value_type = std::size_t;
- /*! @brief Compile-time position of the given type in the sublist. */
- static constexpr value_type value = 0u;
- };
- /**
- * @brief Provides compile-time type access to the types of a type list.
- * @tparam Type Type to look for and for which to return the index.
- */
- template<typename Type>
- struct type_list_index<Type, type_list<>> {
- /*! @brief Unsigned integer type. */
- using value_type = std::size_t;
- /*! @brief Compile-time position of the given type in the sublist. */
- static constexpr value_type value = 0u;
- };
- /**
- * @brief Helper variable template.
- * @tparam List Type list.
- * @tparam Type Type to look for and for which to return the index.
- */
- template<typename Type, typename List>
- inline constexpr std::size_t type_list_index_v = type_list_index<Type, List>::value;
- /**
- * @brief Concatenates multiple type lists.
- * @tparam Type Types provided by the first type list.
- * @tparam Other Types provided by the second type list.
- * @return A type list composed by the types of both the type lists.
- */
- template<typename... Type, typename... Other>
- constexpr type_list<Type..., Other...> operator+(type_list<Type...>, type_list<Other...>) {
- return {};
- }
- /*! @brief Primary template isn't defined on purpose. */
- template<typename...>
- struct type_list_cat;
- /*! @brief Concatenates multiple type lists. */
- template<>
- struct type_list_cat<> {
- /*! @brief A type list composed by the types of all the type lists. */
- using type = type_list<>;
- };
- /**
- * @brief Concatenates multiple type lists.
- * @tparam Type Types provided by the first type list.
- * @tparam Other Types provided by the second type list.
- * @tparam List Other type lists, if any.
- */
- template<typename... Type, typename... Other, typename... List>
- struct type_list_cat<type_list<Type...>, type_list<Other...>, List...> {
- /*! @brief A type list composed by the types of all the type lists. */
- using type = typename type_list_cat<type_list<Type..., Other...>, List...>::type;
- };
- /**
- * @brief Concatenates multiple type lists.
- * @tparam Type Types provided by the type list.
- */
- template<typename... Type>
- struct type_list_cat<type_list<Type...>> {
- /*! @brief A type list composed by the types of all the type lists. */
- using type = type_list<Type...>;
- };
- /**
- * @brief Helper type.
- * @tparam List Type lists to concatenate.
- */
- template<typename... List>
- using type_list_cat_t = typename type_list_cat<List...>::type;
- /*! @cond TURN_OFF_DOXYGEN */
- namespace internal {
- template<typename...>
- struct type_list_unique;
- template<typename First, typename... Other, typename... Type>
- struct type_list_unique<type_list<First, Other...>, Type...>
- : std::conditional_t<(std::is_same_v<First, Type> || ...), type_list_unique<type_list<Other...>, Type...>, type_list_unique<type_list<Other...>, Type..., First>> {};
- template<typename... Type>
- struct type_list_unique<type_list<>, Type...> {
- using type = type_list<Type...>;
- };
- } // namespace internal
- /*! @endcond */
- /**
- * @brief Removes duplicates types from a type list.
- * @tparam List Type list.
- */
- template<typename List>
- struct type_list_unique {
- /*! @brief A type list without duplicate types. */
- using type = typename internal::type_list_unique<List>::type;
- };
- /**
- * @brief Helper type.
- * @tparam List Type list.
- */
- template<typename List>
- using type_list_unique_t = typename type_list_unique<List>::type;
- /**
- * @brief Provides the member constant `value` to true if a type list contains a
- * given type, false otherwise.
- * @tparam List Type list.
- * @tparam Type Type to look for.
- */
- template<typename List, typename Type>
- struct type_list_contains;
- /**
- * @copybrief type_list_contains
- * @tparam Type Types provided by the type list.
- * @tparam Other Type to look for.
- */
- template<typename... Type, typename Other>
- struct type_list_contains<type_list<Type...>, Other>
- : std::bool_constant<(std::is_same_v<Type, Other> || ...)> {};
- /**
- * @brief Helper variable template.
- * @tparam List Type list.
- * @tparam Type Type to look for.
- */
- template<typename List, typename Type>
- inline constexpr bool type_list_contains_v = type_list_contains<List, Type>::value;
- /*! @brief Primary template isn't defined on purpose. */
- template<typename...>
- struct type_list_diff;
- /**
- * @brief Computes the difference between two type lists.
- * @tparam Type Types provided by the first type list.
- * @tparam Other Types provided by the second type list.
- */
- template<typename... Type, typename... Other>
- struct type_list_diff<type_list<Type...>, type_list<Other...>> {
- /*! @brief A type list that is the difference between the two type lists. */
- using type = type_list_cat_t<std::conditional_t<type_list_contains_v<type_list<Other...>, Type>, type_list<>, type_list<Type>>...>;
- };
- /**
- * @brief Helper type.
- * @tparam List Type lists between which to compute the difference.
- */
- template<typename... List>
- using type_list_diff_t = typename type_list_diff<List...>::type;
- /*! @brief Primary template isn't defined on purpose. */
- template<typename, template<typename...> class>
- struct type_list_transform;
- /**
- * @brief Applies a given _function_ to a type list and generate a new list.
- * @tparam Type Types provided by the type list.
- * @tparam Op Unary operation as template class with a type member named `type`.
- */
- template<typename... Type, template<typename...> class Op>
- struct type_list_transform<type_list<Type...>, Op> {
- /*! @brief Resulting type list after applying the transform function. */
- // NOLINTNEXTLINE(modernize-type-traits)
- using type = type_list<typename Op<Type>::type...>;
- };
- /**
- * @brief Helper type.
- * @tparam List Type list.
- * @tparam Op Unary operation as template class with a type member named `type`.
- */
- template<typename List, template<typename...> class Op>
- using type_list_transform_t = typename type_list_transform<List, Op>::type;
- /**
- * @brief A class to use to push around lists of constant values, nothing more.
- * @tparam Value Values provided by the value list.
- */
- template<auto... Value>
- struct value_list {
- /*! @brief Value list type. */
- using type = value_list;
- /*! @brief Compile-time number of elements in the value list. */
- static constexpr auto size = sizeof...(Value);
- };
- /*! @brief Primary template isn't defined on purpose. */
- template<std::size_t, typename>
- struct value_list_element;
- /**
- * @brief Provides compile-time indexed access to the values of a value list.
- * @tparam Index Index of the value to return.
- * @tparam Value First value provided by the value list.
- * @tparam Other Other values provided by the value list.
- */
- template<std::size_t Index, auto Value, auto... Other>
- struct value_list_element<Index, value_list<Value, Other...>>
- : value_list_element<Index - 1u, value_list<Other...>> {};
- /**
- * @brief Provides compile-time indexed access to the types of a type list.
- * @tparam Value First value provided by the value list.
- * @tparam Other Other values provided by the value list.
- */
- template<auto Value, auto... Other>
- struct value_list_element<0u, value_list<Value, Other...>> {
- /*! @brief Searched type. */
- using type = decltype(Value);
- /*! @brief Searched value. */
- static constexpr auto value = Value;
- };
- /**
- * @brief Helper type.
- * @tparam Index Index of the type to return.
- * @tparam List Value list to search into.
- */
- template<std::size_t Index, typename List>
- using value_list_element_t = typename value_list_element<Index, List>::type;
- /**
- * @brief Helper type.
- * @tparam Index Index of the value to return.
- * @tparam List Value list to search into.
- */
- template<std::size_t Index, typename List>
- inline constexpr auto value_list_element_v = value_list_element<Index, List>::value;
- /*! @brief Primary template isn't defined on purpose. */
- template<auto, typename>
- struct value_list_index;
- /**
- * @brief Provides compile-time type access to the values of a value list.
- * @tparam Value Value to look for and for which to return the index.
- * @tparam First First value provided by the value list.
- * @tparam Other Other values provided by the value list.
- */
- template<auto Value, auto First, auto... Other>
- struct value_list_index<Value, value_list<First, Other...>> {
- /*! @brief Unsigned integer type. */
- using value_type = std::size_t;
- /*! @brief Compile-time position of the given value in the sublist. */
- static constexpr value_type value = 1u + value_list_index<Value, value_list<Other...>>::value;
- };
- /**
- * @brief Provides compile-time type access to the values of a value list.
- * @tparam Value Value to look for and for which to return the index.
- * @tparam Other Other values provided by the value list.
- */
- template<auto Value, auto... Other>
- struct value_list_index<Value, value_list<Value, Other...>> {
- static_assert(value_list_index<Value, value_list<Other...>>::value == sizeof...(Other), "Non-unique type");
- /*! @brief Unsigned integer type. */
- using value_type = std::size_t;
- /*! @brief Compile-time position of the given value in the sublist. */
- static constexpr value_type value = 0u;
- };
- /**
- * @brief Provides compile-time type access to the values of a value list.
- * @tparam Value Value to look for and for which to return the index.
- */
- template<auto Value>
- struct value_list_index<Value, value_list<>> {
- /*! @brief Unsigned integer type. */
- using value_type = std::size_t;
- /*! @brief Compile-time position of the given type in the sublist. */
- static constexpr value_type value = 0u;
- };
- /**
- * @brief Helper variable template.
- * @tparam List Value list.
- * @tparam Value Value to look for and for which to return the index.
- */
- template<auto Value, typename List>
- inline constexpr std::size_t value_list_index_v = value_list_index<Value, List>::value;
- /**
- * @brief Concatenates multiple value lists.
- * @tparam Value Values provided by the first value list.
- * @tparam Other Values provided by the second value list.
- * @return A value list composed by the values of both the value lists.
- */
- template<auto... Value, auto... Other>
- constexpr value_list<Value..., Other...> operator+(value_list<Value...>, value_list<Other...>) {
- return {};
- }
- /*! @brief Primary template isn't defined on purpose. */
- template<typename...>
- struct value_list_cat;
- /*! @brief Concatenates multiple value lists. */
- template<>
- struct value_list_cat<> {
- /*! @brief A value list composed by the values of all the value lists. */
- using type = value_list<>;
- };
- /**
- * @brief Concatenates multiple value lists.
- * @tparam Value Values provided by the first value list.
- * @tparam Other Values provided by the second value list.
- * @tparam List Other value lists, if any.
- */
- template<auto... Value, auto... Other, typename... List>
- struct value_list_cat<value_list<Value...>, value_list<Other...>, List...> {
- /*! @brief A value list composed by the values of all the value lists. */
- using type = typename value_list_cat<value_list<Value..., Other...>, List...>::type;
- };
- /**
- * @brief Concatenates multiple value lists.
- * @tparam Value Values provided by the value list.
- */
- template<auto... Value>
- struct value_list_cat<value_list<Value...>> {
- /*! @brief A value list composed by the values of all the value lists. */
- using type = value_list<Value...>;
- };
- /**
- * @brief Helper type.
- * @tparam List Value lists to concatenate.
- */
- template<typename... List>
- using value_list_cat_t = typename value_list_cat<List...>::type;
- /*! @brief Primary template isn't defined on purpose. */
- template<typename>
- struct value_list_unique;
- /**
- * @brief Removes duplicates values from a value list.
- * @tparam Value One of the values provided by the given value list.
- * @tparam Other The other values provided by the given value list.
- */
- template<auto Value, auto... Other>
- struct value_list_unique<value_list<Value, Other...>> {
- /*! @brief A value list without duplicate types. */
- using type = std::conditional_t<
- ((Value == Other) || ...),
- typename value_list_unique<value_list<Other...>>::type,
- value_list_cat_t<value_list<Value>, typename value_list_unique<value_list<Other...>>::type>>;
- };
- /*! @brief Removes duplicates values from a value list. */
- template<>
- struct value_list_unique<value_list<>> {
- /*! @brief A value list without duplicate types. */
- using type = value_list<>;
- };
- /**
- * @brief Helper type.
- * @tparam Type A value list.
- */
- template<typename Type>
- using value_list_unique_t = typename value_list_unique<Type>::type;
- /**
- * @brief Provides the member constant `value` to true if a value list contains
- * a given value, false otherwise.
- * @tparam List Value list.
- * @tparam Value Value to look for.
- */
- template<typename List, auto Value>
- struct value_list_contains;
- /**
- * @copybrief value_list_contains
- * @tparam Value Values provided by the value list.
- * @tparam Other Value to look for.
- */
- template<auto... Value, auto Other>
- struct value_list_contains<value_list<Value...>, Other>
- : std::bool_constant<((Value == Other) || ...)> {};
- /**
- * @brief Helper variable template.
- * @tparam List Value list.
- * @tparam Value Value to look for.
- */
- template<typename List, auto Value>
- inline constexpr bool value_list_contains_v = value_list_contains<List, Value>::value;
- /*! @brief Primary template isn't defined on purpose. */
- template<typename...>
- struct value_list_diff;
- /**
- * @brief Computes the difference between two value lists.
- * @tparam Value Values provided by the first value list.
- * @tparam Other Values provided by the second value list.
- */
- template<auto... Value, auto... Other>
- struct value_list_diff<value_list<Value...>, value_list<Other...>> {
- /*! @brief A value list that is the difference between the two value lists. */
- using type = value_list_cat_t<std::conditional_t<value_list_contains_v<value_list<Other...>, Value>, value_list<>, value_list<Value>>...>;
- };
- /**
- * @brief Helper type.
- * @tparam List Value lists between which to compute the difference.
- */
- template<typename... List>
- using value_list_diff_t = typename value_list_diff<List...>::type;
- /*! @brief Same as std::is_invocable, but with tuples. */
- template<typename, typename>
- struct is_applicable: std::false_type {};
- /**
- * @copybrief is_applicable
- * @tparam Func A valid function type.
- * @tparam Tuple Tuple-like type.
- * @tparam Args The list of arguments to use to probe the function type.
- */
- template<typename Func, template<typename...> class Tuple, typename... Args>
- struct is_applicable<Func, Tuple<Args...>>: std::is_invocable<Func, Args...> {};
- /**
- * @copybrief is_applicable
- * @tparam Func A valid function type.
- * @tparam Tuple Tuple-like type.
- * @tparam Args The list of arguments to use to probe the function type.
- */
- template<typename Func, template<typename...> class Tuple, typename... Args>
- struct is_applicable<Func, const Tuple<Args...>>: std::is_invocable<Func, Args...> {};
- /**
- * @brief Helper variable template.
- * @tparam Func A valid function type.
- * @tparam Args The list of arguments to use to probe the function type.
- */
- template<typename Func, typename Args>
- inline constexpr bool is_applicable_v = is_applicable<Func, Args>::value;
- /*! @brief Same as std::is_invocable_r, but with tuples for arguments. */
- template<typename, typename, typename>
- struct is_applicable_r: std::false_type {};
- /**
- * @copybrief is_applicable_r
- * @tparam Ret The type to which the return type of the function should be
- * convertible.
- * @tparam Func A valid function type.
- * @tparam Args The list of arguments to use to probe the function type.
- */
- template<typename Ret, typename Func, typename... Args>
- struct is_applicable_r<Ret, Func, std::tuple<Args...>>: std::is_invocable_r<Ret, Func, Args...> {};
- /**
- * @brief Helper variable template.
- * @tparam Ret The type to which the return type of the function should be
- * convertible.
- * @tparam Func A valid function type.
- * @tparam Args The list of arguments to use to probe the function type.
- */
- template<typename Ret, typename Func, typename Args>
- inline constexpr bool is_applicable_r_v = is_applicable_r<Ret, Func, Args>::value;
- /**
- * @brief Provides the member constant `value` to true if a given type is
- * complete, false otherwise.
- * @tparam Type The type to test.
- */
- template<typename Type, typename = void>
- struct is_complete: std::false_type {};
- /*! @copydoc is_complete */
- template<typename Type>
- struct is_complete<Type, std::void_t<decltype(sizeof(Type))>>: std::true_type {};
- /**
- * @brief Helper variable template.
- * @tparam Type The type to test.
- */
- template<typename Type>
- inline constexpr bool is_complete_v = is_complete<Type>::value;
- /**
- * @brief Provides the member constant `value` to true if a given type is an
- * iterator, false otherwise.
- * @tparam Type The type to test.
- */
- template<typename Type, typename = void>
- struct is_iterator: std::false_type {};
- /*! @cond TURN_OFF_DOXYGEN */
- namespace internal {
- template<typename, typename = void>
- struct has_iterator_category: std::false_type {};
- template<typename Type>
- struct has_iterator_category<Type, std::void_t<typename std::iterator_traits<Type>::iterator_category>>: std::true_type {};
- } // namespace internal
- /*! @endcond */
- /*! @copydoc is_iterator */
- template<typename Type>
- struct is_iterator<Type, std::enable_if_t<!std::is_void_v<std::remove_const_t<std::remove_pointer_t<Type>>>>>
- : internal::has_iterator_category<Type> {};
- /**
- * @brief Helper variable template.
- * @tparam Type The type to test.
- */
- template<typename Type>
- inline constexpr bool is_iterator_v = is_iterator<Type>::value;
- /**
- * @brief Provides the member constant `value` to true if a given type is both
- * an empty and non-final class, false otherwise.
- * @tparam Type The type to test
- */
- template<typename Type>
- struct is_ebco_eligible
- : std::bool_constant<std::is_empty_v<Type> && !std::is_final_v<Type>> {};
- /**
- * @brief Helper variable template.
- * @tparam Type The type to test.
- */
- template<typename Type>
- inline constexpr bool is_ebco_eligible_v = is_ebco_eligible<Type>::value;
- /**
- * @brief Provides the member constant `value` to true if `Type::is_transparent`
- * is valid and denotes a type, false otherwise.
- * @tparam Type The type to test.
- */
- template<typename Type, typename = void>
- struct is_transparent: std::false_type {};
- /*! @copydoc is_transparent */
- template<typename Type>
- struct is_transparent<Type, std::void_t<typename Type::is_transparent>>: std::true_type {};
- /**
- * @brief Helper variable template.
- * @tparam Type The type to test.
- */
- template<typename Type>
- inline constexpr bool is_transparent_v = is_transparent<Type>::value;
- /*! @cond TURN_OFF_DOXYGEN */
- namespace internal {
- template<typename, typename = void>
- struct has_tuple_size_value: std::false_type {};
- template<typename Type>
- struct has_tuple_size_value<Type, std::void_t<decltype(std::tuple_size<const Type>::value)>>: std::true_type {};
- template<typename, typename = void>
- struct has_value_type: std::false_type {};
- template<typename Type>
- struct has_value_type<Type, std::void_t<typename Type::value_type>>: std::true_type {};
- template<typename>
- [[nodiscard]] constexpr bool dispatch_is_equality_comparable();
- template<typename Type, std::size_t... Index>
- [[nodiscard]] constexpr bool unpack_maybe_equality_comparable(std::index_sequence<Index...>) {
- return (dispatch_is_equality_comparable<std::tuple_element_t<Index, Type>>() && ...);
- }
- template<typename>
- [[nodiscard]] constexpr bool maybe_equality_comparable(char) {
- return false;
- }
- template<typename Type>
- [[nodiscard]] constexpr auto maybe_equality_comparable(int) -> decltype(std::declval<Type>() == std::declval<Type>()) {
- return true;
- }
- template<typename Type>
- [[nodiscard]] constexpr bool dispatch_is_equality_comparable() {
- // NOLINTBEGIN(modernize-use-transparent-functors)
- if constexpr(std::is_array_v<Type>) {
- return false;
- } else if constexpr(is_complete_v<std::tuple_size<std::remove_const_t<Type>>>) {
- if constexpr(has_tuple_size_value<Type>::value) {
- return maybe_equality_comparable<Type>(0) && unpack_maybe_equality_comparable<Type>(std::make_index_sequence<std::tuple_size<Type>::value>{});
- } else {
- return maybe_equality_comparable<Type>(0);
- }
- } else if constexpr(has_value_type<Type>::value) {
- if constexpr(is_iterator_v<Type> || std::is_same_v<typename Type::value_type, Type> || dispatch_is_equality_comparable<typename Type::value_type>()) {
- return maybe_equality_comparable<Type>(0);
- } else {
- return false;
- }
- } else {
- return maybe_equality_comparable<Type>(0);
- }
- // NOLINTEND(modernize-use-transparent-functors)
- }
- } // namespace internal
- /*! @endcond */
- /**
- * @brief Provides the member constant `value` to true if a given type is
- * equality comparable, false otherwise.
- * @tparam Type The type to test.
- */
- template<typename Type>
- struct is_equality_comparable: std::bool_constant<internal::dispatch_is_equality_comparable<Type>()> {};
- /*! @copydoc is_equality_comparable */
- template<typename Type>
- struct is_equality_comparable<const Type>: is_equality_comparable<Type> {};
- /**
- * @brief Helper variable template.
- * @tparam Type The type to test.
- */
- template<typename Type>
- inline constexpr bool is_equality_comparable_v = is_equality_comparable<Type>::value;
- /**
- * @brief Transcribes the constness of a type to another type.
- * @tparam To The type to which to transcribe the constness.
- * @tparam From The type from which to transcribe the constness.
- */
- template<typename To, typename From>
- struct constness_as {
- /*! @brief The type resulting from the transcription of the constness. */
- using type = std::remove_const_t<To>;
- };
- /*! @copydoc constness_as */
- template<typename To, typename From>
- struct constness_as<To, const From> {
- /*! @brief The type resulting from the transcription of the constness. */
- using type = const To;
- };
- /**
- * @brief Alias template to facilitate the transcription of the constness.
- * @tparam To The type to which to transcribe the constness.
- * @tparam From The type from which to transcribe the constness.
- */
- template<typename To, typename From>
- using constness_as_t = typename constness_as<To, From>::type;
- /**
- * @brief Extracts the class of a non-static member object or function.
- * @tparam Member A pointer to a non-static member object or function.
- */
- template<typename Member>
- class member_class {
- static_assert(std::is_member_pointer_v<Member>, "Invalid pointer type to non-static member object or function");
- template<typename Class, typename Ret, typename... Args>
- static Class *clazz(Ret (Class::*)(Args...));
- template<typename Class, typename Ret, typename... Args>
- static Class *clazz(Ret (Class::*)(Args...) const);
- template<typename Class, typename Type>
- static Class *clazz(Type Class::*);
- public:
- /*! @brief The class of the given non-static member object or function. */
- using type = std::remove_pointer_t<decltype(clazz(std::declval<Member>()))>;
- };
- /**
- * @brief Helper type.
- * @tparam Member A pointer to a non-static member object or function.
- */
- template<typename Member>
- using member_class_t = typename member_class<Member>::type;
- /**
- * @brief Extracts the n-th argument of a _callable_ type.
- * @tparam Index The index of the argument to extract.
- * @tparam Candidate A valid _callable_ type.
- */
- template<std::size_t Index, typename Candidate>
- class nth_argument {
- template<typename Ret, typename... Args>
- static constexpr type_list<Args...> pick_up(Ret (*)(Args...));
- template<typename Ret, typename Class, typename... Args>
- static constexpr type_list<Args...> pick_up(Ret (Class ::*)(Args...));
- template<typename Ret, typename Class, typename... Args>
- static constexpr type_list<Args...> pick_up(Ret (Class ::*)(Args...) const);
- template<typename Type, typename Class>
- static constexpr type_list<Type> pick_up(Type Class ::*);
- template<typename Type>
- static constexpr decltype(pick_up(&Type::operator())) pick_up(Type &&);
- public:
- /*! @brief N-th argument of the _callable_ type. */
- using type = type_list_element_t<Index, decltype(pick_up(std::declval<Candidate>()))>;
- };
- /**
- * @brief Helper type.
- * @tparam Index The index of the argument to extract.
- * @tparam Candidate A valid function, member function or data member type.
- */
- template<std::size_t Index, typename Candidate>
- using nth_argument_t = typename nth_argument<Index, Candidate>::type;
- } // namespace entt
- template<typename... Type>
- struct std::tuple_size<entt::type_list<Type...>>: std::integral_constant<std::size_t, entt::type_list<Type...>::size> {};
- template<std::size_t Index, typename... Type>
- struct std::tuple_element<Index, entt::type_list<Type...>>: entt::type_list_element<Index, entt::type_list<Type...>> {};
- template<auto... Value>
- struct std::tuple_size<entt::value_list<Value...>>: std::integral_constant<std::size_t, entt::value_list<Value...>::size> {};
- template<std::size_t Index, auto... Value>
- struct std::tuple_element<Index, entt::value_list<Value...>>: entt::value_list_element<Index, entt::value_list<Value...>> {};
- #endif
- // #include "fwd.hpp"
- #ifndef ENTT_CONTAINER_FWD_HPP
- #define ENTT_CONTAINER_FWD_HPP
- #include <functional>
- #include <memory>
- #include <utility>
- #include <vector>
- namespace entt {
- template<
- typename Key,
- typename Type,
- typename = std::hash<Key>,
- typename = std::equal_to<>,
- typename = std::allocator<std::pair<const Key, Type>>>
- class dense_map;
- template<
- typename Type,
- typename = std::hash<Type>,
- typename = std::equal_to<>,
- typename = std::allocator<Type>>
- class dense_set;
- template<typename...>
- class basic_table;
- /**
- * @brief Alias declaration for the most common use case.
- * @tparam Type Element types.
- */
- template<typename... Type>
- using table = basic_table<std::vector<Type>...>;
- } // namespace entt
- #endif
- namespace entt {
- /*! @cond TURN_OFF_DOXYGEN */
- namespace internal {
- static constexpr std::size_t dense_map_placeholder_position = (std::numeric_limits<std::size_t>::max)();
- template<typename Key, typename Type>
- struct dense_map_node final {
- using value_type = std::pair<Key, Type>;
- template<typename... Args>
- dense_map_node(const std::size_t pos, Args &&...args)
- : next{pos},
- element{std::forward<Args>(args)...} {}
- template<typename Allocator, typename... Args>
- dense_map_node(std::allocator_arg_t, const Allocator &allocator, const std::size_t pos, Args &&...args)
- : next{pos},
- element{entt::make_obj_using_allocator<value_type>(allocator, std::forward<Args>(args)...)} {}
- template<typename Allocator>
- dense_map_node(std::allocator_arg_t, const Allocator &allocator, const dense_map_node &other)
- : next{other.next},
- element{entt::make_obj_using_allocator<value_type>(allocator, other.element)} {}
- template<typename Allocator>
- dense_map_node(std::allocator_arg_t, const Allocator &allocator, dense_map_node &&other)
- : next{other.next},
- element{entt::make_obj_using_allocator<value_type>(allocator, std::move(other.element))} {}
- std::size_t next;
- value_type element;
- };
- template<typename It>
- class dense_map_iterator final {
- template<typename>
- friend class dense_map_iterator;
- using first_type = decltype(std::as_const(std::declval<It>()->element.first));
- using second_type = decltype((std::declval<It>()->element.second));
- public:
- using value_type = std::pair<first_type, second_type>;
- using pointer = input_iterator_pointer<value_type>;
- using reference = value_type;
- using difference_type = std::ptrdiff_t;
- using iterator_category = std::input_iterator_tag;
- using iterator_concept = std::random_access_iterator_tag;
- constexpr dense_map_iterator() noexcept
- : it{} {}
- constexpr dense_map_iterator(const It iter) noexcept
- : it{iter} {}
- template<typename Other, typename = std::enable_if_t<!std::is_same_v<It, Other> && std::is_constructible_v<It, Other>>>
- constexpr dense_map_iterator(const dense_map_iterator<Other> &other) noexcept
- : it{other.it} {}
- constexpr dense_map_iterator &operator++() noexcept {
- return ++it, *this;
- }
- constexpr dense_map_iterator operator++(int) noexcept {
- const dense_map_iterator orig = *this;
- return ++(*this), orig;
- }
- constexpr dense_map_iterator &operator--() noexcept {
- return --it, *this;
- }
- constexpr dense_map_iterator operator--(int) noexcept {
- const dense_map_iterator orig = *this;
- return operator--(), orig;
- }
- constexpr dense_map_iterator &operator+=(const difference_type value) noexcept {
- it += value;
- return *this;
- }
- constexpr dense_map_iterator operator+(const difference_type value) const noexcept {
- dense_map_iterator copy = *this;
- return (copy += value);
- }
- constexpr dense_map_iterator &operator-=(const difference_type value) noexcept {
- return (*this += -value);
- }
- constexpr dense_map_iterator operator-(const difference_type value) const noexcept {
- return (*this + -value);
- }
- [[nodiscard]] constexpr reference operator[](const difference_type value) const noexcept {
- return {it[value].element.first, it[value].element.second};
- }
- [[nodiscard]] constexpr pointer operator->() const noexcept {
- return operator*();
- }
- [[nodiscard]] constexpr reference operator*() const noexcept {
- return operator[](0);
- }
- template<typename Lhs, typename Rhs>
- friend constexpr std::ptrdiff_t operator-(const dense_map_iterator<Lhs> &, const dense_map_iterator<Rhs> &) noexcept;
- template<typename Lhs, typename Rhs>
- friend constexpr bool operator==(const dense_map_iterator<Lhs> &, const dense_map_iterator<Rhs> &) noexcept;
- template<typename Lhs, typename Rhs>
- friend constexpr bool operator<(const dense_map_iterator<Lhs> &, const dense_map_iterator<Rhs> &) noexcept;
- private:
- It it;
- };
- template<typename Lhs, typename Rhs>
- [[nodiscard]] constexpr std::ptrdiff_t operator-(const dense_map_iterator<Lhs> &lhs, const dense_map_iterator<Rhs> &rhs) noexcept {
- return lhs.it - rhs.it;
- }
- template<typename Lhs, typename Rhs>
- [[nodiscard]] constexpr bool operator==(const dense_map_iterator<Lhs> &lhs, const dense_map_iterator<Rhs> &rhs) noexcept {
- return lhs.it == rhs.it;
- }
- template<typename Lhs, typename Rhs>
- [[nodiscard]] constexpr bool operator!=(const dense_map_iterator<Lhs> &lhs, const dense_map_iterator<Rhs> &rhs) noexcept {
- return !(lhs == rhs);
- }
- template<typename Lhs, typename Rhs>
- [[nodiscard]] constexpr bool operator<(const dense_map_iterator<Lhs> &lhs, const dense_map_iterator<Rhs> &rhs) noexcept {
- return lhs.it < rhs.it;
- }
- template<typename Lhs, typename Rhs>
- [[nodiscard]] constexpr bool operator>(const dense_map_iterator<Lhs> &lhs, const dense_map_iterator<Rhs> &rhs) noexcept {
- return rhs < lhs;
- }
- template<typename Lhs, typename Rhs>
- [[nodiscard]] constexpr bool operator<=(const dense_map_iterator<Lhs> &lhs, const dense_map_iterator<Rhs> &rhs) noexcept {
- return !(lhs > rhs);
- }
- template<typename Lhs, typename Rhs>
- [[nodiscard]] constexpr bool operator>=(const dense_map_iterator<Lhs> &lhs, const dense_map_iterator<Rhs> &rhs) noexcept {
- return !(lhs < rhs);
- }
- template<typename It>
- class dense_map_local_iterator final {
- template<typename>
- friend class dense_map_local_iterator;
- using first_type = decltype(std::as_const(std::declval<It>()->element.first));
- using second_type = decltype((std::declval<It>()->element.second));
- public:
- using value_type = std::pair<first_type, second_type>;
- using pointer = input_iterator_pointer<value_type>;
- using reference = value_type;
- using difference_type = std::ptrdiff_t;
- using iterator_category = std::input_iterator_tag;
- using iterator_concept = std::forward_iterator_tag;
- constexpr dense_map_local_iterator() noexcept = default;
- constexpr dense_map_local_iterator(It iter, const std::size_t pos) noexcept
- : it{iter},
- offset{pos} {}
- template<typename Other, typename = std::enable_if_t<!std::is_same_v<It, Other> && std::is_constructible_v<It, Other>>>
- constexpr dense_map_local_iterator(const dense_map_local_iterator<Other> &other) noexcept
- : it{other.it},
- offset{other.offset} {}
- constexpr dense_map_local_iterator &operator++() noexcept {
- return (offset = it[static_cast<typename It::difference_type>(offset)].next), *this;
- }
- constexpr dense_map_local_iterator operator++(int) noexcept {
- const dense_map_local_iterator orig = *this;
- return ++(*this), orig;
- }
- [[nodiscard]] constexpr pointer operator->() const noexcept {
- return operator*();
- }
- [[nodiscard]] constexpr reference operator*() const noexcept {
- const auto idx = static_cast<typename It::difference_type>(offset);
- return {it[idx].element.first, it[idx].element.second};
- }
- [[nodiscard]] constexpr std::size_t index() const noexcept {
- return offset;
- }
- private:
- It it{};
- std::size_t offset{dense_map_placeholder_position};
- };
- template<typename Lhs, typename Rhs>
- [[nodiscard]] constexpr bool operator==(const dense_map_local_iterator<Lhs> &lhs, const dense_map_local_iterator<Rhs> &rhs) noexcept {
- return lhs.index() == rhs.index();
- }
- template<typename Lhs, typename Rhs>
- [[nodiscard]] constexpr bool operator!=(const dense_map_local_iterator<Lhs> &lhs, const dense_map_local_iterator<Rhs> &rhs) noexcept {
- return !(lhs == rhs);
- }
- } // namespace internal
- /*! @endcond */
- /**
- * @brief Associative container for key-value pairs with unique keys.
- *
- * Internally, elements are organized into buckets. Which bucket an element is
- * placed into depends entirely on the hash of its key. Keys with the same hash
- * code appear in the same bucket.
- *
- * @tparam Key Key type of the associative container.
- * @tparam Type Mapped type of the associative container.
- * @tparam Hash Type of function to use to hash the keys.
- * @tparam KeyEqual Type of function to use to compare the keys for equality.
- * @tparam Allocator Type of allocator used to manage memory and elements.
- */
- template<typename Key, typename Type, typename Hash, typename KeyEqual, typename Allocator>
- class dense_map {
- static constexpr float default_threshold = 0.875f;
- static constexpr std::size_t minimum_capacity = 8u;
- static constexpr std::size_t placeholder_position = internal::dense_map_placeholder_position;
- using node_type = internal::dense_map_node<Key, Type>;
- using alloc_traits = std::allocator_traits<Allocator>;
- static_assert(std::is_same_v<typename alloc_traits::value_type, std::pair<const Key, Type>>, "Invalid value type");
- using sparse_container_type = std::vector<std::size_t, typename alloc_traits::template rebind_alloc<std::size_t>>;
- using packed_container_type = std::vector<node_type, typename alloc_traits::template rebind_alloc<node_type>>;
- template<typename Other>
- [[nodiscard]] std::size_t key_to_bucket(const Other &key) const noexcept {
- // NOLINTNEXTLINE(cppcoreguidelines-pro-bounds-array-to-pointer-decay)
- return fast_mod(static_cast<size_type>(sparse.second()(key)), bucket_count());
- }
- template<typename Other>
- [[nodiscard]] auto constrained_find(const Other &key, const std::size_t bucket) {
- for(auto offset = sparse.first()[bucket]; offset != placeholder_position; offset = packed.first()[offset].next) {
- if(packed.second()(packed.first()[offset].element.first, key)) {
- return begin() + static_cast<typename iterator::difference_type>(offset);
- }
- }
- return end();
- }
- template<typename Other>
- [[nodiscard]] auto constrained_find(const Other &key, const std::size_t bucket) const {
- for(auto offset = sparse.first()[bucket]; offset != placeholder_position; offset = packed.first()[offset].next) {
- if(packed.second()(packed.first()[offset].element.first, key)) {
- return cbegin() + static_cast<typename const_iterator::difference_type>(offset);
- }
- }
- return cend();
- }
- template<typename Other, typename... Args>
- [[nodiscard]] auto insert_or_do_nothing(Other &&key, Args &&...args) {
- const auto index = key_to_bucket(key);
- if(auto it = constrained_find(key, index); it != end()) {
- return std::make_pair(it, false);
- }
- packed.first().emplace_back(sparse.first()[index], std::piecewise_construct, std::forward_as_tuple(std::forward<Other>(key)), std::forward_as_tuple(std::forward<Args>(args)...));
- sparse.first()[index] = packed.first().size() - 1u;
- rehash_if_required();
- return std::make_pair(--end(), true);
- }
- template<typename Other, typename Arg>
- [[nodiscard]] auto insert_or_overwrite(Other &&key, Arg &&value) {
- const auto index = key_to_bucket(key);
- if(auto it = constrained_find(key, index); it != end()) {
- it->second = std::forward<Arg>(value);
- return std::make_pair(it, false);
- }
- packed.first().emplace_back(sparse.first()[index], std::forward<Other>(key), std::forward<Arg>(value));
- sparse.first()[index] = packed.first().size() - 1u;
- rehash_if_required();
- return std::make_pair(--end(), true);
- }
- void move_and_pop(const std::size_t pos) {
- if(const auto last = size() - 1u; pos != last) {
- size_type *curr = &sparse.first()[key_to_bucket(packed.first().back().element.first)];
- packed.first()[pos] = std::move(packed.first().back());
- for(; *curr != last; curr = &packed.first()[*curr].next) {}
- *curr = pos;
- }
- packed.first().pop_back();
- }
- void rehash_if_required() {
- if(const auto bc = bucket_count(); size() > static_cast<size_type>(static_cast<float>(bc) * max_load_factor())) {
- rehash(bc * 2u);
- }
- }
- public:
- /*! @brief Allocator type. */
- using allocator_type = Allocator;
- /*! @brief Key type of the container. */
- using key_type = Key;
- /*! @brief Mapped type of the container. */
- using mapped_type = Type;
- /*! @brief Key-value type of the container. */
- using value_type = std::pair<const Key, Type>;
- /*! @brief Unsigned integer type. */
- using size_type = std::size_t;
- /*! @brief Signed integer type. */
- using difference_type = std::ptrdiff_t;
- /*! @brief Type of function to use to hash the keys. */
- using hasher = Hash;
- /*! @brief Type of function to use to compare the keys for equality. */
- using key_equal = KeyEqual;
- /*! @brief Input iterator type. */
- using iterator = internal::dense_map_iterator<typename packed_container_type::iterator>;
- /*! @brief Constant input iterator type. */
- using const_iterator = internal::dense_map_iterator<typename packed_container_type::const_iterator>;
- /*! @brief Input iterator type. */
- using local_iterator = internal::dense_map_local_iterator<typename packed_container_type::iterator>;
- /*! @brief Constant input iterator type. */
- using const_local_iterator = internal::dense_map_local_iterator<typename packed_container_type::const_iterator>;
- /*! @brief Default constructor. */
- dense_map()
- : dense_map{minimum_capacity} {}
- /**
- * @brief Constructs an empty container with a given allocator.
- * @param allocator The allocator to use.
- */
- explicit dense_map(const allocator_type &allocator)
- : dense_map{minimum_capacity, hasher{}, key_equal{}, allocator} {}
- /**
- * @brief Constructs an empty container with a given allocator and user
- * supplied minimal number of buckets.
- * @param cnt Minimal number of buckets.
- * @param allocator The allocator to use.
- */
- dense_map(const size_type cnt, const allocator_type &allocator)
- : dense_map{cnt, hasher{}, key_equal{}, allocator} {}
- /**
- * @brief Constructs an empty container with a given allocator, hash
- * function and user supplied minimal number of buckets.
- * @param cnt Minimal number of buckets.
- * @param hash Hash function to use.
- * @param allocator The allocator to use.
- */
- dense_map(const size_type cnt, const hasher &hash, const allocator_type &allocator)
- : dense_map{cnt, hash, key_equal{}, allocator} {}
- /**
- * @brief Constructs an empty container with a given allocator, hash
- * function, compare function and user supplied minimal number of buckets.
- * @param cnt Minimal number of buckets.
- * @param hash Hash function to use.
- * @param equal Compare function to use.
- * @param allocator The allocator to use.
- */
- explicit dense_map(const size_type cnt, const hasher &hash = hasher{}, const key_equal &equal = key_equal{}, const allocator_type &allocator = allocator_type{})
- : sparse{allocator, hash},
- packed{allocator, equal} {
- rehash(cnt);
- }
- /*! @brief Default copy constructor. */
- dense_map(const dense_map &) = default;
- /**
- * @brief Allocator-extended copy constructor.
- * @param other The instance to copy from.
- * @param allocator The allocator to use.
- */
- dense_map(const dense_map &other, const allocator_type &allocator)
- : sparse{std::piecewise_construct, std::forward_as_tuple(other.sparse.first(), allocator), std::forward_as_tuple(other.sparse.second())},
- packed{std::piecewise_construct, std::forward_as_tuple(other.packed.first(), allocator), std::forward_as_tuple(other.packed.second())},
- threshold{other.threshold} {}
- /*! @brief Default move constructor. */
- dense_map(dense_map &&) noexcept = default;
- /**
- * @brief Allocator-extended move constructor.
- * @param other The instance to move from.
- * @param allocator The allocator to use.
- */
- dense_map(dense_map &&other, const allocator_type &allocator)
- : sparse{std::piecewise_construct, std::forward_as_tuple(std::move(other.sparse.first()), allocator), std::forward_as_tuple(std::move(other.sparse.second()))},
- packed{std::piecewise_construct, std::forward_as_tuple(std::move(other.packed.first()), allocator), std::forward_as_tuple(std::move(other.packed.second()))},
- threshold{other.threshold} {}
- /*! @brief Default destructor. */
- ~dense_map() = default;
- /**
- * @brief Default copy assignment operator.
- * @return This container.
- */
- dense_map &operator=(const dense_map &) = default;
- /**
- * @brief Default move assignment operator.
- * @return This container.
- */
- dense_map &operator=(dense_map &&) noexcept = default;
- /**
- * @brief Exchanges the contents with those of a given container.
- * @param other Container to exchange the content with.
- */
- void swap(dense_map &other) noexcept {
- using std::swap;
- swap(sparse, other.sparse);
- swap(packed, other.packed);
- swap(threshold, other.threshold);
- }
- /**
- * @brief Returns the associated allocator.
- * @return The associated allocator.
- */
- [[nodiscard]] constexpr allocator_type get_allocator() const noexcept {
- return sparse.first().get_allocator();
- }
- /**
- * @brief Returns an iterator to the beginning.
- *
- * If the array is empty, the returned iterator will be equal to `end()`.
- *
- * @return An iterator to the first instance of the internal array.
- */
- [[nodiscard]] const_iterator cbegin() const noexcept {
- return packed.first().begin();
- }
- /*! @copydoc cbegin */
- [[nodiscard]] const_iterator begin() const noexcept {
- return cbegin();
- }
- /*! @copydoc begin */
- [[nodiscard]] iterator begin() noexcept {
- return packed.first().begin();
- }
- /**
- * @brief Returns an iterator to the end.
- * @return An iterator to the element following the last instance of the
- * internal array.
- */
- [[nodiscard]] const_iterator cend() const noexcept {
- return packed.first().end();
- }
- /*! @copydoc cend */
- [[nodiscard]] const_iterator end() const noexcept {
- return cend();
- }
- /*! @copydoc end */
- [[nodiscard]] iterator end() noexcept {
- return packed.first().end();
- }
- /**
- * @brief Checks whether a container is empty.
- * @return True if the container is empty, false otherwise.
- */
- [[nodiscard]] bool empty() const noexcept {
- return packed.first().empty();
- }
- /**
- * @brief Returns the number of elements in a container.
- * @return Number of elements in a container.
- */
- [[nodiscard]] size_type size() const noexcept {
- return packed.first().size();
- }
- /**
- * @brief Returns the maximum possible number of elements.
- * @return Maximum possible number of elements.
- */
- [[nodiscard]] size_type max_size() const noexcept {
- return packed.first().max_size();
- }
- /*! @brief Clears the container. */
- void clear() noexcept {
- sparse.first().clear();
- packed.first().clear();
- rehash(0u);
- }
- /**
- * @brief Inserts an element into the container, if the key does not exist.
- * @param value A key-value pair eventually convertible to the value type.
- * @return A pair consisting of an iterator to the inserted element (or to
- * the element that prevented the insertion) and a bool denoting whether the
- * insertion took place.
- */
- std::pair<iterator, bool> insert(const value_type &value) {
- return insert_or_do_nothing(value.first, value.second);
- }
- /*! @copydoc insert */
- std::pair<iterator, bool> insert(value_type &&value) {
- return insert_or_do_nothing(std::move(value.first), std::move(value.second));
- }
- /**
- * @copydoc insert
- * @tparam Arg Type of the key-value pair to insert into the container.
- */
- template<typename Arg>
- std::enable_if_t<std::is_constructible_v<value_type, Arg &&>, std::pair<iterator, bool>>
- insert(Arg &&value) {
- return insert_or_do_nothing(std::forward<Arg>(value).first, std::forward<Arg>(value).second);
- }
- /**
- * @brief Inserts elements into the container, if their keys do not exist.
- * @tparam It Type of input iterator.
- * @param first An iterator to the first element of the range of elements.
- * @param last An iterator past the last element of the range of elements.
- */
- template<typename It>
- void insert(It first, It last) {
- for(; first != last; ++first) {
- insert(*first);
- }
- }
- /**
- * @brief Inserts an element into the container or assigns to the current
- * element if the key already exists.
- * @tparam Arg Type of the value to insert or assign.
- * @param key A key used both to look up and to insert if not found.
- * @param value A value to insert or assign.
- * @return A pair consisting of an iterator to the element and a bool
- * denoting whether the insertion took place.
- */
- template<typename Arg>
- std::pair<iterator, bool> insert_or_assign(const key_type &key, Arg &&value) {
- return insert_or_overwrite(key, std::forward<Arg>(value));
- }
- /*! @copydoc insert_or_assign */
- template<typename Arg>
- std::pair<iterator, bool> insert_or_assign(key_type &&key, Arg &&value) {
- return insert_or_overwrite(std::move(key), std::forward<Arg>(value));
- }
- /**
- * @brief Constructs an element in-place, if the key does not exist.
- *
- * The element is also constructed when the container already has the key,
- * in which case the newly constructed object is destroyed immediately.
- *
- * @tparam Args Types of arguments to forward to the constructor of the
- * element.
- * @param args Arguments to forward to the constructor of the element.
- * @return A pair consisting of an iterator to the inserted element (or to
- * the element that prevented the insertion) and a bool denoting whether the
- * insertion took place.
- */
- template<typename... Args>
- std::pair<iterator, bool> emplace([[maybe_unused]] Args &&...args) {
- if constexpr(sizeof...(Args) == 0u) {
- return insert_or_do_nothing(key_type{});
- } else if constexpr(sizeof...(Args) == 1u) {
- return insert_or_do_nothing(std::forward<Args>(args).first..., std::forward<Args>(args).second...);
- } else if constexpr(sizeof...(Args) == 2u) {
- return insert_or_do_nothing(std::forward<Args>(args)...);
- } else {
- auto &node = packed.first().emplace_back(packed.first().size(), std::forward<Args>(args)...);
- const auto index = key_to_bucket(node.element.first);
- if(auto it = constrained_find(node.element.first, index); it != end()) {
- packed.first().pop_back();
- return std::make_pair(it, false);
- }
- std::swap(node.next, sparse.first()[index]);
- rehash_if_required();
- return std::make_pair(--end(), true);
- }
- }
- /**
- * @brief Inserts in-place if the key does not exist, does nothing if the
- * key exists.
- * @tparam Args Types of arguments to forward to the constructor of the
- * element.
- * @param key A key used both to look up and to insert if not found.
- * @param args Arguments to forward to the constructor of the element.
- * @return A pair consisting of an iterator to the inserted element (or to
- * the element that prevented the insertion) and a bool denoting whether the
- * insertion took place.
- */
- template<typename... Args>
- std::pair<iterator, bool> try_emplace(const key_type &key, Args &&...args) {
- return insert_or_do_nothing(key, std::forward<Args>(args)...);
- }
- /*! @copydoc try_emplace */
- template<typename... Args>
- std::pair<iterator, bool> try_emplace(key_type &&key, Args &&...args) {
- return insert_or_do_nothing(std::move(key), std::forward<Args>(args)...);
- }
- /**
- * @brief Removes an element from a given position.
- * @param pos An iterator to the element to remove.
- * @return An iterator following the removed element.
- */
- iterator erase(const_iterator pos) {
- const auto diff = pos - cbegin();
- erase(pos->first);
- return begin() + diff;
- }
- /**
- * @brief Removes the given elements from a container.
- * @param first An iterator to the first element of the range of elements.
- * @param last An iterator past the last element of the range of elements.
- * @return An iterator following the last removed element.
- */
- iterator erase(const_iterator first, const_iterator last) {
- const auto dist = first - cbegin();
- for(auto from = last - cbegin(); from != dist; --from) {
- erase(packed.first()[static_cast<size_type>(from) - 1u].element.first);
- }
- return (begin() + dist);
- }
- /**
- * @brief Removes the element associated with a given key.
- * @param key A key value of an element to remove.
- * @return Number of elements removed (either 0 or 1).
- */
- size_type erase(const key_type &key) {
- for(size_type *curr = &sparse.first()[key_to_bucket(key)]; *curr != placeholder_position; curr = &packed.first()[*curr].next) {
- if(packed.second()(packed.first()[*curr].element.first, key)) {
- const auto index = *curr;
- *curr = packed.first()[*curr].next;
- move_and_pop(index);
- return 1u;
- }
- }
- return 0u;
- }
- /**
- * @brief Accesses a given element with bounds checking.
- * @param key A key of an element to find.
- * @return A reference to the mapped value of the requested element.
- */
- [[nodiscard]] mapped_type &at(const key_type &key) {
- auto it = find(key);
- ENTT_ASSERT(it != end(), "Invalid key");
- return it->second;
- }
- /*! @copydoc at */
- [[nodiscard]] const mapped_type &at(const key_type &key) const {
- auto it = find(key);
- ENTT_ASSERT(it != cend(), "Invalid key");
- return it->second;
- }
- /**
- * @brief Accesses a given element with bounds checking.
- * @tparam Other Type of the key of an element to find.
- * @param key A key of an element to find.
- * @return A reference to the mapped value of the requested element.
- */
- template<typename Other>
- [[nodiscard]] std::enable_if_t<is_transparent_v<hasher> && is_transparent_v<key_equal>, std::conditional_t<false, Other, mapped_type const &>>
- at(const Other &key) const {
- auto it = find(key);
- ENTT_ASSERT(it != cend(), "Invalid key");
- return it->second;
- }
- /*! @copydoc at */
- template<typename Other>
- [[nodiscard]] std::enable_if_t<is_transparent_v<hasher> && is_transparent_v<key_equal>, std::conditional_t<false, Other, mapped_type &>>
- at(const Other &key) {
- auto it = find(key);
- ENTT_ASSERT(it != end(), "Invalid key");
- return it->second;
- }
- /**
- * @brief Accesses or inserts a given element.
- * @param key A key of an element to find or insert.
- * @return A reference to the mapped value of the requested element.
- */
- [[nodiscard]] mapped_type &operator[](const key_type &key) {
- return insert_or_do_nothing(key).first->second;
- }
- /**
- * @brief Accesses or inserts a given element.
- * @param key A key of an element to find or insert.
- * @return A reference to the mapped value of the requested element.
- */
- [[nodiscard]] mapped_type &operator[](key_type &&key) {
- return insert_or_do_nothing(std::move(key)).first->second;
- }
- /**
- * @brief Returns the number of elements matching a key (either 1 or 0).
- * @param key Key value of an element to search for.
- * @return Number of elements matching the key (either 1 or 0).
- */
- [[nodiscard]] size_type count(const key_type &key) const {
- return find(key) != end();
- }
- /**
- * @brief Returns the number of elements matching a key (either 1 or 0).
- * @tparam Other Type of the key value of an element to search for.
- * @param key Key value of an element to search for.
- * @return Number of elements matching the key (either 1 or 0).
- */
- template<typename Other>
- [[nodiscard]] std::enable_if_t<is_transparent_v<hasher> && is_transparent_v<key_equal>, std::conditional_t<false, Other, size_type>>
- count(const Other &key) const {
- return find(key) != end();
- }
- /**
- * @brief Finds an element with a given key.
- * @param key Key value of an element to search for.
- * @return An iterator to an element with the given key. If no such element
- * is found, a past-the-end iterator is returned.
- */
- [[nodiscard]] iterator find(const key_type &key) {
- return constrained_find(key, key_to_bucket(key));
- }
- /*! @copydoc find */
- [[nodiscard]] const_iterator find(const key_type &key) const {
- return constrained_find(key, key_to_bucket(key));
- }
- /**
- * @brief Finds an element with a key that compares _equivalent_ to a given
- * key.
- * @tparam Other Type of the key value of an element to search for.
- * @param key Key value of an element to search for.
- * @return An iterator to an element with the given key. If no such element
- * is found, a past-the-end iterator is returned.
- */
- template<typename Other>
- [[nodiscard]] std::enable_if_t<is_transparent_v<hasher> && is_transparent_v<key_equal>, std::conditional_t<false, Other, iterator>>
- find(const Other &key) {
- return constrained_find(key, key_to_bucket(key));
- }
- /*! @copydoc find */
- template<typename Other>
- [[nodiscard]] std::enable_if_t<is_transparent_v<hasher> && is_transparent_v<key_equal>, std::conditional_t<false, Other, const_iterator>>
- find(const Other &key) const {
- return constrained_find(key, key_to_bucket(key));
- }
- /**
- * @brief Returns a range containing all elements with a given key.
- * @param key Key value of an element to search for.
- * @return A pair of iterators pointing to the first element and past the
- * last element of the range.
- */
- [[nodiscard]] std::pair<iterator, iterator> equal_range(const key_type &key) {
- const auto it = find(key);
- return {it, it + !(it == end())};
- }
- /*! @copydoc equal_range */
- [[nodiscard]] std::pair<const_iterator, const_iterator> equal_range(const key_type &key) const {
- const auto it = find(key);
- return {it, it + !(it == cend())};
- }
- /**
- * @brief Returns a range containing all elements that compare _equivalent_
- * to a given key.
- * @tparam Other Type of an element to search for.
- * @param key Key value of an element to search for.
- * @return A pair of iterators pointing to the first element and past the
- * last element of the range.
- */
- template<typename Other>
- [[nodiscard]] std::enable_if_t<is_transparent_v<hasher> && is_transparent_v<key_equal>, std::conditional_t<false, Other, std::pair<iterator, iterator>>>
- equal_range(const Other &key) {
- const auto it = find(key);
- return {it, it + !(it == end())};
- }
- /*! @copydoc equal_range */
- template<typename Other>
- [[nodiscard]] std::enable_if_t<is_transparent_v<hasher> && is_transparent_v<key_equal>, std::conditional_t<false, Other, std::pair<const_iterator, const_iterator>>>
- equal_range(const Other &key) const {
- const auto it = find(key);
- return {it, it + !(it == cend())};
- }
- /**
- * @brief Checks if the container contains an element with a given key.
- * @param key Key value of an element to search for.
- * @return True if there is such an element, false otherwise.
- */
- [[nodiscard]] bool contains(const key_type &key) const {
- return (find(key) != cend());
- }
- /**
- * @brief Checks if the container contains an element with a key that
- * compares _equivalent_ to a given value.
- * @tparam Other Type of the key value of an element to search for.
- * @param key Key value of an element to search for.
- * @return True if there is such an element, false otherwise.
- */
- template<typename Other>
- [[nodiscard]] std::enable_if_t<is_transparent_v<hasher> && is_transparent_v<key_equal>, std::conditional_t<false, Other, bool>>
- contains(const Other &key) const {
- return (find(key) != cend());
- }
- /**
- * @brief Returns an iterator to the beginning of a given bucket.
- * @param index An index of a bucket to access.
- * @return An iterator to the beginning of the given bucket.
- */
- [[nodiscard]] const_local_iterator cbegin(const size_type index) const {
- return {packed.first().begin(), sparse.first()[index]};
- }
- /**
- * @brief Returns an iterator to the beginning of a given bucket.
- * @param index An index of a bucket to access.
- * @return An iterator to the beginning of the given bucket.
- */
- [[nodiscard]] const_local_iterator begin(const size_type index) const {
- return cbegin(index);
- }
- /**
- * @brief Returns an iterator to the beginning of a given bucket.
- * @param index An index of a bucket to access.
- * @return An iterator to the beginning of the given bucket.
- */
- [[nodiscard]] local_iterator begin(const size_type index) {
- return {packed.first().begin(), sparse.first()[index]};
- }
- /**
- * @brief Returns an iterator to the end of a given bucket.
- * @param index An index of a bucket to access.
- * @return An iterator to the end of the given bucket.
- */
- [[nodiscard]] const_local_iterator cend([[maybe_unused]] const size_type index) const {
- return {};
- }
- /**
- * @brief Returns an iterator to the end of a given bucket.
- * @param index An index of a bucket to access.
- * @return An iterator to the end of the given bucket.
- */
- [[nodiscard]] const_local_iterator end(const size_type index) const {
- return cend(index);
- }
- /**
- * @brief Returns an iterator to the end of a given bucket.
- * @param index An index of a bucket to access.
- * @return An iterator to the end of the given bucket.
- */
- [[nodiscard]] local_iterator end([[maybe_unused]] const size_type index) {
- return {};
- }
- /**
- * @brief Returns the number of buckets.
- * @return The number of buckets.
- */
- [[nodiscard]] size_type bucket_count() const {
- return sparse.first().size();
- }
- /**
- * @brief Returns the maximum number of buckets.
- * @return The maximum number of buckets.
- */
- [[nodiscard]] size_type max_bucket_count() const {
- return sparse.first().max_size();
- }
- /**
- * @brief Returns the number of elements in a given bucket.
- * @param index The index of the bucket to examine.
- * @return The number of elements in the given bucket.
- */
- [[nodiscard]] size_type bucket_size(const size_type index) const {
- return static_cast<size_type>(std::distance(begin(index), end(index)));
- }
- /**
- * @brief Returns the bucket for a given key.
- * @param key The value of the key to examine.
- * @return The bucket for the given key.
- */
- [[nodiscard]] size_type bucket(const key_type &key) const {
- return key_to_bucket(key);
- }
- /**
- * @brief Returns the average number of elements per bucket.
- * @return The average number of elements per bucket.
- */
- [[nodiscard]] float load_factor() const {
- return static_cast<float>(size()) / static_cast<float>(bucket_count());
- }
- /**
- * @brief Returns the maximum average number of elements per bucket.
- * @return The maximum average number of elements per bucket.
- */
- [[nodiscard]] float max_load_factor() const {
- return threshold;
- }
- /**
- * @brief Sets the desired maximum average number of elements per bucket.
- * @param value A desired maximum average number of elements per bucket.
- */
- void max_load_factor(const float value) {
- ENTT_ASSERT(value > 0.f, "Invalid load factor");
- threshold = value;
- rehash(0u);
- }
- /**
- * @brief Reserves at least the specified number of buckets and regenerates
- * the hash table.
- * @param cnt New number of buckets.
- */
- void rehash(const size_type cnt) {
- auto value = cnt > minimum_capacity ? cnt : minimum_capacity;
- const auto cap = static_cast<size_type>(static_cast<float>(size()) / max_load_factor());
- value = value > cap ? value : cap;
- if(const auto sz = next_power_of_two(value); sz != bucket_count()) {
- sparse.first().resize(sz);
- for(auto &&elem: sparse.first()) {
- elem = placeholder_position;
- }
- for(size_type pos{}, last = size(); pos < last; ++pos) {
- const auto index = key_to_bucket(packed.first()[pos].element.first);
- packed.first()[pos].next = std::exchange(sparse.first()[index], pos);
- }
- }
- }
- /**
- * @brief Reserves space for at least the specified number of elements and
- * regenerates the hash table.
- * @param cnt New number of elements.
- */
- void reserve(const size_type cnt) {
- packed.first().reserve(cnt);
- rehash(static_cast<size_type>(std::ceil(static_cast<float>(cnt) / max_load_factor())));
- }
- /**
- * @brief Returns the function used to hash the keys.
- * @return The function used to hash the keys.
- */
- [[nodiscard]] hasher hash_function() const {
- return sparse.second();
- }
- /**
- * @brief Returns the function used to compare keys for equality.
- * @return The function used to compare keys for equality.
- */
- [[nodiscard]] key_equal key_eq() const {
- return packed.second();
- }
- private:
- compressed_pair<sparse_container_type, hasher> sparse;
- compressed_pair<packed_container_type, key_equal> packed;
- float threshold{default_threshold};
- };
- } // namespace entt
- /*! @cond TURN_OFF_DOXYGEN */
- namespace std {
- template<typename Key, typename Value, typename Allocator>
- struct uses_allocator<entt::internal::dense_map_node<Key, Value>, Allocator>
- : std::true_type {};
- } // namespace std
- /*! @endcond */
- #endif
- // #include "../container/dense_set.hpp"
- #ifndef ENTT_CONTAINER_DENSE_SET_HPP
- #define ENTT_CONTAINER_DENSE_SET_HPP
- #include <cmath>
- #include <cstddef>
- #include <functional>
- #include <iterator>
- #include <limits>
- #include <memory>
- #include <tuple>
- #include <type_traits>
- #include <utility>
- #include <vector>
- // #include "../config/config.h"
- // #include "../core/bit.hpp"
- // #include "../core/compressed_pair.hpp"
- // #include "../core/type_traits.hpp"
- // #include "fwd.hpp"
- namespace entt {
- /*! @cond TURN_OFF_DOXYGEN */
- namespace internal {
- static constexpr std::size_t dense_set_placeholder_position = (std::numeric_limits<std::size_t>::max)();
- template<typename It>
- class dense_set_iterator final {
- template<typename>
- friend class dense_set_iterator;
- public:
- using value_type = typename It::value_type::second_type;
- using pointer = const value_type *;
- using reference = const value_type &;
- using difference_type = std::ptrdiff_t;
- using iterator_category = std::random_access_iterator_tag;
- constexpr dense_set_iterator() noexcept
- : it{} {}
- constexpr dense_set_iterator(const It iter) noexcept
- : it{iter} {}
- template<typename Other, typename = std::enable_if_t<!std::is_same_v<It, Other> && std::is_constructible_v<It, Other>>>
- constexpr dense_set_iterator(const dense_set_iterator<Other> &other) noexcept
- : it{other.it} {}
- constexpr dense_set_iterator &operator++() noexcept {
- return ++it, *this;
- }
- constexpr dense_set_iterator operator++(int) noexcept {
- const dense_set_iterator orig = *this;
- return ++(*this), orig;
- }
- constexpr dense_set_iterator &operator--() noexcept {
- return --it, *this;
- }
- constexpr dense_set_iterator operator--(int) noexcept {
- const dense_set_iterator orig = *this;
- return operator--(), orig;
- }
- constexpr dense_set_iterator &operator+=(const difference_type value) noexcept {
- it += value;
- return *this;
- }
- constexpr dense_set_iterator operator+(const difference_type value) const noexcept {
- dense_set_iterator copy = *this;
- return (copy += value);
- }
- constexpr dense_set_iterator &operator-=(const difference_type value) noexcept {
- return (*this += -value);
- }
- constexpr dense_set_iterator operator-(const difference_type value) const noexcept {
- return (*this + -value);
- }
- [[nodiscard]] constexpr reference operator[](const difference_type value) const noexcept {
- return it[value].second;
- }
- [[nodiscard]] constexpr pointer operator->() const noexcept {
- return std::addressof(operator[](0));
- }
- [[nodiscard]] constexpr reference operator*() const noexcept {
- return operator[](0);
- }
- template<typename Lhs, typename Rhs>
- friend constexpr std::ptrdiff_t operator-(const dense_set_iterator<Lhs> &, const dense_set_iterator<Rhs> &) noexcept;
- template<typename Lhs, typename Rhs>
- friend constexpr bool operator==(const dense_set_iterator<Lhs> &, const dense_set_iterator<Rhs> &) noexcept;
- template<typename Lhs, typename Rhs>
- friend constexpr bool operator<(const dense_set_iterator<Lhs> &, const dense_set_iterator<Rhs> &) noexcept;
- private:
- It it;
- };
- template<typename Lhs, typename Rhs>
- [[nodiscard]] constexpr std::ptrdiff_t operator-(const dense_set_iterator<Lhs> &lhs, const dense_set_iterator<Rhs> &rhs) noexcept {
- return lhs.it - rhs.it;
- }
- template<typename Lhs, typename Rhs>
- [[nodiscard]] constexpr bool operator==(const dense_set_iterator<Lhs> &lhs, const dense_set_iterator<Rhs> &rhs) noexcept {
- return lhs.it == rhs.it;
- }
- template<typename Lhs, typename Rhs>
- [[nodiscard]] constexpr bool operator!=(const dense_set_iterator<Lhs> &lhs, const dense_set_iterator<Rhs> &rhs) noexcept {
- return !(lhs == rhs);
- }
- template<typename Lhs, typename Rhs>
- [[nodiscard]] constexpr bool operator<(const dense_set_iterator<Lhs> &lhs, const dense_set_iterator<Rhs> &rhs) noexcept {
- return lhs.it < rhs.it;
- }
- template<typename Lhs, typename Rhs>
- [[nodiscard]] constexpr bool operator>(const dense_set_iterator<Lhs> &lhs, const dense_set_iterator<Rhs> &rhs) noexcept {
- return rhs < lhs;
- }
- template<typename Lhs, typename Rhs>
- [[nodiscard]] constexpr bool operator<=(const dense_set_iterator<Lhs> &lhs, const dense_set_iterator<Rhs> &rhs) noexcept {
- return !(lhs > rhs);
- }
- template<typename Lhs, typename Rhs>
- [[nodiscard]] constexpr bool operator>=(const dense_set_iterator<Lhs> &lhs, const dense_set_iterator<Rhs> &rhs) noexcept {
- return !(lhs < rhs);
- }
- template<typename It>
- class dense_set_local_iterator final {
- template<typename>
- friend class dense_set_local_iterator;
- public:
- using value_type = typename It::value_type::second_type;
- using pointer = const value_type *;
- using reference = const value_type &;
- using difference_type = std::ptrdiff_t;
- using iterator_category = std::forward_iterator_tag;
- constexpr dense_set_local_iterator() noexcept = default;
- constexpr dense_set_local_iterator(It iter, const std::size_t pos) noexcept
- : it{iter},
- offset{pos} {}
- template<typename Other, typename = std::enable_if_t<!std::is_same_v<It, Other> && std::is_constructible_v<It, Other>>>
- constexpr dense_set_local_iterator(const dense_set_local_iterator<Other> &other) noexcept
- : it{other.it},
- offset{other.offset} {}
- constexpr dense_set_local_iterator &operator++() noexcept {
- return offset = it[static_cast<typename It::difference_type>(offset)].first, *this;
- }
- constexpr dense_set_local_iterator operator++(int) noexcept {
- const dense_set_local_iterator orig = *this;
- return ++(*this), orig;
- }
- [[nodiscard]] constexpr pointer operator->() const noexcept {
- return std::addressof(it[static_cast<typename It::difference_type>(offset)].second);
- }
- [[nodiscard]] constexpr reference operator*() const noexcept {
- return *operator->();
- }
- [[nodiscard]] constexpr std::size_t index() const noexcept {
- return offset;
- }
- private:
- It it{};
- std::size_t offset{dense_set_placeholder_position};
- };
- template<typename Lhs, typename Rhs>
- [[nodiscard]] constexpr bool operator==(const dense_set_local_iterator<Lhs> &lhs, const dense_set_local_iterator<Rhs> &rhs) noexcept {
- return lhs.index() == rhs.index();
- }
- template<typename Lhs, typename Rhs>
- [[nodiscard]] constexpr bool operator!=(const dense_set_local_iterator<Lhs> &lhs, const dense_set_local_iterator<Rhs> &rhs) noexcept {
- return !(lhs == rhs);
- }
- } // namespace internal
- /*! @endcond */
- /**
- * @brief Associative container for unique objects of a given type.
- *
- * Internally, elements are organized into buckets. Which bucket an element is
- * placed into depends entirely on its hash. Elements with the same hash code
- * appear in the same bucket.
- *
- * @tparam Type Value type of the associative container.
- * @tparam Hash Type of function to use to hash the values.
- * @tparam KeyEqual Type of function to use to compare the values for equality.
- * @tparam Allocator Type of allocator used to manage memory and elements.
- */
- template<typename Type, typename Hash, typename KeyEqual, typename Allocator>
- class dense_set {
- static constexpr float default_threshold = 0.875f;
- static constexpr std::size_t minimum_capacity = 8u;
- static constexpr std::size_t placeholder_position = internal::dense_set_placeholder_position;
- using node_type = std::pair<std::size_t, Type>;
- using alloc_traits = std::allocator_traits<Allocator>;
- static_assert(std::is_same_v<typename alloc_traits::value_type, Type>, "Invalid value type");
- using sparse_container_type = std::vector<std::size_t, typename alloc_traits::template rebind_alloc<std::size_t>>;
- using packed_container_type = std::vector<node_type, typename alloc_traits::template rebind_alloc<node_type>>;
- template<typename Other>
- [[nodiscard]] std::size_t value_to_bucket(const Other &value) const noexcept {
- return fast_mod(static_cast<size_type>(sparse.second()(value)), bucket_count());
- }
- template<typename Other>
- [[nodiscard]] auto constrained_find(const Other &value, const std::size_t bucket) {
- for(auto offset = sparse.first()[bucket]; offset != placeholder_position; offset = packed.first()[offset].first) {
- if(packed.second()(packed.first()[offset].second, value)) {
- return begin() + static_cast<typename iterator::difference_type>(offset);
- }
- }
- return end();
- }
- template<typename Other>
- [[nodiscard]] auto constrained_find(const Other &value, const std::size_t bucket) const {
- for(auto offset = sparse.first()[bucket]; offset != placeholder_position; offset = packed.first()[offset].first) {
- if(packed.second()(packed.first()[offset].second, value)) {
- return cbegin() + static_cast<typename const_iterator::difference_type>(offset);
- }
- }
- return cend();
- }
- template<typename Other>
- [[nodiscard]] auto insert_or_do_nothing(Other &&value) {
- const auto index = value_to_bucket(value);
- if(auto it = constrained_find(value, index); it != end()) {
- return std::make_pair(it, false);
- }
- packed.first().emplace_back(sparse.first()[index], std::forward<Other>(value));
- sparse.first()[index] = packed.first().size() - 1u;
- rehash_if_required();
- return std::make_pair(--end(), true);
- }
- void move_and_pop(const std::size_t pos) {
- if(const auto last = size() - 1u; pos != last) {
- size_type *curr = &sparse.first()[value_to_bucket(packed.first().back().second)];
- packed.first()[pos] = std::move(packed.first().back());
- for(; *curr != last; curr = &packed.first()[*curr].first) {}
- *curr = pos;
- }
- packed.first().pop_back();
- }
- void rehash_if_required() {
- if(const auto bc = bucket_count(); size() > static_cast<size_type>(static_cast<float>(bc) * max_load_factor())) {
- rehash(bc * 2u);
- }
- }
- public:
- /*! @brief Allocator type. */
- using allocator_type = Allocator;
- /*! @brief Key type of the container. */
- using key_type = Type;
- /*! @brief Value type of the container. */
- using value_type = Type;
- /*! @brief Unsigned integer type. */
- using size_type = std::size_t;
- /*! @brief Signed integer type. */
- using difference_type = std::ptrdiff_t;
- /*! @brief Type of function to use to hash the elements. */
- using hasher = Hash;
- /*! @brief Type of function to use to compare the elements for equality. */
- using key_equal = KeyEqual;
- /*! @brief Random access iterator type. */
- using iterator = internal::dense_set_iterator<typename packed_container_type::iterator>;
- /*! @brief Constant random access iterator type. */
- using const_iterator = internal::dense_set_iterator<typename packed_container_type::const_iterator>;
- /*! @brief Reverse iterator type. */
- using reverse_iterator = std::reverse_iterator<iterator>;
- /*! @brief Constant reverse iterator type. */
- using const_reverse_iterator = std::reverse_iterator<const_iterator>;
- /*! @brief Forward iterator type. */
- using local_iterator = internal::dense_set_local_iterator<typename packed_container_type::iterator>;
- /*! @brief Constant forward iterator type. */
- using const_local_iterator = internal::dense_set_local_iterator<typename packed_container_type::const_iterator>;
- /*! @brief Default constructor. */
- dense_set()
- : dense_set{minimum_capacity} {}
- /**
- * @brief Constructs an empty container with a given allocator.
- * @param allocator The allocator to use.
- */
- explicit dense_set(const allocator_type &allocator)
- : dense_set{minimum_capacity, hasher{}, key_equal{}, allocator} {}
- /**
- * @brief Constructs an empty container with a given allocator and user
- * supplied minimal number of buckets.
- * @param cnt Minimal number of buckets.
- * @param allocator The allocator to use.
- */
- dense_set(const size_type cnt, const allocator_type &allocator)
- : dense_set{cnt, hasher{}, key_equal{}, allocator} {}
- /**
- * @brief Constructs an empty container with a given allocator, hash
- * function and user supplied minimal number of buckets.
- * @param cnt Minimal number of buckets.
- * @param hash Hash function to use.
- * @param allocator The allocator to use.
- */
- dense_set(const size_type cnt, const hasher &hash, const allocator_type &allocator)
- : dense_set{cnt, hash, key_equal{}, allocator} {}
- /**
- * @brief Constructs an empty container with a given allocator, hash
- * function, compare function and user supplied minimal number of buckets.
- * @param cnt Minimal number of buckets.
- * @param hash Hash function to use.
- * @param equal Compare function to use.
- * @param allocator The allocator to use.
- */
- explicit dense_set(const size_type cnt, const hasher &hash = hasher{}, const key_equal &equal = key_equal{}, const allocator_type &allocator = allocator_type{})
- : sparse{allocator, hash},
- packed{allocator, equal} {
- rehash(cnt);
- }
- /*! @brief Default copy constructor. */
- dense_set(const dense_set &) = default;
- /**
- * @brief Allocator-extended copy constructor.
- * @param other The instance to copy from.
- * @param allocator The allocator to use.
- */
- dense_set(const dense_set &other, const allocator_type &allocator)
- : sparse{std::piecewise_construct, std::forward_as_tuple(other.sparse.first(), allocator), std::forward_as_tuple(other.sparse.second())},
- packed{std::piecewise_construct, std::forward_as_tuple(other.packed.first(), allocator), std::forward_as_tuple(other.packed.second())},
- threshold{other.threshold} {}
- /*! @brief Default move constructor. */
- dense_set(dense_set &&) noexcept = default;
- /**
- * @brief Allocator-extended move constructor.
- * @param other The instance to move from.
- * @param allocator The allocator to use.
- */
- dense_set(dense_set &&other, const allocator_type &allocator)
- : sparse{std::piecewise_construct, std::forward_as_tuple(std::move(other.sparse.first()), allocator), std::forward_as_tuple(std::move(other.sparse.second()))},
- packed{std::piecewise_construct, std::forward_as_tuple(std::move(other.packed.first()), allocator), std::forward_as_tuple(std::move(other.packed.second()))},
- threshold{other.threshold} {}
- /*! @brief Default destructor. */
- ~dense_set() = default;
- /**
- * @brief Default copy assignment operator.
- * @return This container.
- */
- dense_set &operator=(const dense_set &) = default;
- /**
- * @brief Default move assignment operator.
- * @return This container.
- */
- dense_set &operator=(dense_set &&) noexcept = default;
- /**
- * @brief Exchanges the contents with those of a given container.
- * @param other Container to exchange the content with.
- */
- void swap(dense_set &other) noexcept {
- using std::swap;
- swap(sparse, other.sparse);
- swap(packed, other.packed);
- swap(threshold, other.threshold);
- }
- /**
- * @brief Returns the associated allocator.
- * @return The associated allocator.
- */
- [[nodiscard]] constexpr allocator_type get_allocator() const noexcept {
- return sparse.first().get_allocator();
- }
- /**
- * @brief Returns an iterator to the beginning.
- *
- * If the array is empty, the returned iterator will be equal to `end()`.
- *
- * @return An iterator to the first instance of the internal array.
- */
- [[nodiscard]] const_iterator cbegin() const noexcept {
- return packed.first().begin();
- }
- /*! @copydoc cbegin */
- [[nodiscard]] const_iterator begin() const noexcept {
- return cbegin();
- }
- /*! @copydoc begin */
- [[nodiscard]] iterator begin() noexcept {
- return packed.first().begin();
- }
- /**
- * @brief Returns an iterator to the end.
- * @return An iterator to the element following the last instance of the
- * internal array.
- */
- [[nodiscard]] const_iterator cend() const noexcept {
- return packed.first().end();
- }
- /*! @copydoc cend */
- [[nodiscard]] const_iterator end() const noexcept {
- return cend();
- }
- /*! @copydoc end */
- [[nodiscard]] iterator end() noexcept {
- return packed.first().end();
- }
- /**
- * @brief Returns a reverse iterator to the beginning.
- *
- * If the array is empty, the returned iterator will be equal to `rend()`.
- *
- * @return An iterator to the first instance of the reversed internal array.
- */
- [[nodiscard]] const_reverse_iterator crbegin() const noexcept {
- return std::make_reverse_iterator(cend());
- }
- /*! @copydoc crbegin */
- [[nodiscard]] const_reverse_iterator rbegin() const noexcept {
- return crbegin();
- }
- /*! @copydoc rbegin */
- [[nodiscard]] reverse_iterator rbegin() noexcept {
- return std::make_reverse_iterator(end());
- }
- /**
- * @brief Returns a reverse iterator to the end.
- * @return An iterator to the element following the last instance of the
- * reversed internal array.
- */
- [[nodiscard]] const_reverse_iterator crend() const noexcept {
- return std::make_reverse_iterator(cbegin());
- }
- /*! @copydoc crend */
- [[nodiscard]] const_reverse_iterator rend() const noexcept {
- return crend();
- }
- /*! @copydoc rend */
- [[nodiscard]] reverse_iterator rend() noexcept {
- return std::make_reverse_iterator(begin());
- }
- /**
- * @brief Checks whether a container is empty.
- * @return True if the container is empty, false otherwise.
- */
- [[nodiscard]] bool empty() const noexcept {
- return packed.first().empty();
- }
- /**
- * @brief Returns the number of elements in a container.
- * @return Number of elements in a container.
- */
- [[nodiscard]] size_type size() const noexcept {
- return packed.first().size();
- }
- /**
- * @brief Returns the maximum possible number of elements.
- * @return Maximum possible number of elements.
- */
- [[nodiscard]] size_type max_size() const noexcept {
- return packed.first().max_size();
- }
- /*! @brief Clears the container. */
- void clear() noexcept {
- sparse.first().clear();
- packed.first().clear();
- rehash(0u);
- }
- /**
- * @brief Inserts an element into the container, if it does not exist.
- * @param value An element to insert into the container.
- * @return A pair consisting of an iterator to the inserted element (or to
- * the element that prevented the insertion) and a bool denoting whether the
- * insertion took place.
- */
- std::pair<iterator, bool> insert(const value_type &value) {
- return insert_or_do_nothing(value);
- }
- /*! @copydoc insert */
- std::pair<iterator, bool> insert(value_type &&value) {
- return insert_or_do_nothing(std::move(value));
- }
- /**
- * @brief Inserts elements into the container, if they do not exist.
- * @tparam It Type of input iterator.
- * @param first An iterator to the first element of the range of elements.
- * @param last An iterator past the last element of the range of elements.
- */
- template<typename It>
- void insert(It first, It last) {
- for(; first != last; ++first) {
- insert(*first);
- }
- }
- /**
- * @brief Constructs an element in-place, if it does not exist.
- *
- * The element is also constructed when the container already has the key,
- * in which case the newly constructed object is destroyed immediately.
- *
- * @tparam Args Types of arguments to forward to the constructor of the
- * element.
- * @param args Arguments to forward to the constructor of the element.
- * @return A pair consisting of an iterator to the inserted element (or to
- * the element that prevented the insertion) and a bool denoting whether the
- * insertion took place.
- */
- template<typename... Args>
- std::pair<iterator, bool> emplace(Args &&...args) {
- if constexpr(((sizeof...(Args) == 1u) && ... && std::is_same_v<std::decay_t<Args>, value_type>)) {
- return insert_or_do_nothing(std::forward<Args>(args)...);
- } else {
- auto &node = packed.first().emplace_back(std::piecewise_construct, std::make_tuple(packed.first().size()), std::forward_as_tuple(std::forward<Args>(args)...));
- const auto index = value_to_bucket(node.second);
- if(auto it = constrained_find(node.second, index); it != end()) {
- packed.first().pop_back();
- return std::make_pair(it, false);
- }
- std::swap(node.first, sparse.first()[index]);
- rehash_if_required();
- return std::make_pair(--end(), true);
- }
- }
- /**
- * @brief Removes an element from a given position.
- * @param pos An iterator to the element to remove.
- * @return An iterator following the removed element.
- */
- iterator erase(const_iterator pos) {
- const auto diff = pos - cbegin();
- erase(*pos);
- return begin() + diff;
- }
- /**
- * @brief Removes the given elements from a container.
- * @param first An iterator to the first element of the range of elements.
- * @param last An iterator past the last element of the range of elements.
- * @return An iterator following the last removed element.
- */
- iterator erase(const_iterator first, const_iterator last) {
- const auto dist = first - cbegin();
- for(auto from = last - cbegin(); from != dist; --from) {
- erase(packed.first()[static_cast<size_type>(from) - 1u].second);
- }
- return (begin() + dist);
- }
- /**
- * @brief Removes the element associated with a given value.
- * @param value Value of an element to remove.
- * @return Number of elements removed (either 0 or 1).
- */
- size_type erase(const value_type &value) {
- for(size_type *curr = &sparse.first()[value_to_bucket(value)]; *curr != placeholder_position; curr = &packed.first()[*curr].first) {
- if(packed.second()(packed.first()[*curr].second, value)) {
- const auto index = *curr;
- *curr = packed.first()[*curr].first;
- move_and_pop(index);
- return 1u;
- }
- }
- return 0u;
- }
- /**
- * @brief Returns the number of elements matching a value (either 1 or 0).
- * @param key Key value of an element to search for.
- * @return Number of elements matching the key (either 1 or 0).
- */
- [[nodiscard]] size_type count(const value_type &key) const {
- return find(key) != end();
- }
- /**
- * @brief Returns the number of elements matching a key (either 1 or 0).
- * @tparam Other Type of the key value of an element to search for.
- * @param key Key value of an element to search for.
- * @return Number of elements matching the key (either 1 or 0).
- */
- template<typename Other>
- [[nodiscard]] std::enable_if_t<is_transparent_v<hasher> && is_transparent_v<key_equal>, std::conditional_t<false, Other, size_type>>
- count(const Other &key) const {
- return find(key) != end();
- }
- /**
- * @brief Finds an element with a given value.
- * @param value Value of an element to search for.
- * @return An iterator to an element with the given value. If no such
- * element is found, a past-the-end iterator is returned.
- */
- [[nodiscard]] iterator find(const value_type &value) {
- return constrained_find(value, value_to_bucket(value));
- }
- /*! @copydoc find */
- [[nodiscard]] const_iterator find(const value_type &value) const {
- return constrained_find(value, value_to_bucket(value));
- }
- /**
- * @brief Finds an element that compares _equivalent_ to a given value.
- * @tparam Other Type of an element to search for.
- * @param value Value of an element to search for.
- * @return An iterator to an element with the given value. If no such
- * element is found, a past-the-end iterator is returned.
- */
- template<typename Other>
- [[nodiscard]] std::enable_if_t<is_transparent_v<hasher> && is_transparent_v<key_equal>, std::conditional_t<false, Other, iterator>>
- find(const Other &value) {
- return constrained_find(value, value_to_bucket(value));
- }
- /*! @copydoc find */
- template<typename Other>
- [[nodiscard]] std::enable_if_t<is_transparent_v<hasher> && is_transparent_v<key_equal>, std::conditional_t<false, Other, const_iterator>>
- find(const Other &value) const {
- return constrained_find(value, value_to_bucket(value));
- }
- /**
- * @brief Returns a range containing all elements with a given value.
- * @param value Value of an element to search for.
- * @return A pair of iterators pointing to the first element and past the
- * last element of the range.
- */
- [[nodiscard]] std::pair<iterator, iterator> equal_range(const value_type &value) {
- const auto it = find(value);
- return {it, it + !(it == end())};
- }
- /*! @copydoc equal_range */
- [[nodiscard]] std::pair<const_iterator, const_iterator> equal_range(const value_type &value) const {
- const auto it = find(value);
- return {it, it + !(it == cend())};
- }
- /**
- * @brief Returns a range containing all elements that compare _equivalent_
- * to a given value.
- * @tparam Other Type of an element to search for.
- * @param value Value of an element to search for.
- * @return A pair of iterators pointing to the first element and past the
- * last element of the range.
- */
- template<typename Other>
- [[nodiscard]] std::enable_if_t<is_transparent_v<hasher> && is_transparent_v<key_equal>, std::conditional_t<false, Other, std::pair<iterator, iterator>>>
- equal_range(const Other &value) {
- const auto it = find(value);
- return {it, it + !(it == end())};
- }
- /*! @copydoc equal_range */
- template<typename Other>
- [[nodiscard]] std::enable_if_t<is_transparent_v<hasher> && is_transparent_v<key_equal>, std::conditional_t<false, Other, std::pair<const_iterator, const_iterator>>>
- equal_range(const Other &value) const {
- const auto it = find(value);
- return {it, it + !(it == cend())};
- }
- /**
- * @brief Checks if the container contains an element with a given value.
- * @param value Value of an element to search for.
- * @return True if there is such an element, false otherwise.
- */
- [[nodiscard]] bool contains(const value_type &value) const {
- return (find(value) != cend());
- }
- /**
- * @brief Checks if the container contains an element that compares
- * _equivalent_ to a given value.
- * @tparam Other Type of an element to search for.
- * @param value Value of an element to search for.
- * @return True if there is such an element, false otherwise.
- */
- template<typename Other>
- [[nodiscard]] std::enable_if_t<is_transparent_v<hasher> && is_transparent_v<key_equal>, std::conditional_t<false, Other, bool>>
- contains(const Other &value) const {
- return (find(value) != cend());
- }
- /**
- * @brief Returns an iterator to the beginning of a given bucket.
- * @param index An index of a bucket to access.
- * @return An iterator to the beginning of the given bucket.
- */
- [[nodiscard]] const_local_iterator cbegin(const size_type index) const {
- return {packed.first().begin(), sparse.first()[index]};
- }
- /**
- * @brief Returns an iterator to the beginning of a given bucket.
- * @param index An index of a bucket to access.
- * @return An iterator to the beginning of the given bucket.
- */
- [[nodiscard]] const_local_iterator begin(const size_type index) const {
- return cbegin(index);
- }
- /**
- * @brief Returns an iterator to the beginning of a given bucket.
- * @param index An index of a bucket to access.
- * @return An iterator to the beginning of the given bucket.
- */
- [[nodiscard]] local_iterator begin(const size_type index) {
- return {packed.first().begin(), sparse.first()[index]};
- }
- /**
- * @brief Returns an iterator to the end of a given bucket.
- * @param index An index of a bucket to access.
- * @return An iterator to the end of the given bucket.
- */
- [[nodiscard]] const_local_iterator cend([[maybe_unused]] const size_type index) const {
- return {};
- }
- /**
- * @brief Returns an iterator to the end of a given bucket.
- * @param index An index of a bucket to access.
- * @return An iterator to the end of the given bucket.
- */
- [[nodiscard]] const_local_iterator end(const size_type index) const {
- return cend(index);
- }
- /**
- * @brief Returns an iterator to the end of a given bucket.
- * @param index An index of a bucket to access.
- * @return An iterator to the end of the given bucket.
- */
- [[nodiscard]] local_iterator end([[maybe_unused]] const size_type index) {
- return {};
- }
- /**
- * @brief Returns the number of buckets.
- * @return The number of buckets.
- */
- [[nodiscard]] size_type bucket_count() const {
- return sparse.first().size();
- }
- /**
- * @brief Returns the maximum number of buckets.
- * @return The maximum number of buckets.
- */
- [[nodiscard]] size_type max_bucket_count() const {
- return sparse.first().max_size();
- }
- /**
- * @brief Returns the number of elements in a given bucket.
- * @param index The index of the bucket to examine.
- * @return The number of elements in the given bucket.
- */
- [[nodiscard]] size_type bucket_size(const size_type index) const {
- return static_cast<size_type>(std::distance(begin(index), end(index)));
- }
- /**
- * @brief Returns the bucket for a given element.
- * @param value The value of the element to examine.
- * @return The bucket for the given element.
- */
- [[nodiscard]] size_type bucket(const value_type &value) const {
- return value_to_bucket(value);
- }
- /**
- * @brief Returns the average number of elements per bucket.
- * @return The average number of elements per bucket.
- */
- [[nodiscard]] float load_factor() const {
- return static_cast<float>(size()) / static_cast<float>(bucket_count());
- }
- /**
- * @brief Returns the maximum average number of elements per bucket.
- * @return The maximum average number of elements per bucket.
- */
- [[nodiscard]] float max_load_factor() const {
- return threshold;
- }
- /**
- * @brief Sets the desired maximum average number of elements per bucket.
- * @param value A desired maximum average number of elements per bucket.
- */
- void max_load_factor(const float value) {
- ENTT_ASSERT(value > 0.f, "Invalid load factor");
- threshold = value;
- rehash(0u);
- }
- /**
- * @brief Reserves at least the specified number of buckets and regenerates
- * the hash table.
- * @param cnt New number of buckets.
- */
- void rehash(const size_type cnt) {
- auto value = cnt > minimum_capacity ? cnt : minimum_capacity;
- const auto cap = static_cast<size_type>(static_cast<float>(size()) / max_load_factor());
- value = value > cap ? value : cap;
- if(const auto sz = next_power_of_two(value); sz != bucket_count()) {
- sparse.first().resize(sz);
- for(auto &&elem: sparse.first()) {
- elem = placeholder_position;
- }
- for(size_type pos{}, last = size(); pos < last; ++pos) {
- const auto index = value_to_bucket(packed.first()[pos].second);
- packed.first()[pos].first = std::exchange(sparse.first()[index], pos);
- }
- }
- }
- /**
- * @brief Reserves space for at least the specified number of elements and
- * regenerates the hash table.
- * @param cnt New number of elements.
- */
- void reserve(const size_type cnt) {
- packed.first().reserve(cnt);
- rehash(static_cast<size_type>(std::ceil(static_cast<float>(cnt) / max_load_factor())));
- }
- /**
- * @brief Returns the function used to hash the elements.
- * @return The function used to hash the elements.
- */
- [[nodiscard]] hasher hash_function() const {
- return sparse.second();
- }
- /**
- * @brief Returns the function used to compare elements for equality.
- * @return The function used to compare elements for equality.
- */
- [[nodiscard]] key_equal key_eq() const {
- return packed.second();
- }
- private:
- compressed_pair<sparse_container_type, hasher> sparse;
- compressed_pair<packed_container_type, key_equal> packed;
- float threshold{default_threshold};
- };
- } // namespace entt
- #endif
- // #include "../core/type_traits.hpp"
- #ifndef ENTT_CORE_TYPE_TRAITS_HPP
- #define ENTT_CORE_TYPE_TRAITS_HPP
- #include <cstddef>
- #include <iterator>
- #include <tuple>
- #include <type_traits>
- #include <utility>
- // #include "../config/config.h"
- #ifndef ENTT_CONFIG_CONFIG_H
- #define ENTT_CONFIG_CONFIG_H
- // #include "version.h"
- #ifndef ENTT_CONFIG_VERSION_H
- #define ENTT_CONFIG_VERSION_H
- // #include "macro.h"
- #ifndef ENTT_CONFIG_MACRO_H
- #define ENTT_CONFIG_MACRO_H
- // NOLINTBEGIN(cppcoreguidelines-macro-usage)
- #define ENTT_STR(arg) #arg
- #define ENTT_XSTR(arg) ENTT_STR(arg)
- // NOLINTEND(cppcoreguidelines-macro-usage)
- #endif
- // NOLINTBEGIN(cppcoreguidelines-macro-*,modernize-macro-*)
- #define ENTT_VERSION_MAJOR 3
- #define ENTT_VERSION_MINOR 16
- #define ENTT_VERSION_PATCH 0
- #define ENTT_VERSION \
- ENTT_XSTR(ENTT_VERSION_MAJOR) \
- "." ENTT_XSTR(ENTT_VERSION_MINOR) "." ENTT_XSTR(ENTT_VERSION_PATCH)
- // NOLINTEND(cppcoreguidelines-macro-*,modernize-macro-*)
- #endif
- // NOLINTBEGIN(cppcoreguidelines-macro-usage)
- #if defined(__cpp_exceptions) && !defined(ENTT_NOEXCEPTION)
- # define ENTT_CONSTEXPR
- # define ENTT_THROW throw
- # define ENTT_TRY try
- # define ENTT_CATCH catch(...)
- #else
- # define ENTT_CONSTEXPR constexpr // use only with throwing functions (waiting for C++20)
- # define ENTT_THROW
- # define ENTT_TRY if(true)
- # define ENTT_CATCH if(false)
- #endif
- #if __has_include(<version>)
- # include <version>
- #
- # if defined(__cpp_consteval)
- # define ENTT_CONSTEVAL consteval
- # endif
- #endif
- #ifndef ENTT_CONSTEVAL
- # define ENTT_CONSTEVAL constexpr
- #endif
- #ifdef ENTT_USE_ATOMIC
- # include <atomic>
- # define ENTT_MAYBE_ATOMIC(Type) std::atomic<Type>
- #else
- # define ENTT_MAYBE_ATOMIC(Type) Type
- #endif
- #ifndef ENTT_ID_TYPE
- # include <cstdint>
- # define ENTT_ID_TYPE std::uint32_t
- #else
- # include <cstdint> // provides coverage for types in the std namespace
- #endif
- #ifndef ENTT_SPARSE_PAGE
- # define ENTT_SPARSE_PAGE 4096
- #endif
- #ifndef ENTT_PACKED_PAGE
- # define ENTT_PACKED_PAGE 1024
- #endif
- #ifdef ENTT_DISABLE_ASSERT
- # undef ENTT_ASSERT
- # define ENTT_ASSERT(condition, msg) (void(0))
- #elif !defined ENTT_ASSERT
- # include <cassert>
- # define ENTT_ASSERT(condition, msg) assert(((condition) && (msg)))
- #endif
- #ifdef ENTT_DISABLE_ASSERT
- # undef ENTT_ASSERT_CONSTEXPR
- # define ENTT_ASSERT_CONSTEXPR(condition, msg) (void(0))
- #elif !defined ENTT_ASSERT_CONSTEXPR
- # define ENTT_ASSERT_CONSTEXPR(condition, msg) ENTT_ASSERT(condition, msg)
- #endif
- #define ENTT_FAIL(msg) ENTT_ASSERT(false, msg);
- #ifdef ENTT_NO_ETO
- # define ENTT_ETO_TYPE(Type) void
- #else
- # define ENTT_ETO_TYPE(Type) Type
- #endif
- #ifdef ENTT_NO_MIXIN
- # define ENTT_STORAGE(Mixin, ...) __VA_ARGS__
- #else
- # define ENTT_STORAGE(Mixin, ...) Mixin<__VA_ARGS__>
- #endif
- #ifdef ENTT_STANDARD_CPP
- # define ENTT_NONSTD false
- #else
- # define ENTT_NONSTD true
- # if defined __clang__ || defined __GNUC__
- # define ENTT_PRETTY_FUNCTION __PRETTY_FUNCTION__
- # define ENTT_PRETTY_FUNCTION_PREFIX '='
- # define ENTT_PRETTY_FUNCTION_SUFFIX ']'
- # elif defined _MSC_VER
- # define ENTT_PRETTY_FUNCTION __FUNCSIG__
- # define ENTT_PRETTY_FUNCTION_PREFIX '<'
- # define ENTT_PRETTY_FUNCTION_SUFFIX '>'
- # endif
- #endif
- #ifndef ENTT_EXPORT
- # if defined _WIN32 || defined __CYGWIN__ || defined _MSC_VER
- # define ENTT_EXPORT __declspec(dllexport)
- # define ENTT_IMPORT __declspec(dllimport)
- # define ENTT_HIDDEN
- # elif defined __GNUC__ && __GNUC__ >= 4
- # define ENTT_EXPORT __attribute__((visibility("default")))
- # define ENTT_IMPORT __attribute__((visibility("default")))
- # define ENTT_HIDDEN __attribute__((visibility("hidden")))
- # else /* Unsupported compiler */
- # define ENTT_EXPORT
- # define ENTT_IMPORT
- # define ENTT_HIDDEN
- # endif
- #endif
- #ifndef ENTT_API
- # if defined ENTT_API_EXPORT
- # define ENTT_API ENTT_EXPORT
- # elif defined ENTT_API_IMPORT
- # define ENTT_API ENTT_IMPORT
- # else /* No API */
- # define ENTT_API
- # endif
- #endif
- #if defined _MSC_VER
- # pragma detect_mismatch("entt.version", ENTT_VERSION)
- # pragma detect_mismatch("entt.noexcept", ENTT_XSTR(ENTT_TRY))
- # pragma detect_mismatch("entt.id", ENTT_XSTR(ENTT_ID_TYPE))
- # pragma detect_mismatch("entt.nonstd", ENTT_XSTR(ENTT_NONSTD))
- #endif
- // NOLINTEND(cppcoreguidelines-macro-usage)
- #endif
- // #include "fwd.hpp"
- #ifndef ENTT_CORE_FWD_HPP
- #define ENTT_CORE_FWD_HPP
- #include <cstddef>
- #include <cstdint>
- // #include "../config/config.h"
- namespace entt {
- /*! @brief Possible modes of an any object. */
- enum class any_policy : std::uint8_t {
- /*! @brief Default mode, no element available. */
- empty,
- /*! @brief Owning mode, dynamically allocated element. */
- dynamic,
- /*! @brief Owning mode, embedded element. */
- embedded,
- /*! @brief Aliasing mode, non-const reference. */
- ref,
- /*! @brief Const aliasing mode, const reference. */
- cref
- };
- // NOLINTNEXTLINE(cppcoreguidelines-avoid-c-arrays, modernize-avoid-c-arrays)
- template<std::size_t Len = sizeof(double[2]), std::size_t = alignof(double[2])>
- class basic_any;
- /*! @brief Alias declaration for type identifiers. */
- using id_type = ENTT_ID_TYPE;
- /*! @brief Alias declaration for the most common use case. */
- using any = basic_any<>;
- template<typename, typename>
- class compressed_pair;
- template<typename>
- class basic_hashed_string;
- /*! @brief Aliases for common character types. */
- using hashed_string = basic_hashed_string<char>;
- /*! @brief Aliases for common character types. */
- using hashed_wstring = basic_hashed_string<wchar_t>;
- // NOLINTNEXTLINE(bugprone-forward-declaration-namespace)
- struct type_info;
- } // namespace entt
- #endif
- namespace entt {
- /**
- * @brief Utility class to disambiguate overloaded functions.
- * @tparam N Number of choices available.
- */
- template<std::size_t N>
- struct choice_t
- // unfortunately, doxygen cannot parse such a construct
- : /*! @cond TURN_OFF_DOXYGEN */ choice_t<N - 1> /*! @endcond */
- {};
- /*! @copybrief choice_t */
- template<>
- struct choice_t<0> {};
- /**
- * @brief Variable template for the choice trick.
- * @tparam N Number of choices available.
- */
- template<std::size_t N>
- inline constexpr choice_t<N> choice{};
- /**
- * @brief Identity type trait.
- *
- * Useful to establish non-deduced contexts in template argument deduction
- * (waiting for C++20) or to provide types through function arguments.
- *
- * @tparam Type A type.
- */
- template<typename Type>
- struct type_identity {
- /*! @brief Identity type. */
- using type = Type;
- };
- /**
- * @brief Helper type.
- * @tparam Type A type.
- */
- template<typename Type>
- using type_identity_t = typename type_identity<Type>::type;
- /**
- * @brief A type-only `sizeof` wrapper that returns 0 where `sizeof` complains.
- * @tparam Type The type of which to return the size.
- */
- template<typename Type, typename = void>
- struct size_of: std::integral_constant<std::size_t, 0u> {};
- /*! @copydoc size_of */
- template<typename Type>
- struct size_of<Type, std::void_t<decltype(sizeof(Type))>>
- // NOLINTNEXTLINE(bugprone-sizeof-expression)
- : std::integral_constant<std::size_t, sizeof(Type)> {};
- /**
- * @brief Helper variable template.
- * @tparam Type The type of which to return the size.
- */
- template<typename Type>
- inline constexpr std::size_t size_of_v = size_of<Type>::value;
- /**
- * @brief Using declaration to be used to _repeat_ the same type a number of
- * times equal to the size of a given parameter pack.
- * @tparam Type A type to repeat.
- */
- template<typename Type, typename>
- using unpack_as_type = Type;
- /**
- * @brief Helper variable template to be used to _repeat_ the same value a
- * number of times equal to the size of a given parameter pack.
- * @tparam Value A value to repeat.
- */
- template<auto Value, typename>
- inline constexpr auto unpack_as_value = Value;
- /**
- * @brief Wraps a static constant.
- * @tparam Value A static constant.
- */
- template<auto Value>
- using integral_constant = std::integral_constant<decltype(Value), Value>;
- /**
- * @brief Alias template to facilitate the creation of named values.
- * @tparam Value A constant value at least convertible to `id_type`.
- */
- template<id_type Value>
- using tag = integral_constant<Value>;
- /**
- * @brief A class to use to push around lists of types, nothing more.
- * @tparam Type Types provided by the type list.
- */
- template<typename... Type>
- struct type_list {
- /*! @brief Type list type. */
- using type = type_list;
- /*! @brief Compile-time number of elements in the type list. */
- static constexpr auto size = sizeof...(Type);
- };
- /*! @brief Primary template isn't defined on purpose. */
- template<std::size_t, typename>
- struct type_list_element;
- /**
- * @brief Provides compile-time indexed access to the types of a type list.
- * @tparam Index Index of the type to return.
- * @tparam First First type provided by the type list.
- * @tparam Other Other types provided by the type list.
- */
- template<std::size_t Index, typename First, typename... Other>
- struct type_list_element<Index, type_list<First, Other...>>
- : type_list_element<Index - 1u, type_list<Other...>> {};
- /**
- * @brief Provides compile-time indexed access to the types of a type list.
- * @tparam First First type provided by the type list.
- * @tparam Other Other types provided by the type list.
- */
- template<typename First, typename... Other>
- struct type_list_element<0u, type_list<First, Other...>> {
- /*! @brief Searched type. */
- using type = First;
- };
- /**
- * @brief Helper type.
- * @tparam Index Index of the type to return.
- * @tparam List Type list to search into.
- */
- template<std::size_t Index, typename List>
- using type_list_element_t = typename type_list_element<Index, List>::type;
- /*! @brief Primary template isn't defined on purpose. */
- template<typename, typename>
- struct type_list_index;
- /**
- * @brief Provides compile-time type access to the types of a type list.
- * @tparam Type Type to look for and for which to return the index.
- * @tparam First First type provided by the type list.
- * @tparam Other Other types provided by the type list.
- */
- template<typename Type, typename First, typename... Other>
- struct type_list_index<Type, type_list<First, Other...>> {
- /*! @brief Unsigned integer type. */
- using value_type = std::size_t;
- /*! @brief Compile-time position of the given type in the sublist. */
- static constexpr value_type value = 1u + type_list_index<Type, type_list<Other...>>::value;
- };
- /**
- * @brief Provides compile-time type access to the types of a type list.
- * @tparam Type Type to look for and for which to return the index.
- * @tparam Other Other types provided by the type list.
- */
- template<typename Type, typename... Other>
- struct type_list_index<Type, type_list<Type, Other...>> {
- static_assert(type_list_index<Type, type_list<Other...>>::value == sizeof...(Other), "Non-unique type");
- /*! @brief Unsigned integer type. */
- using value_type = std::size_t;
- /*! @brief Compile-time position of the given type in the sublist. */
- static constexpr value_type value = 0u;
- };
- /**
- * @brief Provides compile-time type access to the types of a type list.
- * @tparam Type Type to look for and for which to return the index.
- */
- template<typename Type>
- struct type_list_index<Type, type_list<>> {
- /*! @brief Unsigned integer type. */
- using value_type = std::size_t;
- /*! @brief Compile-time position of the given type in the sublist. */
- static constexpr value_type value = 0u;
- };
- /**
- * @brief Helper variable template.
- * @tparam List Type list.
- * @tparam Type Type to look for and for which to return the index.
- */
- template<typename Type, typename List>
- inline constexpr std::size_t type_list_index_v = type_list_index<Type, List>::value;
- /**
- * @brief Concatenates multiple type lists.
- * @tparam Type Types provided by the first type list.
- * @tparam Other Types provided by the second type list.
- * @return A type list composed by the types of both the type lists.
- */
- template<typename... Type, typename... Other>
- constexpr type_list<Type..., Other...> operator+(type_list<Type...>, type_list<Other...>) {
- return {};
- }
- /*! @brief Primary template isn't defined on purpose. */
- template<typename...>
- struct type_list_cat;
- /*! @brief Concatenates multiple type lists. */
- template<>
- struct type_list_cat<> {
- /*! @brief A type list composed by the types of all the type lists. */
- using type = type_list<>;
- };
- /**
- * @brief Concatenates multiple type lists.
- * @tparam Type Types provided by the first type list.
- * @tparam Other Types provided by the second type list.
- * @tparam List Other type lists, if any.
- */
- template<typename... Type, typename... Other, typename... List>
- struct type_list_cat<type_list<Type...>, type_list<Other...>, List...> {
- /*! @brief A type list composed by the types of all the type lists. */
- using type = typename type_list_cat<type_list<Type..., Other...>, List...>::type;
- };
- /**
- * @brief Concatenates multiple type lists.
- * @tparam Type Types provided by the type list.
- */
- template<typename... Type>
- struct type_list_cat<type_list<Type...>> {
- /*! @brief A type list composed by the types of all the type lists. */
- using type = type_list<Type...>;
- };
- /**
- * @brief Helper type.
- * @tparam List Type lists to concatenate.
- */
- template<typename... List>
- using type_list_cat_t = typename type_list_cat<List...>::type;
- /*! @cond TURN_OFF_DOXYGEN */
- namespace internal {
- template<typename...>
- struct type_list_unique;
- template<typename First, typename... Other, typename... Type>
- struct type_list_unique<type_list<First, Other...>, Type...>
- : std::conditional_t<(std::is_same_v<First, Type> || ...), type_list_unique<type_list<Other...>, Type...>, type_list_unique<type_list<Other...>, Type..., First>> {};
- template<typename... Type>
- struct type_list_unique<type_list<>, Type...> {
- using type = type_list<Type...>;
- };
- } // namespace internal
- /*! @endcond */
- /**
- * @brief Removes duplicates types from a type list.
- * @tparam List Type list.
- */
- template<typename List>
- struct type_list_unique {
- /*! @brief A type list without duplicate types. */
- using type = typename internal::type_list_unique<List>::type;
- };
- /**
- * @brief Helper type.
- * @tparam List Type list.
- */
- template<typename List>
- using type_list_unique_t = typename type_list_unique<List>::type;
- /**
- * @brief Provides the member constant `value` to true if a type list contains a
- * given type, false otherwise.
- * @tparam List Type list.
- * @tparam Type Type to look for.
- */
- template<typename List, typename Type>
- struct type_list_contains;
- /**
- * @copybrief type_list_contains
- * @tparam Type Types provided by the type list.
- * @tparam Other Type to look for.
- */
- template<typename... Type, typename Other>
- struct type_list_contains<type_list<Type...>, Other>
- : std::bool_constant<(std::is_same_v<Type, Other> || ...)> {};
- /**
- * @brief Helper variable template.
- * @tparam List Type list.
- * @tparam Type Type to look for.
- */
- template<typename List, typename Type>
- inline constexpr bool type_list_contains_v = type_list_contains<List, Type>::value;
- /*! @brief Primary template isn't defined on purpose. */
- template<typename...>
- struct type_list_diff;
- /**
- * @brief Computes the difference between two type lists.
- * @tparam Type Types provided by the first type list.
- * @tparam Other Types provided by the second type list.
- */
- template<typename... Type, typename... Other>
- struct type_list_diff<type_list<Type...>, type_list<Other...>> {
- /*! @brief A type list that is the difference between the two type lists. */
- using type = type_list_cat_t<std::conditional_t<type_list_contains_v<type_list<Other...>, Type>, type_list<>, type_list<Type>>...>;
- };
- /**
- * @brief Helper type.
- * @tparam List Type lists between which to compute the difference.
- */
- template<typename... List>
- using type_list_diff_t = typename type_list_diff<List...>::type;
- /*! @brief Primary template isn't defined on purpose. */
- template<typename, template<typename...> class>
- struct type_list_transform;
- /**
- * @brief Applies a given _function_ to a type list and generate a new list.
- * @tparam Type Types provided by the type list.
- * @tparam Op Unary operation as template class with a type member named `type`.
- */
- template<typename... Type, template<typename...> class Op>
- struct type_list_transform<type_list<Type...>, Op> {
- /*! @brief Resulting type list after applying the transform function. */
- // NOLINTNEXTLINE(modernize-type-traits)
- using type = type_list<typename Op<Type>::type...>;
- };
- /**
- * @brief Helper type.
- * @tparam List Type list.
- * @tparam Op Unary operation as template class with a type member named `type`.
- */
- template<typename List, template<typename...> class Op>
- using type_list_transform_t = typename type_list_transform<List, Op>::type;
- /**
- * @brief A class to use to push around lists of constant values, nothing more.
- * @tparam Value Values provided by the value list.
- */
- template<auto... Value>
- struct value_list {
- /*! @brief Value list type. */
- using type = value_list;
- /*! @brief Compile-time number of elements in the value list. */
- static constexpr auto size = sizeof...(Value);
- };
- /*! @brief Primary template isn't defined on purpose. */
- template<std::size_t, typename>
- struct value_list_element;
- /**
- * @brief Provides compile-time indexed access to the values of a value list.
- * @tparam Index Index of the value to return.
- * @tparam Value First value provided by the value list.
- * @tparam Other Other values provided by the value list.
- */
- template<std::size_t Index, auto Value, auto... Other>
- struct value_list_element<Index, value_list<Value, Other...>>
- : value_list_element<Index - 1u, value_list<Other...>> {};
- /**
- * @brief Provides compile-time indexed access to the types of a type list.
- * @tparam Value First value provided by the value list.
- * @tparam Other Other values provided by the value list.
- */
- template<auto Value, auto... Other>
- struct value_list_element<0u, value_list<Value, Other...>> {
- /*! @brief Searched type. */
- using type = decltype(Value);
- /*! @brief Searched value. */
- static constexpr auto value = Value;
- };
- /**
- * @brief Helper type.
- * @tparam Index Index of the type to return.
- * @tparam List Value list to search into.
- */
- template<std::size_t Index, typename List>
- using value_list_element_t = typename value_list_element<Index, List>::type;
- /**
- * @brief Helper type.
- * @tparam Index Index of the value to return.
- * @tparam List Value list to search into.
- */
- template<std::size_t Index, typename List>
- inline constexpr auto value_list_element_v = value_list_element<Index, List>::value;
- /*! @brief Primary template isn't defined on purpose. */
- template<auto, typename>
- struct value_list_index;
- /**
- * @brief Provides compile-time type access to the values of a value list.
- * @tparam Value Value to look for and for which to return the index.
- * @tparam First First value provided by the value list.
- * @tparam Other Other values provided by the value list.
- */
- template<auto Value, auto First, auto... Other>
- struct value_list_index<Value, value_list<First, Other...>> {
- /*! @brief Unsigned integer type. */
- using value_type = std::size_t;
- /*! @brief Compile-time position of the given value in the sublist. */
- static constexpr value_type value = 1u + value_list_index<Value, value_list<Other...>>::value;
- };
- /**
- * @brief Provides compile-time type access to the values of a value list.
- * @tparam Value Value to look for and for which to return the index.
- * @tparam Other Other values provided by the value list.
- */
- template<auto Value, auto... Other>
- struct value_list_index<Value, value_list<Value, Other...>> {
- static_assert(value_list_index<Value, value_list<Other...>>::value == sizeof...(Other), "Non-unique type");
- /*! @brief Unsigned integer type. */
- using value_type = std::size_t;
- /*! @brief Compile-time position of the given value in the sublist. */
- static constexpr value_type value = 0u;
- };
- /**
- * @brief Provides compile-time type access to the values of a value list.
- * @tparam Value Value to look for and for which to return the index.
- */
- template<auto Value>
- struct value_list_index<Value, value_list<>> {
- /*! @brief Unsigned integer type. */
- using value_type = std::size_t;
- /*! @brief Compile-time position of the given type in the sublist. */
- static constexpr value_type value = 0u;
- };
- /**
- * @brief Helper variable template.
- * @tparam List Value list.
- * @tparam Value Value to look for and for which to return the index.
- */
- template<auto Value, typename List>
- inline constexpr std::size_t value_list_index_v = value_list_index<Value, List>::value;
- /**
- * @brief Concatenates multiple value lists.
- * @tparam Value Values provided by the first value list.
- * @tparam Other Values provided by the second value list.
- * @return A value list composed by the values of both the value lists.
- */
- template<auto... Value, auto... Other>
- constexpr value_list<Value..., Other...> operator+(value_list<Value...>, value_list<Other...>) {
- return {};
- }
- /*! @brief Primary template isn't defined on purpose. */
- template<typename...>
- struct value_list_cat;
- /*! @brief Concatenates multiple value lists. */
- template<>
- struct value_list_cat<> {
- /*! @brief A value list composed by the values of all the value lists. */
- using type = value_list<>;
- };
- /**
- * @brief Concatenates multiple value lists.
- * @tparam Value Values provided by the first value list.
- * @tparam Other Values provided by the second value list.
- * @tparam List Other value lists, if any.
- */
- template<auto... Value, auto... Other, typename... List>
- struct value_list_cat<value_list<Value...>, value_list<Other...>, List...> {
- /*! @brief A value list composed by the values of all the value lists. */
- using type = typename value_list_cat<value_list<Value..., Other...>, List...>::type;
- };
- /**
- * @brief Concatenates multiple value lists.
- * @tparam Value Values provided by the value list.
- */
- template<auto... Value>
- struct value_list_cat<value_list<Value...>> {
- /*! @brief A value list composed by the values of all the value lists. */
- using type = value_list<Value...>;
- };
- /**
- * @brief Helper type.
- * @tparam List Value lists to concatenate.
- */
- template<typename... List>
- using value_list_cat_t = typename value_list_cat<List...>::type;
- /*! @brief Primary template isn't defined on purpose. */
- template<typename>
- struct value_list_unique;
- /**
- * @brief Removes duplicates values from a value list.
- * @tparam Value One of the values provided by the given value list.
- * @tparam Other The other values provided by the given value list.
- */
- template<auto Value, auto... Other>
- struct value_list_unique<value_list<Value, Other...>> {
- /*! @brief A value list without duplicate types. */
- using type = std::conditional_t<
- ((Value == Other) || ...),
- typename value_list_unique<value_list<Other...>>::type,
- value_list_cat_t<value_list<Value>, typename value_list_unique<value_list<Other...>>::type>>;
- };
- /*! @brief Removes duplicates values from a value list. */
- template<>
- struct value_list_unique<value_list<>> {
- /*! @brief A value list without duplicate types. */
- using type = value_list<>;
- };
- /**
- * @brief Helper type.
- * @tparam Type A value list.
- */
- template<typename Type>
- using value_list_unique_t = typename value_list_unique<Type>::type;
- /**
- * @brief Provides the member constant `value` to true if a value list contains
- * a given value, false otherwise.
- * @tparam List Value list.
- * @tparam Value Value to look for.
- */
- template<typename List, auto Value>
- struct value_list_contains;
- /**
- * @copybrief value_list_contains
- * @tparam Value Values provided by the value list.
- * @tparam Other Value to look for.
- */
- template<auto... Value, auto Other>
- struct value_list_contains<value_list<Value...>, Other>
- : std::bool_constant<((Value == Other) || ...)> {};
- /**
- * @brief Helper variable template.
- * @tparam List Value list.
- * @tparam Value Value to look for.
- */
- template<typename List, auto Value>
- inline constexpr bool value_list_contains_v = value_list_contains<List, Value>::value;
- /*! @brief Primary template isn't defined on purpose. */
- template<typename...>
- struct value_list_diff;
- /**
- * @brief Computes the difference between two value lists.
- * @tparam Value Values provided by the first value list.
- * @tparam Other Values provided by the second value list.
- */
- template<auto... Value, auto... Other>
- struct value_list_diff<value_list<Value...>, value_list<Other...>> {
- /*! @brief A value list that is the difference between the two value lists. */
- using type = value_list_cat_t<std::conditional_t<value_list_contains_v<value_list<Other...>, Value>, value_list<>, value_list<Value>>...>;
- };
- /**
- * @brief Helper type.
- * @tparam List Value lists between which to compute the difference.
- */
- template<typename... List>
- using value_list_diff_t = typename value_list_diff<List...>::type;
- /*! @brief Same as std::is_invocable, but with tuples. */
- template<typename, typename>
- struct is_applicable: std::false_type {};
- /**
- * @copybrief is_applicable
- * @tparam Func A valid function type.
- * @tparam Tuple Tuple-like type.
- * @tparam Args The list of arguments to use to probe the function type.
- */
- template<typename Func, template<typename...> class Tuple, typename... Args>
- struct is_applicable<Func, Tuple<Args...>>: std::is_invocable<Func, Args...> {};
- /**
- * @copybrief is_applicable
- * @tparam Func A valid function type.
- * @tparam Tuple Tuple-like type.
- * @tparam Args The list of arguments to use to probe the function type.
- */
- template<typename Func, template<typename...> class Tuple, typename... Args>
- struct is_applicable<Func, const Tuple<Args...>>: std::is_invocable<Func, Args...> {};
- /**
- * @brief Helper variable template.
- * @tparam Func A valid function type.
- * @tparam Args The list of arguments to use to probe the function type.
- */
- template<typename Func, typename Args>
- inline constexpr bool is_applicable_v = is_applicable<Func, Args>::value;
- /*! @brief Same as std::is_invocable_r, but with tuples for arguments. */
- template<typename, typename, typename>
- struct is_applicable_r: std::false_type {};
- /**
- * @copybrief is_applicable_r
- * @tparam Ret The type to which the return type of the function should be
- * convertible.
- * @tparam Func A valid function type.
- * @tparam Args The list of arguments to use to probe the function type.
- */
- template<typename Ret, typename Func, typename... Args>
- struct is_applicable_r<Ret, Func, std::tuple<Args...>>: std::is_invocable_r<Ret, Func, Args...> {};
- /**
- * @brief Helper variable template.
- * @tparam Ret The type to which the return type of the function should be
- * convertible.
- * @tparam Func A valid function type.
- * @tparam Args The list of arguments to use to probe the function type.
- */
- template<typename Ret, typename Func, typename Args>
- inline constexpr bool is_applicable_r_v = is_applicable_r<Ret, Func, Args>::value;
- /**
- * @brief Provides the member constant `value` to true if a given type is
- * complete, false otherwise.
- * @tparam Type The type to test.
- */
- template<typename Type, typename = void>
- struct is_complete: std::false_type {};
- /*! @copydoc is_complete */
- template<typename Type>
- struct is_complete<Type, std::void_t<decltype(sizeof(Type))>>: std::true_type {};
- /**
- * @brief Helper variable template.
- * @tparam Type The type to test.
- */
- template<typename Type>
- inline constexpr bool is_complete_v = is_complete<Type>::value;
- /**
- * @brief Provides the member constant `value` to true if a given type is an
- * iterator, false otherwise.
- * @tparam Type The type to test.
- */
- template<typename Type, typename = void>
- struct is_iterator: std::false_type {};
- /*! @cond TURN_OFF_DOXYGEN */
- namespace internal {
- template<typename, typename = void>
- struct has_iterator_category: std::false_type {};
- template<typename Type>
- struct has_iterator_category<Type, std::void_t<typename std::iterator_traits<Type>::iterator_category>>: std::true_type {};
- } // namespace internal
- /*! @endcond */
- /*! @copydoc is_iterator */
- template<typename Type>
- struct is_iterator<Type, std::enable_if_t<!std::is_void_v<std::remove_const_t<std::remove_pointer_t<Type>>>>>
- : internal::has_iterator_category<Type> {};
- /**
- * @brief Helper variable template.
- * @tparam Type The type to test.
- */
- template<typename Type>
- inline constexpr bool is_iterator_v = is_iterator<Type>::value;
- /**
- * @brief Provides the member constant `value` to true if a given type is both
- * an empty and non-final class, false otherwise.
- * @tparam Type The type to test
- */
- template<typename Type>
- struct is_ebco_eligible
- : std::bool_constant<std::is_empty_v<Type> && !std::is_final_v<Type>> {};
- /**
- * @brief Helper variable template.
- * @tparam Type The type to test.
- */
- template<typename Type>
- inline constexpr bool is_ebco_eligible_v = is_ebco_eligible<Type>::value;
- /**
- * @brief Provides the member constant `value` to true if `Type::is_transparent`
- * is valid and denotes a type, false otherwise.
- * @tparam Type The type to test.
- */
- template<typename Type, typename = void>
- struct is_transparent: std::false_type {};
- /*! @copydoc is_transparent */
- template<typename Type>
- struct is_transparent<Type, std::void_t<typename Type::is_transparent>>: std::true_type {};
- /**
- * @brief Helper variable template.
- * @tparam Type The type to test.
- */
- template<typename Type>
- inline constexpr bool is_transparent_v = is_transparent<Type>::value;
- /*! @cond TURN_OFF_DOXYGEN */
- namespace internal {
- template<typename, typename = void>
- struct has_tuple_size_value: std::false_type {};
- template<typename Type>
- struct has_tuple_size_value<Type, std::void_t<decltype(std::tuple_size<const Type>::value)>>: std::true_type {};
- template<typename, typename = void>
- struct has_value_type: std::false_type {};
- template<typename Type>
- struct has_value_type<Type, std::void_t<typename Type::value_type>>: std::true_type {};
- template<typename>
- [[nodiscard]] constexpr bool dispatch_is_equality_comparable();
- template<typename Type, std::size_t... Index>
- [[nodiscard]] constexpr bool unpack_maybe_equality_comparable(std::index_sequence<Index...>) {
- return (dispatch_is_equality_comparable<std::tuple_element_t<Index, Type>>() && ...);
- }
- template<typename>
- [[nodiscard]] constexpr bool maybe_equality_comparable(char) {
- return false;
- }
- template<typename Type>
- [[nodiscard]] constexpr auto maybe_equality_comparable(int) -> decltype(std::declval<Type>() == std::declval<Type>()) {
- return true;
- }
- template<typename Type>
- [[nodiscard]] constexpr bool dispatch_is_equality_comparable() {
- // NOLINTBEGIN(modernize-use-transparent-functors)
- if constexpr(std::is_array_v<Type>) {
- return false;
- } else if constexpr(is_complete_v<std::tuple_size<std::remove_const_t<Type>>>) {
- if constexpr(has_tuple_size_value<Type>::value) {
- return maybe_equality_comparable<Type>(0) && unpack_maybe_equality_comparable<Type>(std::make_index_sequence<std::tuple_size<Type>::value>{});
- } else {
- return maybe_equality_comparable<Type>(0);
- }
- } else if constexpr(has_value_type<Type>::value) {
- if constexpr(is_iterator_v<Type> || std::is_same_v<typename Type::value_type, Type> || dispatch_is_equality_comparable<typename Type::value_type>()) {
- return maybe_equality_comparable<Type>(0);
- } else {
- return false;
- }
- } else {
- return maybe_equality_comparable<Type>(0);
- }
- // NOLINTEND(modernize-use-transparent-functors)
- }
- } // namespace internal
- /*! @endcond */
- /**
- * @brief Provides the member constant `value` to true if a given type is
- * equality comparable, false otherwise.
- * @tparam Type The type to test.
- */
- template<typename Type>
- struct is_equality_comparable: std::bool_constant<internal::dispatch_is_equality_comparable<Type>()> {};
- /*! @copydoc is_equality_comparable */
- template<typename Type>
- struct is_equality_comparable<const Type>: is_equality_comparable<Type> {};
- /**
- * @brief Helper variable template.
- * @tparam Type The type to test.
- */
- template<typename Type>
- inline constexpr bool is_equality_comparable_v = is_equality_comparable<Type>::value;
- /**
- * @brief Transcribes the constness of a type to another type.
- * @tparam To The type to which to transcribe the constness.
- * @tparam From The type from which to transcribe the constness.
- */
- template<typename To, typename From>
- struct constness_as {
- /*! @brief The type resulting from the transcription of the constness. */
- using type = std::remove_const_t<To>;
- };
- /*! @copydoc constness_as */
- template<typename To, typename From>
- struct constness_as<To, const From> {
- /*! @brief The type resulting from the transcription of the constness. */
- using type = const To;
- };
- /**
- * @brief Alias template to facilitate the transcription of the constness.
- * @tparam To The type to which to transcribe the constness.
- * @tparam From The type from which to transcribe the constness.
- */
- template<typename To, typename From>
- using constness_as_t = typename constness_as<To, From>::type;
- /**
- * @brief Extracts the class of a non-static member object or function.
- * @tparam Member A pointer to a non-static member object or function.
- */
- template<typename Member>
- class member_class {
- static_assert(std::is_member_pointer_v<Member>, "Invalid pointer type to non-static member object or function");
- template<typename Class, typename Ret, typename... Args>
- static Class *clazz(Ret (Class::*)(Args...));
- template<typename Class, typename Ret, typename... Args>
- static Class *clazz(Ret (Class::*)(Args...) const);
- template<typename Class, typename Type>
- static Class *clazz(Type Class::*);
- public:
- /*! @brief The class of the given non-static member object or function. */
- using type = std::remove_pointer_t<decltype(clazz(std::declval<Member>()))>;
- };
- /**
- * @brief Helper type.
- * @tparam Member A pointer to a non-static member object or function.
- */
- template<typename Member>
- using member_class_t = typename member_class<Member>::type;
- /**
- * @brief Extracts the n-th argument of a _callable_ type.
- * @tparam Index The index of the argument to extract.
- * @tparam Candidate A valid _callable_ type.
- */
- template<std::size_t Index, typename Candidate>
- class nth_argument {
- template<typename Ret, typename... Args>
- static constexpr type_list<Args...> pick_up(Ret (*)(Args...));
- template<typename Ret, typename Class, typename... Args>
- static constexpr type_list<Args...> pick_up(Ret (Class ::*)(Args...));
- template<typename Ret, typename Class, typename... Args>
- static constexpr type_list<Args...> pick_up(Ret (Class ::*)(Args...) const);
- template<typename Type, typename Class>
- static constexpr type_list<Type> pick_up(Type Class ::*);
- template<typename Type>
- static constexpr decltype(pick_up(&Type::operator())) pick_up(Type &&);
- public:
- /*! @brief N-th argument of the _callable_ type. */
- using type = type_list_element_t<Index, decltype(pick_up(std::declval<Candidate>()))>;
- };
- /**
- * @brief Helper type.
- * @tparam Index The index of the argument to extract.
- * @tparam Candidate A valid function, member function or data member type.
- */
- template<std::size_t Index, typename Candidate>
- using nth_argument_t = typename nth_argument<Index, Candidate>::type;
- } // namespace entt
- template<typename... Type>
- struct std::tuple_size<entt::type_list<Type...>>: std::integral_constant<std::size_t, entt::type_list<Type...>::size> {};
- template<std::size_t Index, typename... Type>
- struct std::tuple_element<Index, entt::type_list<Type...>>: entt::type_list_element<Index, entt::type_list<Type...>> {};
- template<auto... Value>
- struct std::tuple_size<entt::value_list<Value...>>: std::integral_constant<std::size_t, entt::value_list<Value...>::size> {};
- template<std::size_t Index, auto... Value>
- struct std::tuple_element<Index, entt::value_list<Value...>>: entt::value_list_element<Index, entt::value_list<Value...>> {};
- #endif
- // #include "context.hpp"
- #ifndef ENTT_META_CTX_HPP
- #define ENTT_META_CTX_HPP
- #include <memory>
- // #include "../container/dense_map.hpp"
- // #include "../core/fwd.hpp"
- #ifndef ENTT_CORE_FWD_HPP
- #define ENTT_CORE_FWD_HPP
- #include <cstddef>
- #include <cstdint>
- // #include "../config/config.h"
- namespace entt {
- /*! @brief Possible modes of an any object. */
- enum class any_policy : std::uint8_t {
- /*! @brief Default mode, no element available. */
- empty,
- /*! @brief Owning mode, dynamically allocated element. */
- dynamic,
- /*! @brief Owning mode, embedded element. */
- embedded,
- /*! @brief Aliasing mode, non-const reference. */
- ref,
- /*! @brief Const aliasing mode, const reference. */
- cref
- };
- // NOLINTNEXTLINE(cppcoreguidelines-avoid-c-arrays, modernize-avoid-c-arrays)
- template<std::size_t Len = sizeof(double[2]), std::size_t = alignof(double[2])>
- class basic_any;
- /*! @brief Alias declaration for type identifiers. */
- using id_type = ENTT_ID_TYPE;
- /*! @brief Alias declaration for the most common use case. */
- using any = basic_any<>;
- template<typename, typename>
- class compressed_pair;
- template<typename>
- class basic_hashed_string;
- /*! @brief Aliases for common character types. */
- using hashed_string = basic_hashed_string<char>;
- /*! @brief Aliases for common character types. */
- using hashed_wstring = basic_hashed_string<wchar_t>;
- // NOLINTNEXTLINE(bugprone-forward-declaration-namespace)
- struct type_info;
- } // namespace entt
- #endif
- // #include "../core/utility.hpp"
- #ifndef ENTT_CORE_UTILITY_HPP
- #define ENTT_CORE_UTILITY_HPP
- #include <type_traits>
- #include <utility>
- namespace entt {
- /*! @brief Identity function object (waiting for C++20). */
- struct identity {
- /*! @brief Indicates that this is a transparent function object. */
- using is_transparent = void;
- /**
- * @brief Returns its argument unchanged.
- * @tparam Type Type of the argument.
- * @param value The actual argument.
- * @return The submitted value as-is.
- */
- template<typename Type>
- [[nodiscard]] constexpr Type &&operator()(Type &&value) const noexcept {
- return std::forward<Type>(value);
- }
- };
- /**
- * @brief Constant utility to disambiguate overloaded members of a class.
- * @tparam Type Type of the desired overload.
- * @tparam Class Type of class to which the member belongs.
- * @param member A valid pointer to a member.
- * @return Pointer to the member.
- */
- template<typename Type, typename Class>
- [[nodiscard]] constexpr auto overload(Type Class::*member) noexcept {
- return member;
- }
- /**
- * @brief Constant utility to disambiguate overloaded functions.
- * @tparam Func Function type of the desired overload.
- * @param func A valid pointer to a function.
- * @return Pointer to the function.
- */
- template<typename Func>
- [[nodiscard]] constexpr auto overload(Func *func) noexcept {
- return func;
- }
- /**
- * @brief Helper type for visitors.
- * @tparam Func Types of function objects.
- */
- template<typename... Func>
- struct overloaded: Func... {
- using Func::operator()...;
- };
- /**
- * @brief Deduction guide.
- * @tparam Func Types of function objects.
- */
- template<typename... Func>
- overloaded(Func...) -> overloaded<Func...>;
- /**
- * @brief Basic implementation of a y-combinator.
- * @tparam Func Type of a potentially recursive function.
- */
- template<typename Func>
- struct y_combinator {
- /**
- * @brief Constructs a y-combinator from a given function.
- * @param recursive A potentially recursive function.
- */
- constexpr y_combinator(Func recursive) noexcept(std::is_nothrow_move_constructible_v<Func>)
- : func{std::move(recursive)} {}
- /**
- * @brief Invokes a y-combinator and therefore its underlying function.
- * @tparam Args Types of arguments to use to invoke the underlying function.
- * @param args Parameters to use to invoke the underlying function.
- * @return Return value of the underlying function, if any.
- */
- template<typename... Args>
- constexpr decltype(auto) operator()(Args &&...args) const noexcept(std::is_nothrow_invocable_v<Func, const y_combinator &, Args...>) {
- return func(*this, std::forward<Args>(args)...);
- }
- /*! @copydoc operator()() */
- template<typename... Args>
- constexpr decltype(auto) operator()(Args &&...args) noexcept(std::is_nothrow_invocable_v<Func, y_combinator &, Args...>) {
- return func(*this, std::forward<Args>(args)...);
- }
- private:
- Func func;
- };
- } // namespace entt
- #endif
- // #include "fwd.hpp"
- #ifndef ENTT_META_FWD_HPP
- #define ENTT_META_FWD_HPP
- #include <cstddef>
- #include <limits>
- namespace entt {
- class meta_ctx;
- class meta_sequence_container;
- class meta_associative_container;
- class meta_any;
- class meta_handle;
- struct meta_custom;
- class meta_data;
- class meta_func;
- class meta_type;
- template<typename>
- class meta_factory;
- /*! @brief Used to identicate that a sequence container has not a fixed size. */
- inline constexpr std::size_t meta_dynamic_extent = (std::numeric_limits<std::size_t>::max)();
- } // namespace entt
- #endif
- namespace entt {
- /*! @cond TURN_OFF_DOXYGEN */
- namespace internal {
- struct meta_type_node;
- struct meta_context {
- dense_map<id_type, std::unique_ptr<meta_type_node>, identity> value;
- [[nodiscard]] inline static meta_context &from(meta_ctx &);
- [[nodiscard]] inline static const meta_context &from(const meta_ctx &);
- };
- } // namespace internal
- /*! @endcond */
- /*! @brief Disambiguation tag for constructors and the like. */
- class meta_ctx_arg_t final {};
- /*! @brief Constant of type meta_context_arg_t used to disambiguate calls. */
- inline constexpr meta_ctx_arg_t meta_ctx_arg{};
- /*! @brief Opaque meta context type. */
- class meta_ctx: private internal::meta_context {
- // attorney idiom like model to access the base class
- friend struct internal::meta_context;
- };
- /*! @cond TURN_OFF_DOXYGEN */
- [[nodiscard]] inline internal::meta_context &internal::meta_context::from(meta_ctx &ctx) {
- return ctx;
- }
- [[nodiscard]] inline const internal::meta_context &internal::meta_context::from(const meta_ctx &ctx) {
- return ctx;
- }
- /*! @endcond */
- } // namespace entt
- #endif
- // #include "fwd.hpp"
- // #include "meta.hpp"
- #ifndef ENTT_META_META_HPP
- #define ENTT_META_META_HPP
- #include <array>
- #include <cstddef>
- #include <iterator>
- #include <memory>
- #include <type_traits>
- #include <utility>
- // #include "../config/config.h"
- #ifndef ENTT_CONFIG_CONFIG_H
- #define ENTT_CONFIG_CONFIG_H
- // #include "version.h"
- #ifndef ENTT_CONFIG_VERSION_H
- #define ENTT_CONFIG_VERSION_H
- // #include "macro.h"
- #ifndef ENTT_CONFIG_MACRO_H
- #define ENTT_CONFIG_MACRO_H
- // NOLINTBEGIN(cppcoreguidelines-macro-usage)
- #define ENTT_STR(arg) #arg
- #define ENTT_XSTR(arg) ENTT_STR(arg)
- // NOLINTEND(cppcoreguidelines-macro-usage)
- #endif
- // NOLINTBEGIN(cppcoreguidelines-macro-*,modernize-macro-*)
- #define ENTT_VERSION_MAJOR 3
- #define ENTT_VERSION_MINOR 16
- #define ENTT_VERSION_PATCH 0
- #define ENTT_VERSION \
- ENTT_XSTR(ENTT_VERSION_MAJOR) \
- "." ENTT_XSTR(ENTT_VERSION_MINOR) "." ENTT_XSTR(ENTT_VERSION_PATCH)
- // NOLINTEND(cppcoreguidelines-macro-*,modernize-macro-*)
- #endif
- // NOLINTBEGIN(cppcoreguidelines-macro-usage)
- #if defined(__cpp_exceptions) && !defined(ENTT_NOEXCEPTION)
- # define ENTT_CONSTEXPR
- # define ENTT_THROW throw
- # define ENTT_TRY try
- # define ENTT_CATCH catch(...)
- #else
- # define ENTT_CONSTEXPR constexpr // use only with throwing functions (waiting for C++20)
- # define ENTT_THROW
- # define ENTT_TRY if(true)
- # define ENTT_CATCH if(false)
- #endif
- #if __has_include(<version>)
- # include <version>
- #
- # if defined(__cpp_consteval)
- # define ENTT_CONSTEVAL consteval
- # endif
- #endif
- #ifndef ENTT_CONSTEVAL
- # define ENTT_CONSTEVAL constexpr
- #endif
- #ifdef ENTT_USE_ATOMIC
- # include <atomic>
- # define ENTT_MAYBE_ATOMIC(Type) std::atomic<Type>
- #else
- # define ENTT_MAYBE_ATOMIC(Type) Type
- #endif
- #ifndef ENTT_ID_TYPE
- # include <cstdint>
- # define ENTT_ID_TYPE std::uint32_t
- #else
- # include <cstdint> // provides coverage for types in the std namespace
- #endif
- #ifndef ENTT_SPARSE_PAGE
- # define ENTT_SPARSE_PAGE 4096
- #endif
- #ifndef ENTT_PACKED_PAGE
- # define ENTT_PACKED_PAGE 1024
- #endif
- #ifdef ENTT_DISABLE_ASSERT
- # undef ENTT_ASSERT
- # define ENTT_ASSERT(condition, msg) (void(0))
- #elif !defined ENTT_ASSERT
- # include <cassert>
- # define ENTT_ASSERT(condition, msg) assert(((condition) && (msg)))
- #endif
- #ifdef ENTT_DISABLE_ASSERT
- # undef ENTT_ASSERT_CONSTEXPR
- # define ENTT_ASSERT_CONSTEXPR(condition, msg) (void(0))
- #elif !defined ENTT_ASSERT_CONSTEXPR
- # define ENTT_ASSERT_CONSTEXPR(condition, msg) ENTT_ASSERT(condition, msg)
- #endif
- #define ENTT_FAIL(msg) ENTT_ASSERT(false, msg);
- #ifdef ENTT_NO_ETO
- # define ENTT_ETO_TYPE(Type) void
- #else
- # define ENTT_ETO_TYPE(Type) Type
- #endif
- #ifdef ENTT_NO_MIXIN
- # define ENTT_STORAGE(Mixin, ...) __VA_ARGS__
- #else
- # define ENTT_STORAGE(Mixin, ...) Mixin<__VA_ARGS__>
- #endif
- #ifdef ENTT_STANDARD_CPP
- # define ENTT_NONSTD false
- #else
- # define ENTT_NONSTD true
- # if defined __clang__ || defined __GNUC__
- # define ENTT_PRETTY_FUNCTION __PRETTY_FUNCTION__
- # define ENTT_PRETTY_FUNCTION_PREFIX '='
- # define ENTT_PRETTY_FUNCTION_SUFFIX ']'
- # elif defined _MSC_VER
- # define ENTT_PRETTY_FUNCTION __FUNCSIG__
- # define ENTT_PRETTY_FUNCTION_PREFIX '<'
- # define ENTT_PRETTY_FUNCTION_SUFFIX '>'
- # endif
- #endif
- #ifndef ENTT_EXPORT
- # if defined _WIN32 || defined __CYGWIN__ || defined _MSC_VER
- # define ENTT_EXPORT __declspec(dllexport)
- # define ENTT_IMPORT __declspec(dllimport)
- # define ENTT_HIDDEN
- # elif defined __GNUC__ && __GNUC__ >= 4
- # define ENTT_EXPORT __attribute__((visibility("default")))
- # define ENTT_IMPORT __attribute__((visibility("default")))
- # define ENTT_HIDDEN __attribute__((visibility("hidden")))
- # else /* Unsupported compiler */
- # define ENTT_EXPORT
- # define ENTT_IMPORT
- # define ENTT_HIDDEN
- # endif
- #endif
- #ifndef ENTT_API
- # if defined ENTT_API_EXPORT
- # define ENTT_API ENTT_EXPORT
- # elif defined ENTT_API_IMPORT
- # define ENTT_API ENTT_IMPORT
- # else /* No API */
- # define ENTT_API
- # endif
- #endif
- #if defined _MSC_VER
- # pragma detect_mismatch("entt.version", ENTT_VERSION)
- # pragma detect_mismatch("entt.noexcept", ENTT_XSTR(ENTT_TRY))
- # pragma detect_mismatch("entt.id", ENTT_XSTR(ENTT_ID_TYPE))
- # pragma detect_mismatch("entt.nonstd", ENTT_XSTR(ENTT_NONSTD))
- #endif
- // NOLINTEND(cppcoreguidelines-macro-usage)
- #endif
- // #include "../core/any.hpp"
- #ifndef ENTT_CORE_ANY_HPP
- #define ENTT_CORE_ANY_HPP
- #include <cstddef>
- #include <memory>
- #include <type_traits>
- #include <utility>
- // #include "../config/config.h"
- // #include "fwd.hpp"
- // #include "type_info.hpp"
- #ifndef ENTT_CORE_TYPE_INFO_HPP
- #define ENTT_CORE_TYPE_INFO_HPP
- #include <string_view>
- #include <type_traits>
- #include <utility>
- // #include "../config/config.h"
- // #include "fwd.hpp"
- // #include "hashed_string.hpp"
- #ifndef ENTT_CORE_HASHED_STRING_HPP
- #define ENTT_CORE_HASHED_STRING_HPP
- #include <cstddef>
- #include <cstdint>
- // #include "fwd.hpp"
- namespace entt {
- /*! @cond TURN_OFF_DOXYGEN */
- namespace internal {
- template<typename = id_type>
- struct fnv_1a_params;
- template<>
- struct fnv_1a_params<std::uint32_t> {
- static constexpr auto offset = 2166136261;
- static constexpr auto prime = 16777619;
- };
- template<>
- struct fnv_1a_params<std::uint64_t> {
- static constexpr auto offset = 14695981039346656037ull;
- static constexpr auto prime = 1099511628211ull;
- };
- template<typename Char>
- struct basic_hashed_string {
- using value_type = Char;
- using size_type = std::size_t;
- using hash_type = id_type;
- const value_type *repr{};
- hash_type hash{fnv_1a_params<>::offset};
- size_type length{};
- };
- } // namespace internal
- /*! @endcond */
- /**
- * @brief Zero overhead unique identifier.
- *
- * A hashed string is a compile-time tool that allows users to use
- * human-readable identifiers in the codebase while using their numeric
- * counterparts at runtime.<br/>
- * Because of that, a hashed string can also be used in constant expressions if
- * required.
- *
- * @warning
- * This class doesn't take ownership of user-supplied strings nor does it make a
- * copy of them.
- *
- * @tparam Char Character type.
- */
- template<typename Char>
- class basic_hashed_string: internal::basic_hashed_string<Char> {
- using base_type = internal::basic_hashed_string<Char>;
- using params = internal::fnv_1a_params<>;
- struct const_wrapper {
- // non-explicit constructor on purpose
- constexpr const_wrapper(const typename base_type::value_type *str) noexcept
- : repr{str} {}
- const typename base_type::value_type *repr;
- };
- public:
- /*! @brief Character type. */
- using value_type = typename base_type::value_type;
- /*! @brief Unsigned integer type. */
- using size_type = typename base_type::size_type;
- /*! @brief Unsigned integer type. */
- using hash_type = typename base_type::hash_type;
- /**
- * @brief Returns directly the numeric representation of a string view.
- * @param str Human-readable identifier.
- * @param len Length of the string to hash.
- * @return The numeric representation of the string.
- */
- [[nodiscard]] static constexpr hash_type value(const value_type *str, const size_type len) noexcept {
- return basic_hashed_string{str, len};
- }
- /**
- * @brief Returns directly the numeric representation of a string.
- * @tparam N Number of characters of the identifier.
- * @param str Human-readable identifier.
- * @return The numeric representation of the string.
- */
- template<std::size_t N>
- // NOLINTNEXTLINE(cppcoreguidelines-avoid-c-arrays, modernize-avoid-c-arrays)
- [[nodiscard]] static ENTT_CONSTEVAL hash_type value(const value_type (&str)[N]) noexcept {
- return basic_hashed_string{str};
- }
- /**
- * @brief Returns directly the numeric representation of a string.
- * @param wrapper Helps achieving the purpose by relying on overloading.
- * @return The numeric representation of the string.
- */
- [[nodiscard]] static constexpr hash_type value(const_wrapper wrapper) noexcept {
- return basic_hashed_string{wrapper};
- }
- /*! @brief Constructs an empty hashed string. */
- constexpr basic_hashed_string() noexcept
- : basic_hashed_string{nullptr, 0u} {}
- /**
- * @brief Constructs a hashed string from a string view.
- * @param str Human-readable identifier.
- * @param len Length of the string to hash.
- */
- constexpr basic_hashed_string(const value_type *str, const size_type len) noexcept
- // NOLINTNEXTLINE(cppcoreguidelines-pro-bounds-array-to-pointer-decay)
- : base_type{str} {
- // NOLINTBEGIN(cppcoreguidelines-pro-bounds-pointer-arithmetic)
- for(; base_type::length < len; ++base_type::length) {
- base_type::hash = (base_type::hash ^ static_cast<id_type>(str[base_type::length])) * params::prime;
- }
- // NOLINTEND(cppcoreguidelines-pro-bounds-pointer-arithmetic)
- }
- /**
- * @brief Constructs a hashed string from an array of const characters.
- * @tparam N Number of characters of the identifier.
- * @param str Human-readable identifier.
- */
- template<std::size_t N>
- // NOLINTNEXTLINE(cppcoreguidelines-avoid-c-arrays, modernize-avoid-c-arrays)
- ENTT_CONSTEVAL basic_hashed_string(const value_type (&str)[N]) noexcept
- // NOLINTNEXTLINE(cppcoreguidelines-pro-bounds-array-to-pointer-decay)
- : base_type{str} {
- for(; str[base_type::length]; ++base_type::length) {
- base_type::hash = (base_type::hash ^ static_cast<id_type>(str[base_type::length])) * params::prime;
- }
- }
- /**
- * @brief Explicit constructor on purpose to avoid constructing a hashed
- * string directly from a `const value_type *`.
- *
- * @warning
- * The lifetime of the string is not extended nor is it copied.
- *
- * @param wrapper Helps achieving the purpose by relying on overloading.
- */
- explicit constexpr basic_hashed_string(const_wrapper wrapper) noexcept
- : base_type{wrapper.repr} {
- // NOLINTBEGIN(cppcoreguidelines-pro-bounds-pointer-arithmetic)
- for(; wrapper.repr[base_type::length]; ++base_type::length) {
- base_type::hash = (base_type::hash ^ static_cast<id_type>(wrapper.repr[base_type::length])) * params::prime;
- }
- // NOLINTEND(cppcoreguidelines-pro-bounds-pointer-arithmetic)
- }
- /**
- * @brief Returns the size of a hashed string.
- * @return The size of the hashed string.
- */
- [[nodiscard]] constexpr size_type size() const noexcept {
- return base_type::length;
- }
- /**
- * @brief Returns the human-readable representation of a hashed string.
- * @return The string used to initialize the hashed string.
- */
- [[nodiscard]] constexpr const value_type *data() const noexcept {
- return base_type::repr;
- }
- /**
- * @brief Returns the numeric representation of a hashed string.
- * @return The numeric representation of the hashed string.
- */
- [[nodiscard]] constexpr hash_type value() const noexcept {
- return base_type::hash;
- }
- /*! @copydoc data */
- [[nodiscard]] explicit constexpr operator const value_type *() const noexcept {
- return data();
- }
- /**
- * @brief Returns the numeric representation of a hashed string.
- * @return The numeric representation of the hashed string.
- */
- [[nodiscard]] constexpr operator hash_type() const noexcept {
- return value();
- }
- };
- /**
- * @brief Deduction guide.
- * @tparam Char Character type.
- * @param str Human-readable identifier.
- * @param len Length of the string to hash.
- */
- template<typename Char>
- basic_hashed_string(const Char *str, std::size_t len) -> basic_hashed_string<Char>;
- /**
- * @brief Deduction guide.
- * @tparam Char Character type.
- * @tparam N Number of characters of the identifier.
- * @param str Human-readable identifier.
- */
- template<typename Char, std::size_t N>
- // NOLINTNEXTLINE(cppcoreguidelines-avoid-c-arrays, modernize-avoid-c-arrays)
- basic_hashed_string(const Char (&str)[N]) -> basic_hashed_string<Char>;
- /**
- * @brief Compares two hashed strings.
- * @tparam Char Character type.
- * @param lhs A valid hashed string.
- * @param rhs A valid hashed string.
- * @return True if the two hashed strings are identical, false otherwise.
- */
- template<typename Char>
- [[nodiscard]] constexpr bool operator==(const basic_hashed_string<Char> &lhs, const basic_hashed_string<Char> &rhs) noexcept {
- return lhs.value() == rhs.value();
- }
- /**
- * @brief Compares two hashed strings.
- * @tparam Char Character type.
- * @param lhs A valid hashed string.
- * @param rhs A valid hashed string.
- * @return True if the two hashed strings differ, false otherwise.
- */
- template<typename Char>
- [[nodiscard]] constexpr bool operator!=(const basic_hashed_string<Char> &lhs, const basic_hashed_string<Char> &rhs) noexcept {
- return !(lhs == rhs);
- }
- /**
- * @brief Compares two hashed strings.
- * @tparam Char Character type.
- * @param lhs A valid hashed string.
- * @param rhs A valid hashed string.
- * @return True if the first element is less than the second, false otherwise.
- */
- template<typename Char>
- [[nodiscard]] constexpr bool operator<(const basic_hashed_string<Char> &lhs, const basic_hashed_string<Char> &rhs) noexcept {
- return lhs.value() < rhs.value();
- }
- /**
- * @brief Compares two hashed strings.
- * @tparam Char Character type.
- * @param lhs A valid hashed string.
- * @param rhs A valid hashed string.
- * @return True if the first element is less than or equal to the second, false
- * otherwise.
- */
- template<typename Char>
- [[nodiscard]] constexpr bool operator<=(const basic_hashed_string<Char> &lhs, const basic_hashed_string<Char> &rhs) noexcept {
- return !(rhs < lhs);
- }
- /**
- * @brief Compares two hashed strings.
- * @tparam Char Character type.
- * @param lhs A valid hashed string.
- * @param rhs A valid hashed string.
- * @return True if the first element is greater than the second, false
- * otherwise.
- */
- template<typename Char>
- [[nodiscard]] constexpr bool operator>(const basic_hashed_string<Char> &lhs, const basic_hashed_string<Char> &rhs) noexcept {
- return rhs < lhs;
- }
- /**
- * @brief Compares two hashed strings.
- * @tparam Char Character type.
- * @param lhs A valid hashed string.
- * @param rhs A valid hashed string.
- * @return True if the first element is greater than or equal to the second,
- * false otherwise.
- */
- template<typename Char>
- [[nodiscard]] constexpr bool operator>=(const basic_hashed_string<Char> &lhs, const basic_hashed_string<Char> &rhs) noexcept {
- return !(lhs < rhs);
- }
- inline namespace literals {
- /**
- * @brief User defined literal for hashed strings.
- * @param str The literal without its suffix.
- * @return A properly initialized hashed string.
- */
- [[nodiscard]] ENTT_CONSTEVAL hashed_string operator""_hs(const char *str, std::size_t) noexcept {
- return hashed_string{str};
- }
- /**
- * @brief User defined literal for hashed wstrings.
- * @param str The literal without its suffix.
- * @return A properly initialized hashed wstring.
- */
- [[nodiscard]] ENTT_CONSTEVAL hashed_wstring operator""_hws(const wchar_t *str, std::size_t) noexcept {
- return hashed_wstring{str};
- }
- } // namespace literals
- } // namespace entt
- #endif
- namespace entt {
- /*! @cond TURN_OFF_DOXYGEN */
- namespace internal {
- struct ENTT_API type_index final {
- [[nodiscard]] static id_type next() noexcept {
- static ENTT_MAYBE_ATOMIC(id_type) value{};
- return value++;
- }
- };
- template<typename Type>
- [[nodiscard]] constexpr const char *pretty_function() noexcept {
- #if defined ENTT_PRETTY_FUNCTION
- return static_cast<const char *>(ENTT_PRETTY_FUNCTION);
- #else
- return "";
- #endif
- }
- template<typename Type>
- [[nodiscard]] constexpr auto stripped_type_name() noexcept {
- #if defined ENTT_PRETTY_FUNCTION
- const std::string_view full_name{pretty_function<Type>()};
- auto first = full_name.find_first_not_of(' ', full_name.find_first_of(ENTT_PRETTY_FUNCTION_PREFIX) + 1);
- auto value = full_name.substr(first, full_name.find_last_of(ENTT_PRETTY_FUNCTION_SUFFIX) - first);
- return value;
- #else
- return std::string_view{};
- #endif
- }
- template<typename Type, auto = stripped_type_name<Type>().find_first_of('.')>
- [[nodiscard]] constexpr std::string_view type_name(int) noexcept {
- constexpr auto value = stripped_type_name<Type>();
- return value;
- }
- template<typename Type>
- [[nodiscard]] std::string_view type_name(char) noexcept {
- static const auto value = stripped_type_name<Type>();
- return value;
- }
- template<typename Type, auto = stripped_type_name<Type>().find_first_of('.')>
- [[nodiscard]] constexpr id_type type_hash(int) noexcept {
- constexpr auto stripped = stripped_type_name<Type>();
- constexpr auto value = hashed_string::value(stripped.data(), stripped.size());
- return value;
- }
- template<typename Type>
- [[nodiscard]] id_type type_hash(char) noexcept {
- static const auto value = [](const auto stripped) {
- return hashed_string::value(stripped.data(), stripped.size());
- }(stripped_type_name<Type>());
- return value;
- }
- } // namespace internal
- /*! @endcond */
- /**
- * @brief Type sequential identifier.
- * @tparam Type Type for which to generate a sequential identifier.
- */
- template<typename Type, typename = void>
- struct ENTT_API type_index final {
- /**
- * @brief Returns the sequential identifier of a given type.
- * @return The sequential identifier of a given type.
- */
- [[nodiscard]] static id_type value() noexcept {
- static const id_type value = internal::type_index::next();
- return value;
- }
- /*! @copydoc value */
- [[nodiscard]] constexpr operator id_type() const noexcept {
- return value();
- }
- };
- /**
- * @brief Type hash.
- * @tparam Type Type for which to generate a hash value.
- */
- template<typename Type, typename = void>
- struct type_hash final {
- /**
- * @brief Returns the numeric representation of a given type.
- * @return The numeric representation of the given type.
- */
- #if defined ENTT_PRETTY_FUNCTION
- [[nodiscard]] static constexpr id_type value() noexcept {
- return internal::type_hash<Type>(0);
- #else
- [[nodiscard]] static constexpr id_type value() noexcept {
- return type_index<Type>::value();
- #endif
- }
- /*! @copydoc value */
- [[nodiscard]] constexpr operator id_type() const noexcept {
- return value();
- }
- };
- /**
- * @brief Type name.
- * @tparam Type Type for which to generate a name.
- */
- template<typename Type, typename = void>
- struct type_name final {
- /**
- * @brief Returns the name of a given type.
- * @return The name of the given type.
- */
- [[nodiscard]] static constexpr std::string_view value() noexcept {
- return internal::type_name<Type>(0);
- }
- /*! @copydoc value */
- [[nodiscard]] constexpr operator std::string_view() const noexcept {
- return value();
- }
- };
- /*! @brief Implementation specific information about a type. */
- struct type_info final {
- /**
- * @brief Constructs a type info object for a given type.
- * @tparam Type Type for which to construct a type info object.
- */
- template<typename Type>
- // NOLINTBEGIN(modernize-use-transparent-functors)
- constexpr type_info(std::in_place_type_t<Type>) noexcept
- : seq{type_index<std::remove_const_t<std::remove_reference_t<Type>>>::value()},
- identifier{type_hash<std::remove_const_t<std::remove_reference_t<Type>>>::value()},
- alias{type_name<std::remove_const_t<std::remove_reference_t<Type>>>::value()} {}
- // NOLINTEND(modernize-use-transparent-functors)
- /**
- * @brief Type index.
- * @return Type index.
- */
- [[nodiscard]] constexpr id_type index() const noexcept {
- return seq;
- }
- /**
- * @brief Type hash.
- * @return Type hash.
- */
- [[nodiscard]] constexpr id_type hash() const noexcept {
- return identifier;
- }
- /**
- * @brief Type name.
- * @return Type name.
- */
- [[nodiscard]] constexpr std::string_view name() const noexcept {
- return alias;
- }
- private:
- id_type seq;
- id_type identifier;
- std::string_view alias;
- };
- /**
- * @brief Compares the contents of two type info objects.
- * @param lhs A type info object.
- * @param rhs A type info object.
- * @return True if the two type info objects are identical, false otherwise.
- */
- [[nodiscard]] constexpr bool operator==(const type_info &lhs, const type_info &rhs) noexcept {
- return lhs.hash() == rhs.hash();
- }
- /**
- * @brief Compares the contents of two type info objects.
- * @param lhs A type info object.
- * @param rhs A type info object.
- * @return True if the two type info objects differ, false otherwise.
- */
- [[nodiscard]] constexpr bool operator!=(const type_info &lhs, const type_info &rhs) noexcept {
- return !(lhs == rhs);
- }
- /**
- * @brief Compares two type info objects.
- * @param lhs A valid type info object.
- * @param rhs A valid type info object.
- * @return True if the first element is less than the second, false otherwise.
- */
- [[nodiscard]] constexpr bool operator<(const type_info &lhs, const type_info &rhs) noexcept {
- return lhs.index() < rhs.index();
- }
- /**
- * @brief Compares two type info objects.
- * @param lhs A valid type info object.
- * @param rhs A valid type info object.
- * @return True if the first element is less than or equal to the second, false
- * otherwise.
- */
- [[nodiscard]] constexpr bool operator<=(const type_info &lhs, const type_info &rhs) noexcept {
- return !(rhs < lhs);
- }
- /**
- * @brief Compares two type info objects.
- * @param lhs A valid type info object.
- * @param rhs A valid type info object.
- * @return True if the first element is greater than the second, false
- * otherwise.
- */
- [[nodiscard]] constexpr bool operator>(const type_info &lhs, const type_info &rhs) noexcept {
- return rhs < lhs;
- }
- /**
- * @brief Compares two type info objects.
- * @param lhs A valid type info object.
- * @param rhs A valid type info object.
- * @return True if the first element is greater than or equal to the second,
- * false otherwise.
- */
- [[nodiscard]] constexpr bool operator>=(const type_info &lhs, const type_info &rhs) noexcept {
- return !(lhs < rhs);
- }
- /**
- * @brief Returns the type info object associated to a given type.
- *
- * The returned element refers to an object with static storage duration.<br/>
- * The type doesn't need to be a complete type. If the type is a reference, the
- * result refers to the referenced type. In all cases, top-level cv-qualifiers
- * are ignored.
- *
- * @tparam Type Type for which to generate a type info object.
- * @return A reference to a properly initialized type info object.
- */
- template<typename Type>
- [[nodiscard]] const type_info &type_id() noexcept {
- if constexpr(std::is_same_v<Type, std::remove_const_t<std::remove_reference_t<Type>>>) {
- static const type_info instance{std::in_place_type<Type>};
- return instance;
- } else {
- return type_id<std::remove_const_t<std::remove_reference_t<Type>>>();
- }
- }
- /*! @copydoc type_id */
- template<typename Type>
- // NOLINTNEXTLINE(cppcoreguidelines-missing-std-forward)
- [[nodiscard]] const type_info &type_id(Type &&) noexcept {
- return type_id<std::remove_const_t<std::remove_reference_t<Type>>>();
- }
- } // namespace entt
- #endif
- // #include "type_traits.hpp"
- #ifndef ENTT_CORE_TYPE_TRAITS_HPP
- #define ENTT_CORE_TYPE_TRAITS_HPP
- #include <cstddef>
- #include <iterator>
- #include <tuple>
- #include <type_traits>
- #include <utility>
- // #include "../config/config.h"
- // #include "fwd.hpp"
- namespace entt {
- /**
- * @brief Utility class to disambiguate overloaded functions.
- * @tparam N Number of choices available.
- */
- template<std::size_t N>
- struct choice_t
- // unfortunately, doxygen cannot parse such a construct
- : /*! @cond TURN_OFF_DOXYGEN */ choice_t<N - 1> /*! @endcond */
- {};
- /*! @copybrief choice_t */
- template<>
- struct choice_t<0> {};
- /**
- * @brief Variable template for the choice trick.
- * @tparam N Number of choices available.
- */
- template<std::size_t N>
- inline constexpr choice_t<N> choice{};
- /**
- * @brief Identity type trait.
- *
- * Useful to establish non-deduced contexts in template argument deduction
- * (waiting for C++20) or to provide types through function arguments.
- *
- * @tparam Type A type.
- */
- template<typename Type>
- struct type_identity {
- /*! @brief Identity type. */
- using type = Type;
- };
- /**
- * @brief Helper type.
- * @tparam Type A type.
- */
- template<typename Type>
- using type_identity_t = typename type_identity<Type>::type;
- /**
- * @brief A type-only `sizeof` wrapper that returns 0 where `sizeof` complains.
- * @tparam Type The type of which to return the size.
- */
- template<typename Type, typename = void>
- struct size_of: std::integral_constant<std::size_t, 0u> {};
- /*! @copydoc size_of */
- template<typename Type>
- struct size_of<Type, std::void_t<decltype(sizeof(Type))>>
- // NOLINTNEXTLINE(bugprone-sizeof-expression)
- : std::integral_constant<std::size_t, sizeof(Type)> {};
- /**
- * @brief Helper variable template.
- * @tparam Type The type of which to return the size.
- */
- template<typename Type>
- inline constexpr std::size_t size_of_v = size_of<Type>::value;
- /**
- * @brief Using declaration to be used to _repeat_ the same type a number of
- * times equal to the size of a given parameter pack.
- * @tparam Type A type to repeat.
- */
- template<typename Type, typename>
- using unpack_as_type = Type;
- /**
- * @brief Helper variable template to be used to _repeat_ the same value a
- * number of times equal to the size of a given parameter pack.
- * @tparam Value A value to repeat.
- */
- template<auto Value, typename>
- inline constexpr auto unpack_as_value = Value;
- /**
- * @brief Wraps a static constant.
- * @tparam Value A static constant.
- */
- template<auto Value>
- using integral_constant = std::integral_constant<decltype(Value), Value>;
- /**
- * @brief Alias template to facilitate the creation of named values.
- * @tparam Value A constant value at least convertible to `id_type`.
- */
- template<id_type Value>
- using tag = integral_constant<Value>;
- /**
- * @brief A class to use to push around lists of types, nothing more.
- * @tparam Type Types provided by the type list.
- */
- template<typename... Type>
- struct type_list {
- /*! @brief Type list type. */
- using type = type_list;
- /*! @brief Compile-time number of elements in the type list. */
- static constexpr auto size = sizeof...(Type);
- };
- /*! @brief Primary template isn't defined on purpose. */
- template<std::size_t, typename>
- struct type_list_element;
- /**
- * @brief Provides compile-time indexed access to the types of a type list.
- * @tparam Index Index of the type to return.
- * @tparam First First type provided by the type list.
- * @tparam Other Other types provided by the type list.
- */
- template<std::size_t Index, typename First, typename... Other>
- struct type_list_element<Index, type_list<First, Other...>>
- : type_list_element<Index - 1u, type_list<Other...>> {};
- /**
- * @brief Provides compile-time indexed access to the types of a type list.
- * @tparam First First type provided by the type list.
- * @tparam Other Other types provided by the type list.
- */
- template<typename First, typename... Other>
- struct type_list_element<0u, type_list<First, Other...>> {
- /*! @brief Searched type. */
- using type = First;
- };
- /**
- * @brief Helper type.
- * @tparam Index Index of the type to return.
- * @tparam List Type list to search into.
- */
- template<std::size_t Index, typename List>
- using type_list_element_t = typename type_list_element<Index, List>::type;
- /*! @brief Primary template isn't defined on purpose. */
- template<typename, typename>
- struct type_list_index;
- /**
- * @brief Provides compile-time type access to the types of a type list.
- * @tparam Type Type to look for and for which to return the index.
- * @tparam First First type provided by the type list.
- * @tparam Other Other types provided by the type list.
- */
- template<typename Type, typename First, typename... Other>
- struct type_list_index<Type, type_list<First, Other...>> {
- /*! @brief Unsigned integer type. */
- using value_type = std::size_t;
- /*! @brief Compile-time position of the given type in the sublist. */
- static constexpr value_type value = 1u + type_list_index<Type, type_list<Other...>>::value;
- };
- /**
- * @brief Provides compile-time type access to the types of a type list.
- * @tparam Type Type to look for and for which to return the index.
- * @tparam Other Other types provided by the type list.
- */
- template<typename Type, typename... Other>
- struct type_list_index<Type, type_list<Type, Other...>> {
- static_assert(type_list_index<Type, type_list<Other...>>::value == sizeof...(Other), "Non-unique type");
- /*! @brief Unsigned integer type. */
- using value_type = std::size_t;
- /*! @brief Compile-time position of the given type in the sublist. */
- static constexpr value_type value = 0u;
- };
- /**
- * @brief Provides compile-time type access to the types of a type list.
- * @tparam Type Type to look for and for which to return the index.
- */
- template<typename Type>
- struct type_list_index<Type, type_list<>> {
- /*! @brief Unsigned integer type. */
- using value_type = std::size_t;
- /*! @brief Compile-time position of the given type in the sublist. */
- static constexpr value_type value = 0u;
- };
- /**
- * @brief Helper variable template.
- * @tparam List Type list.
- * @tparam Type Type to look for and for which to return the index.
- */
- template<typename Type, typename List>
- inline constexpr std::size_t type_list_index_v = type_list_index<Type, List>::value;
- /**
- * @brief Concatenates multiple type lists.
- * @tparam Type Types provided by the first type list.
- * @tparam Other Types provided by the second type list.
- * @return A type list composed by the types of both the type lists.
- */
- template<typename... Type, typename... Other>
- constexpr type_list<Type..., Other...> operator+(type_list<Type...>, type_list<Other...>) {
- return {};
- }
- /*! @brief Primary template isn't defined on purpose. */
- template<typename...>
- struct type_list_cat;
- /*! @brief Concatenates multiple type lists. */
- template<>
- struct type_list_cat<> {
- /*! @brief A type list composed by the types of all the type lists. */
- using type = type_list<>;
- };
- /**
- * @brief Concatenates multiple type lists.
- * @tparam Type Types provided by the first type list.
- * @tparam Other Types provided by the second type list.
- * @tparam List Other type lists, if any.
- */
- template<typename... Type, typename... Other, typename... List>
- struct type_list_cat<type_list<Type...>, type_list<Other...>, List...> {
- /*! @brief A type list composed by the types of all the type lists. */
- using type = typename type_list_cat<type_list<Type..., Other...>, List...>::type;
- };
- /**
- * @brief Concatenates multiple type lists.
- * @tparam Type Types provided by the type list.
- */
- template<typename... Type>
- struct type_list_cat<type_list<Type...>> {
- /*! @brief A type list composed by the types of all the type lists. */
- using type = type_list<Type...>;
- };
- /**
- * @brief Helper type.
- * @tparam List Type lists to concatenate.
- */
- template<typename... List>
- using type_list_cat_t = typename type_list_cat<List...>::type;
- /*! @cond TURN_OFF_DOXYGEN */
- namespace internal {
- template<typename...>
- struct type_list_unique;
- template<typename First, typename... Other, typename... Type>
- struct type_list_unique<type_list<First, Other...>, Type...>
- : std::conditional_t<(std::is_same_v<First, Type> || ...), type_list_unique<type_list<Other...>, Type...>, type_list_unique<type_list<Other...>, Type..., First>> {};
- template<typename... Type>
- struct type_list_unique<type_list<>, Type...> {
- using type = type_list<Type...>;
- };
- } // namespace internal
- /*! @endcond */
- /**
- * @brief Removes duplicates types from a type list.
- * @tparam List Type list.
- */
- template<typename List>
- struct type_list_unique {
- /*! @brief A type list without duplicate types. */
- using type = typename internal::type_list_unique<List>::type;
- };
- /**
- * @brief Helper type.
- * @tparam List Type list.
- */
- template<typename List>
- using type_list_unique_t = typename type_list_unique<List>::type;
- /**
- * @brief Provides the member constant `value` to true if a type list contains a
- * given type, false otherwise.
- * @tparam List Type list.
- * @tparam Type Type to look for.
- */
- template<typename List, typename Type>
- struct type_list_contains;
- /**
- * @copybrief type_list_contains
- * @tparam Type Types provided by the type list.
- * @tparam Other Type to look for.
- */
- template<typename... Type, typename Other>
- struct type_list_contains<type_list<Type...>, Other>
- : std::bool_constant<(std::is_same_v<Type, Other> || ...)> {};
- /**
- * @brief Helper variable template.
- * @tparam List Type list.
- * @tparam Type Type to look for.
- */
- template<typename List, typename Type>
- inline constexpr bool type_list_contains_v = type_list_contains<List, Type>::value;
- /*! @brief Primary template isn't defined on purpose. */
- template<typename...>
- struct type_list_diff;
- /**
- * @brief Computes the difference between two type lists.
- * @tparam Type Types provided by the first type list.
- * @tparam Other Types provided by the second type list.
- */
- template<typename... Type, typename... Other>
- struct type_list_diff<type_list<Type...>, type_list<Other...>> {
- /*! @brief A type list that is the difference between the two type lists. */
- using type = type_list_cat_t<std::conditional_t<type_list_contains_v<type_list<Other...>, Type>, type_list<>, type_list<Type>>...>;
- };
- /**
- * @brief Helper type.
- * @tparam List Type lists between which to compute the difference.
- */
- template<typename... List>
- using type_list_diff_t = typename type_list_diff<List...>::type;
- /*! @brief Primary template isn't defined on purpose. */
- template<typename, template<typename...> class>
- struct type_list_transform;
- /**
- * @brief Applies a given _function_ to a type list and generate a new list.
- * @tparam Type Types provided by the type list.
- * @tparam Op Unary operation as template class with a type member named `type`.
- */
- template<typename... Type, template<typename...> class Op>
- struct type_list_transform<type_list<Type...>, Op> {
- /*! @brief Resulting type list after applying the transform function. */
- // NOLINTNEXTLINE(modernize-type-traits)
- using type = type_list<typename Op<Type>::type...>;
- };
- /**
- * @brief Helper type.
- * @tparam List Type list.
- * @tparam Op Unary operation as template class with a type member named `type`.
- */
- template<typename List, template<typename...> class Op>
- using type_list_transform_t = typename type_list_transform<List, Op>::type;
- /**
- * @brief A class to use to push around lists of constant values, nothing more.
- * @tparam Value Values provided by the value list.
- */
- template<auto... Value>
- struct value_list {
- /*! @brief Value list type. */
- using type = value_list;
- /*! @brief Compile-time number of elements in the value list. */
- static constexpr auto size = sizeof...(Value);
- };
- /*! @brief Primary template isn't defined on purpose. */
- template<std::size_t, typename>
- struct value_list_element;
- /**
- * @brief Provides compile-time indexed access to the values of a value list.
- * @tparam Index Index of the value to return.
- * @tparam Value First value provided by the value list.
- * @tparam Other Other values provided by the value list.
- */
- template<std::size_t Index, auto Value, auto... Other>
- struct value_list_element<Index, value_list<Value, Other...>>
- : value_list_element<Index - 1u, value_list<Other...>> {};
- /**
- * @brief Provides compile-time indexed access to the types of a type list.
- * @tparam Value First value provided by the value list.
- * @tparam Other Other values provided by the value list.
- */
- template<auto Value, auto... Other>
- struct value_list_element<0u, value_list<Value, Other...>> {
- /*! @brief Searched type. */
- using type = decltype(Value);
- /*! @brief Searched value. */
- static constexpr auto value = Value;
- };
- /**
- * @brief Helper type.
- * @tparam Index Index of the type to return.
- * @tparam List Value list to search into.
- */
- template<std::size_t Index, typename List>
- using value_list_element_t = typename value_list_element<Index, List>::type;
- /**
- * @brief Helper type.
- * @tparam Index Index of the value to return.
- * @tparam List Value list to search into.
- */
- template<std::size_t Index, typename List>
- inline constexpr auto value_list_element_v = value_list_element<Index, List>::value;
- /*! @brief Primary template isn't defined on purpose. */
- template<auto, typename>
- struct value_list_index;
- /**
- * @brief Provides compile-time type access to the values of a value list.
- * @tparam Value Value to look for and for which to return the index.
- * @tparam First First value provided by the value list.
- * @tparam Other Other values provided by the value list.
- */
- template<auto Value, auto First, auto... Other>
- struct value_list_index<Value, value_list<First, Other...>> {
- /*! @brief Unsigned integer type. */
- using value_type = std::size_t;
- /*! @brief Compile-time position of the given value in the sublist. */
- static constexpr value_type value = 1u + value_list_index<Value, value_list<Other...>>::value;
- };
- /**
- * @brief Provides compile-time type access to the values of a value list.
- * @tparam Value Value to look for and for which to return the index.
- * @tparam Other Other values provided by the value list.
- */
- template<auto Value, auto... Other>
- struct value_list_index<Value, value_list<Value, Other...>> {
- static_assert(value_list_index<Value, value_list<Other...>>::value == sizeof...(Other), "Non-unique type");
- /*! @brief Unsigned integer type. */
- using value_type = std::size_t;
- /*! @brief Compile-time position of the given value in the sublist. */
- static constexpr value_type value = 0u;
- };
- /**
- * @brief Provides compile-time type access to the values of a value list.
- * @tparam Value Value to look for and for which to return the index.
- */
- template<auto Value>
- struct value_list_index<Value, value_list<>> {
- /*! @brief Unsigned integer type. */
- using value_type = std::size_t;
- /*! @brief Compile-time position of the given type in the sublist. */
- static constexpr value_type value = 0u;
- };
- /**
- * @brief Helper variable template.
- * @tparam List Value list.
- * @tparam Value Value to look for and for which to return the index.
- */
- template<auto Value, typename List>
- inline constexpr std::size_t value_list_index_v = value_list_index<Value, List>::value;
- /**
- * @brief Concatenates multiple value lists.
- * @tparam Value Values provided by the first value list.
- * @tparam Other Values provided by the second value list.
- * @return A value list composed by the values of both the value lists.
- */
- template<auto... Value, auto... Other>
- constexpr value_list<Value..., Other...> operator+(value_list<Value...>, value_list<Other...>) {
- return {};
- }
- /*! @brief Primary template isn't defined on purpose. */
- template<typename...>
- struct value_list_cat;
- /*! @brief Concatenates multiple value lists. */
- template<>
- struct value_list_cat<> {
- /*! @brief A value list composed by the values of all the value lists. */
- using type = value_list<>;
- };
- /**
- * @brief Concatenates multiple value lists.
- * @tparam Value Values provided by the first value list.
- * @tparam Other Values provided by the second value list.
- * @tparam List Other value lists, if any.
- */
- template<auto... Value, auto... Other, typename... List>
- struct value_list_cat<value_list<Value...>, value_list<Other...>, List...> {
- /*! @brief A value list composed by the values of all the value lists. */
- using type = typename value_list_cat<value_list<Value..., Other...>, List...>::type;
- };
- /**
- * @brief Concatenates multiple value lists.
- * @tparam Value Values provided by the value list.
- */
- template<auto... Value>
- struct value_list_cat<value_list<Value...>> {
- /*! @brief A value list composed by the values of all the value lists. */
- using type = value_list<Value...>;
- };
- /**
- * @brief Helper type.
- * @tparam List Value lists to concatenate.
- */
- template<typename... List>
- using value_list_cat_t = typename value_list_cat<List...>::type;
- /*! @brief Primary template isn't defined on purpose. */
- template<typename>
- struct value_list_unique;
- /**
- * @brief Removes duplicates values from a value list.
- * @tparam Value One of the values provided by the given value list.
- * @tparam Other The other values provided by the given value list.
- */
- template<auto Value, auto... Other>
- struct value_list_unique<value_list<Value, Other...>> {
- /*! @brief A value list without duplicate types. */
- using type = std::conditional_t<
- ((Value == Other) || ...),
- typename value_list_unique<value_list<Other...>>::type,
- value_list_cat_t<value_list<Value>, typename value_list_unique<value_list<Other...>>::type>>;
- };
- /*! @brief Removes duplicates values from a value list. */
- template<>
- struct value_list_unique<value_list<>> {
- /*! @brief A value list without duplicate types. */
- using type = value_list<>;
- };
- /**
- * @brief Helper type.
- * @tparam Type A value list.
- */
- template<typename Type>
- using value_list_unique_t = typename value_list_unique<Type>::type;
- /**
- * @brief Provides the member constant `value` to true if a value list contains
- * a given value, false otherwise.
- * @tparam List Value list.
- * @tparam Value Value to look for.
- */
- template<typename List, auto Value>
- struct value_list_contains;
- /**
- * @copybrief value_list_contains
- * @tparam Value Values provided by the value list.
- * @tparam Other Value to look for.
- */
- template<auto... Value, auto Other>
- struct value_list_contains<value_list<Value...>, Other>
- : std::bool_constant<((Value == Other) || ...)> {};
- /**
- * @brief Helper variable template.
- * @tparam List Value list.
- * @tparam Value Value to look for.
- */
- template<typename List, auto Value>
- inline constexpr bool value_list_contains_v = value_list_contains<List, Value>::value;
- /*! @brief Primary template isn't defined on purpose. */
- template<typename...>
- struct value_list_diff;
- /**
- * @brief Computes the difference between two value lists.
- * @tparam Value Values provided by the first value list.
- * @tparam Other Values provided by the second value list.
- */
- template<auto... Value, auto... Other>
- struct value_list_diff<value_list<Value...>, value_list<Other...>> {
- /*! @brief A value list that is the difference between the two value lists. */
- using type = value_list_cat_t<std::conditional_t<value_list_contains_v<value_list<Other...>, Value>, value_list<>, value_list<Value>>...>;
- };
- /**
- * @brief Helper type.
- * @tparam List Value lists between which to compute the difference.
- */
- template<typename... List>
- using value_list_diff_t = typename value_list_diff<List...>::type;
- /*! @brief Same as std::is_invocable, but with tuples. */
- template<typename, typename>
- struct is_applicable: std::false_type {};
- /**
- * @copybrief is_applicable
- * @tparam Func A valid function type.
- * @tparam Tuple Tuple-like type.
- * @tparam Args The list of arguments to use to probe the function type.
- */
- template<typename Func, template<typename...> class Tuple, typename... Args>
- struct is_applicable<Func, Tuple<Args...>>: std::is_invocable<Func, Args...> {};
- /**
- * @copybrief is_applicable
- * @tparam Func A valid function type.
- * @tparam Tuple Tuple-like type.
- * @tparam Args The list of arguments to use to probe the function type.
- */
- template<typename Func, template<typename...> class Tuple, typename... Args>
- struct is_applicable<Func, const Tuple<Args...>>: std::is_invocable<Func, Args...> {};
- /**
- * @brief Helper variable template.
- * @tparam Func A valid function type.
- * @tparam Args The list of arguments to use to probe the function type.
- */
- template<typename Func, typename Args>
- inline constexpr bool is_applicable_v = is_applicable<Func, Args>::value;
- /*! @brief Same as std::is_invocable_r, but with tuples for arguments. */
- template<typename, typename, typename>
- struct is_applicable_r: std::false_type {};
- /**
- * @copybrief is_applicable_r
- * @tparam Ret The type to which the return type of the function should be
- * convertible.
- * @tparam Func A valid function type.
- * @tparam Args The list of arguments to use to probe the function type.
- */
- template<typename Ret, typename Func, typename... Args>
- struct is_applicable_r<Ret, Func, std::tuple<Args...>>: std::is_invocable_r<Ret, Func, Args...> {};
- /**
- * @brief Helper variable template.
- * @tparam Ret The type to which the return type of the function should be
- * convertible.
- * @tparam Func A valid function type.
- * @tparam Args The list of arguments to use to probe the function type.
- */
- template<typename Ret, typename Func, typename Args>
- inline constexpr bool is_applicable_r_v = is_applicable_r<Ret, Func, Args>::value;
- /**
- * @brief Provides the member constant `value` to true if a given type is
- * complete, false otherwise.
- * @tparam Type The type to test.
- */
- template<typename Type, typename = void>
- struct is_complete: std::false_type {};
- /*! @copydoc is_complete */
- template<typename Type>
- struct is_complete<Type, std::void_t<decltype(sizeof(Type))>>: std::true_type {};
- /**
- * @brief Helper variable template.
- * @tparam Type The type to test.
- */
- template<typename Type>
- inline constexpr bool is_complete_v = is_complete<Type>::value;
- /**
- * @brief Provides the member constant `value` to true if a given type is an
- * iterator, false otherwise.
- * @tparam Type The type to test.
- */
- template<typename Type, typename = void>
- struct is_iterator: std::false_type {};
- /*! @cond TURN_OFF_DOXYGEN */
- namespace internal {
- template<typename, typename = void>
- struct has_iterator_category: std::false_type {};
- template<typename Type>
- struct has_iterator_category<Type, std::void_t<typename std::iterator_traits<Type>::iterator_category>>: std::true_type {};
- } // namespace internal
- /*! @endcond */
- /*! @copydoc is_iterator */
- template<typename Type>
- struct is_iterator<Type, std::enable_if_t<!std::is_void_v<std::remove_const_t<std::remove_pointer_t<Type>>>>>
- : internal::has_iterator_category<Type> {};
- /**
- * @brief Helper variable template.
- * @tparam Type The type to test.
- */
- template<typename Type>
- inline constexpr bool is_iterator_v = is_iterator<Type>::value;
- /**
- * @brief Provides the member constant `value` to true if a given type is both
- * an empty and non-final class, false otherwise.
- * @tparam Type The type to test
- */
- template<typename Type>
- struct is_ebco_eligible
- : std::bool_constant<std::is_empty_v<Type> && !std::is_final_v<Type>> {};
- /**
- * @brief Helper variable template.
- * @tparam Type The type to test.
- */
- template<typename Type>
- inline constexpr bool is_ebco_eligible_v = is_ebco_eligible<Type>::value;
- /**
- * @brief Provides the member constant `value` to true if `Type::is_transparent`
- * is valid and denotes a type, false otherwise.
- * @tparam Type The type to test.
- */
- template<typename Type, typename = void>
- struct is_transparent: std::false_type {};
- /*! @copydoc is_transparent */
- template<typename Type>
- struct is_transparent<Type, std::void_t<typename Type::is_transparent>>: std::true_type {};
- /**
- * @brief Helper variable template.
- * @tparam Type The type to test.
- */
- template<typename Type>
- inline constexpr bool is_transparent_v = is_transparent<Type>::value;
- /*! @cond TURN_OFF_DOXYGEN */
- namespace internal {
- template<typename, typename = void>
- struct has_tuple_size_value: std::false_type {};
- template<typename Type>
- struct has_tuple_size_value<Type, std::void_t<decltype(std::tuple_size<const Type>::value)>>: std::true_type {};
- template<typename, typename = void>
- struct has_value_type: std::false_type {};
- template<typename Type>
- struct has_value_type<Type, std::void_t<typename Type::value_type>>: std::true_type {};
- template<typename>
- [[nodiscard]] constexpr bool dispatch_is_equality_comparable();
- template<typename Type, std::size_t... Index>
- [[nodiscard]] constexpr bool unpack_maybe_equality_comparable(std::index_sequence<Index...>) {
- return (dispatch_is_equality_comparable<std::tuple_element_t<Index, Type>>() && ...);
- }
- template<typename>
- [[nodiscard]] constexpr bool maybe_equality_comparable(char) {
- return false;
- }
- template<typename Type>
- [[nodiscard]] constexpr auto maybe_equality_comparable(int) -> decltype(std::declval<Type>() == std::declval<Type>()) {
- return true;
- }
- template<typename Type>
- [[nodiscard]] constexpr bool dispatch_is_equality_comparable() {
- // NOLINTBEGIN(modernize-use-transparent-functors)
- if constexpr(std::is_array_v<Type>) {
- return false;
- } else if constexpr(is_complete_v<std::tuple_size<std::remove_const_t<Type>>>) {
- if constexpr(has_tuple_size_value<Type>::value) {
- return maybe_equality_comparable<Type>(0) && unpack_maybe_equality_comparable<Type>(std::make_index_sequence<std::tuple_size<Type>::value>{});
- } else {
- return maybe_equality_comparable<Type>(0);
- }
- } else if constexpr(has_value_type<Type>::value) {
- if constexpr(is_iterator_v<Type> || std::is_same_v<typename Type::value_type, Type> || dispatch_is_equality_comparable<typename Type::value_type>()) {
- return maybe_equality_comparable<Type>(0);
- } else {
- return false;
- }
- } else {
- return maybe_equality_comparable<Type>(0);
- }
- // NOLINTEND(modernize-use-transparent-functors)
- }
- } // namespace internal
- /*! @endcond */
- /**
- * @brief Provides the member constant `value` to true if a given type is
- * equality comparable, false otherwise.
- * @tparam Type The type to test.
- */
- template<typename Type>
- struct is_equality_comparable: std::bool_constant<internal::dispatch_is_equality_comparable<Type>()> {};
- /*! @copydoc is_equality_comparable */
- template<typename Type>
- struct is_equality_comparable<const Type>: is_equality_comparable<Type> {};
- /**
- * @brief Helper variable template.
- * @tparam Type The type to test.
- */
- template<typename Type>
- inline constexpr bool is_equality_comparable_v = is_equality_comparable<Type>::value;
- /**
- * @brief Transcribes the constness of a type to another type.
- * @tparam To The type to which to transcribe the constness.
- * @tparam From The type from which to transcribe the constness.
- */
- template<typename To, typename From>
- struct constness_as {
- /*! @brief The type resulting from the transcription of the constness. */
- using type = std::remove_const_t<To>;
- };
- /*! @copydoc constness_as */
- template<typename To, typename From>
- struct constness_as<To, const From> {
- /*! @brief The type resulting from the transcription of the constness. */
- using type = const To;
- };
- /**
- * @brief Alias template to facilitate the transcription of the constness.
- * @tparam To The type to which to transcribe the constness.
- * @tparam From The type from which to transcribe the constness.
- */
- template<typename To, typename From>
- using constness_as_t = typename constness_as<To, From>::type;
- /**
- * @brief Extracts the class of a non-static member object or function.
- * @tparam Member A pointer to a non-static member object or function.
- */
- template<typename Member>
- class member_class {
- static_assert(std::is_member_pointer_v<Member>, "Invalid pointer type to non-static member object or function");
- template<typename Class, typename Ret, typename... Args>
- static Class *clazz(Ret (Class::*)(Args...));
- template<typename Class, typename Ret, typename... Args>
- static Class *clazz(Ret (Class::*)(Args...) const);
- template<typename Class, typename Type>
- static Class *clazz(Type Class::*);
- public:
- /*! @brief The class of the given non-static member object or function. */
- using type = std::remove_pointer_t<decltype(clazz(std::declval<Member>()))>;
- };
- /**
- * @brief Helper type.
- * @tparam Member A pointer to a non-static member object or function.
- */
- template<typename Member>
- using member_class_t = typename member_class<Member>::type;
- /**
- * @brief Extracts the n-th argument of a _callable_ type.
- * @tparam Index The index of the argument to extract.
- * @tparam Candidate A valid _callable_ type.
- */
- template<std::size_t Index, typename Candidate>
- class nth_argument {
- template<typename Ret, typename... Args>
- static constexpr type_list<Args...> pick_up(Ret (*)(Args...));
- template<typename Ret, typename Class, typename... Args>
- static constexpr type_list<Args...> pick_up(Ret (Class ::*)(Args...));
- template<typename Ret, typename Class, typename... Args>
- static constexpr type_list<Args...> pick_up(Ret (Class ::*)(Args...) const);
- template<typename Type, typename Class>
- static constexpr type_list<Type> pick_up(Type Class ::*);
- template<typename Type>
- static constexpr decltype(pick_up(&Type::operator())) pick_up(Type &&);
- public:
- /*! @brief N-th argument of the _callable_ type. */
- using type = type_list_element_t<Index, decltype(pick_up(std::declval<Candidate>()))>;
- };
- /**
- * @brief Helper type.
- * @tparam Index The index of the argument to extract.
- * @tparam Candidate A valid function, member function or data member type.
- */
- template<std::size_t Index, typename Candidate>
- using nth_argument_t = typename nth_argument<Index, Candidate>::type;
- } // namespace entt
- template<typename... Type>
- struct std::tuple_size<entt::type_list<Type...>>: std::integral_constant<std::size_t, entt::type_list<Type...>::size> {};
- template<std::size_t Index, typename... Type>
- struct std::tuple_element<Index, entt::type_list<Type...>>: entt::type_list_element<Index, entt::type_list<Type...>> {};
- template<auto... Value>
- struct std::tuple_size<entt::value_list<Value...>>: std::integral_constant<std::size_t, entt::value_list<Value...>::size> {};
- template<std::size_t Index, auto... Value>
- struct std::tuple_element<Index, entt::value_list<Value...>>: entt::value_list_element<Index, entt::value_list<Value...>> {};
- #endif
- // #include "utility.hpp"
- #ifndef ENTT_CORE_UTILITY_HPP
- #define ENTT_CORE_UTILITY_HPP
- #include <type_traits>
- #include <utility>
- namespace entt {
- /*! @brief Identity function object (waiting for C++20). */
- struct identity {
- /*! @brief Indicates that this is a transparent function object. */
- using is_transparent = void;
- /**
- * @brief Returns its argument unchanged.
- * @tparam Type Type of the argument.
- * @param value The actual argument.
- * @return The submitted value as-is.
- */
- template<typename Type>
- [[nodiscard]] constexpr Type &&operator()(Type &&value) const noexcept {
- return std::forward<Type>(value);
- }
- };
- /**
- * @brief Constant utility to disambiguate overloaded members of a class.
- * @tparam Type Type of the desired overload.
- * @tparam Class Type of class to which the member belongs.
- * @param member A valid pointer to a member.
- * @return Pointer to the member.
- */
- template<typename Type, typename Class>
- [[nodiscard]] constexpr auto overload(Type Class::*member) noexcept {
- return member;
- }
- /**
- * @brief Constant utility to disambiguate overloaded functions.
- * @tparam Func Function type of the desired overload.
- * @param func A valid pointer to a function.
- * @return Pointer to the function.
- */
- template<typename Func>
- [[nodiscard]] constexpr auto overload(Func *func) noexcept {
- return func;
- }
- /**
- * @brief Helper type for visitors.
- * @tparam Func Types of function objects.
- */
- template<typename... Func>
- struct overloaded: Func... {
- using Func::operator()...;
- };
- /**
- * @brief Deduction guide.
- * @tparam Func Types of function objects.
- */
- template<typename... Func>
- overloaded(Func...) -> overloaded<Func...>;
- /**
- * @brief Basic implementation of a y-combinator.
- * @tparam Func Type of a potentially recursive function.
- */
- template<typename Func>
- struct y_combinator {
- /**
- * @brief Constructs a y-combinator from a given function.
- * @param recursive A potentially recursive function.
- */
- constexpr y_combinator(Func recursive) noexcept(std::is_nothrow_move_constructible_v<Func>)
- : func{std::move(recursive)} {}
- /**
- * @brief Invokes a y-combinator and therefore its underlying function.
- * @tparam Args Types of arguments to use to invoke the underlying function.
- * @param args Parameters to use to invoke the underlying function.
- * @return Return value of the underlying function, if any.
- */
- template<typename... Args>
- constexpr decltype(auto) operator()(Args &&...args) const noexcept(std::is_nothrow_invocable_v<Func, const y_combinator &, Args...>) {
- return func(*this, std::forward<Args>(args)...);
- }
- /*! @copydoc operator()() */
- template<typename... Args>
- constexpr decltype(auto) operator()(Args &&...args) noexcept(std::is_nothrow_invocable_v<Func, y_combinator &, Args...>) {
- return func(*this, std::forward<Args>(args)...);
- }
- private:
- Func func;
- };
- } // namespace entt
- #endif
- namespace entt {
- /*! @cond TURN_OFF_DOXYGEN */
- namespace internal {
- enum class any_request : std::uint8_t {
- info,
- transfer,
- assign,
- compare,
- copy,
- move
- };
- template<std::size_t Len, std::size_t Align>
- struct basic_any_storage {
- static constexpr bool has_buffer = true;
- union {
- const void *instance{};
- // NOLINTNEXTLINE(cppcoreguidelines-avoid-c-arrays, modernize-avoid-c-arrays)
- alignas(Align) std::byte buffer[Len];
- };
- };
- template<std::size_t Align>
- struct basic_any_storage<0u, Align> {
- static constexpr bool has_buffer = false;
- const void *instance{};
- };
- template<typename Type, std::size_t Len, std::size_t Align>
- // NOLINTNEXTLINE(bugprone-sizeof-expression)
- struct in_situ: std::bool_constant<(Len != 0u) && alignof(Type) <= Align && sizeof(Type) <= Len && std::is_nothrow_move_constructible_v<Type>> {};
- template<std::size_t Len, std::size_t Align>
- struct in_situ<void, Len, Align>: std::false_type {};
- } // namespace internal
- /*! @endcond */
- /**
- * @brief A SBO friendly, type-safe container for single values of any type.
- * @tparam Len Size of the buffer reserved for the small buffer optimization.
- * @tparam Align Optional alignment requirement.
- */
- template<std::size_t Len, std::size_t Align>
- class basic_any: private internal::basic_any_storage<Len, Align> {
- using request = internal::any_request;
- using base_type = internal::basic_any_storage<Len, Align>;
- using vtable_type = const void *(const request, const basic_any &, const void *);
- using deleter_type = void(const basic_any &);
- template<typename Type>
- static constexpr bool in_situ_v = internal::in_situ<Type, Len, Align>::value;
- template<typename Type>
- static const void *basic_vtable(const request req, const basic_any &value, const void *other) {
- static_assert(std::is_same_v<std::remove_const_t<std::remove_reference_t<Type>>, Type>, "Invalid type");
- switch(const auto *elem = static_cast<const Type *>(value.data()); req) {
- case request::info:
- return &type_id<Type>();
- case request::transfer:
- if constexpr(std::is_move_assignable_v<Type>) {
- // NOLINTNEXTLINE(bugprone-casting-through-void)
- *const_cast<Type *>(elem) = std::move(*static_cast<Type *>(const_cast<void *>(other)));
- return other;
- }
- [[fallthrough]];
- case request::assign:
- if constexpr(std::is_copy_assignable_v<Type>) {
- *const_cast<Type *>(elem) = *static_cast<const Type *>(other);
- return other;
- }
- break;
- case request::compare:
- if constexpr(!std::is_function_v<Type> && !std::is_array_v<Type> && is_equality_comparable_v<Type>) {
- return (*elem == *static_cast<const Type *>(other)) ? other : nullptr;
- } else {
- return (elem == other) ? other : nullptr;
- }
- case request::copy:
- if constexpr(std::is_copy_constructible_v<Type>) {
- // NOLINTNEXTLINE(bugprone-casting-through-void)
- static_cast<basic_any *>(const_cast<void *>(other))->initialize<Type>(*elem);
- }
- break;
- case request::move:
- ENTT_ASSERT(value.mode == any_policy::embedded, "Unexpected policy");
- if constexpr(in_situ_v<Type>) {
- // NOLINTNEXTLINE(bugprone-casting-through-void, bugprone-multi-level-implicit-pointer-conversion)
- return ::new(&static_cast<basic_any *>(const_cast<void *>(other))->buffer) Type{std::move(*const_cast<Type *>(elem))};
- }
- }
- return nullptr;
- }
- template<typename Type>
- static void basic_deleter(const basic_any &value) {
- static_assert(std::is_same_v<std::remove_const_t<std::remove_reference_t<Type>>, Type>, "Invalid type");
- ENTT_ASSERT((value.mode == any_policy::dynamic) || ((value.mode == any_policy::embedded) && !std::is_trivially_destructible_v<Type>), "Unexpected policy");
- const auto *elem = static_cast<const Type *>(value.data());
- if constexpr(in_situ_v<Type>) {
- (value.mode == any_policy::embedded) ? elem->~Type() : (delete elem);
- } else if constexpr(std::is_array_v<Type>) {
- delete[] elem;
- } else {
- delete elem;
- }
- }
- template<typename Type, typename... Args>
- void initialize([[maybe_unused]] Args &&...args) {
- using plain_type = std::remove_const_t<std::remove_reference_t<Type>>;
- vtable = basic_vtable<plain_type>;
- underlying_type = type_hash<plain_type>::value();
- if constexpr(std::is_void_v<Type>) {
- deleter = nullptr;
- mode = any_policy::empty;
- this->instance = nullptr;
- } else if constexpr(std::is_lvalue_reference_v<Type>) {
- deleter = nullptr;
- mode = std::is_const_v<std::remove_reference_t<Type>> ? any_policy::cref : any_policy::ref;
- static_assert((std::is_lvalue_reference_v<Args> && ...) && (sizeof...(Args) == 1u), "Invalid arguments");
- // NOLINTNEXTLINE(bugprone-multi-level-implicit-pointer-conversion)
- this->instance = (std::addressof(args), ...);
- } else if constexpr(in_situ_v<plain_type>) {
- if constexpr(std::is_trivially_destructible_v<plain_type>) {
- deleter = nullptr;
- } else {
- deleter = &basic_deleter<plain_type>;
- }
- mode = any_policy::embedded;
- if constexpr(std::is_aggregate_v<plain_type> && (sizeof...(Args) != 0u || !std::is_default_constructible_v<plain_type>)) {
- ::new(&this->buffer) plain_type{std::forward<Args>(args)...};
- } else {
- // NOLINTNEXTLINE(cppcoreguidelines-pro-bounds-array-to-pointer-decay)
- ::new(&this->buffer) plain_type(std::forward<Args>(args)...);
- }
- } else {
- deleter = &basic_deleter<plain_type>;
- mode = any_policy::dynamic;
- if constexpr(std::is_aggregate_v<plain_type> && (sizeof...(Args) != 0u || !std::is_default_constructible_v<plain_type>)) {
- this->instance = new plain_type{std::forward<Args>(args)...};
- } else if constexpr(std::is_array_v<plain_type>) {
- static_assert(sizeof...(Args) == 0u, "Invalid arguments");
- this->instance = new plain_type[std::extent_v<plain_type>]();
- } else {
- this->instance = new plain_type(std::forward<Args>(args)...);
- }
- }
- }
- void invoke_deleter_if_exists() {
- if(deleter != nullptr) {
- deleter(*this);
- }
- }
- public:
- /*! @brief Size of the internal buffer. */
- static constexpr auto length = Len;
- /*! @brief Alignment requirement. */
- static constexpr auto alignment = Align;
- /*! @brief Default constructor. */
- constexpr basic_any() noexcept
- : basic_any{std::in_place_type<void>} {}
- /**
- * @brief Constructs a wrapper by directly initializing the new object.
- * @tparam Type Type of object to use to initialize the wrapper.
- * @tparam Args Types of arguments to use to construct the new instance.
- * @param args Parameters to use to construct the instance.
- */
- template<typename Type, typename... Args>
- explicit basic_any(std::in_place_type_t<Type>, Args &&...args)
- : base_type{} {
- initialize<Type>(std::forward<Args>(args)...);
- }
- /**
- * @brief Constructs a wrapper taking ownership of the passed object.
- * @tparam Type Type of object to use to initialize the wrapper.
- * @param value A pointer to an object to take ownership of.
- */
- template<typename Type>
- explicit basic_any(std::in_place_t, Type *value)
- : base_type{} {
- static_assert(!std::is_const_v<Type> && !std::is_void_v<Type>, "Non-const non-void pointer required");
- if(value == nullptr) {
- initialize<void>();
- } else {
- initialize<Type &>(*value);
- deleter = &basic_deleter<Type>;
- mode = any_policy::dynamic;
- }
- }
- /**
- * @brief Constructs a wrapper from a given value.
- * @tparam Type Type of object to use to initialize the wrapper.
- * @param value An instance of an object to use to initialize the wrapper.
- */
- template<typename Type, typename = std::enable_if_t<!std::is_same_v<std::decay_t<Type>, basic_any>>>
- basic_any(Type &&value)
- : basic_any{std::in_place_type<std::decay_t<Type>>, std::forward<Type>(value)} {}
- /**
- * @brief Copy constructor.
- * @param other The instance to copy from.
- */
- basic_any(const basic_any &other)
- : basic_any{} {
- other.vtable(request::copy, other, this);
- }
- /**
- * @brief Move constructor.
- * @param other The instance to move from.
- */
- basic_any(basic_any &&other) noexcept
- : base_type{},
- vtable{other.vtable},
- deleter{other.deleter},
- underlying_type{other.underlying_type},
- mode{other.mode} {
- if(other.mode == any_policy::embedded) {
- other.vtable(request::move, other, this);
- } else if(other.mode != any_policy::empty) {
- this->instance = std::exchange(other.instance, nullptr);
- }
- }
- /*! @brief Frees the internal buffer, whatever it means. */
- ~basic_any() {
- invoke_deleter_if_exists();
- }
- /**
- * @brief Copy assignment operator.
- * @param other The instance to copy from.
- * @return This any object.
- */
- basic_any &operator=(const basic_any &other) {
- if(this != &other) {
- invoke_deleter_if_exists();
- if(other) {
- other.vtable(request::copy, other, this);
- } else {
- initialize<void>();
- }
- }
- return *this;
- }
- /**
- * @brief Move assignment operator.
- * @param other The instance to move from.
- * @return This any object.
- */
- basic_any &operator=(basic_any &&other) noexcept {
- if(this != &other) {
- invoke_deleter_if_exists();
- if(other.mode == any_policy::embedded) {
- other.vtable(request::move, other, this);
- } else if(other.mode != any_policy::empty) {
- this->instance = std::exchange(other.instance, nullptr);
- }
- vtable = other.vtable;
- deleter = other.deleter;
- underlying_type = other.underlying_type;
- mode = other.mode;
- }
- return *this;
- }
- /**
- * @brief Value assignment operator.
- * @tparam Type Type of object to use to initialize the wrapper.
- * @param value An instance of an object to use to initialize the wrapper.
- * @return This any object.
- */
- template<typename Type, typename = std::enable_if_t<!std::is_same_v<std::decay_t<Type>, basic_any>>>
- basic_any &operator=(Type &&value) {
- emplace<std::decay_t<Type>>(std::forward<Type>(value));
- return *this;
- }
- /**
- * @brief Returns false if a wrapper is empty, true otherwise.
- * @return False if the wrapper is empty, true otherwise.
- */
- [[nodiscard]] bool has_value() const noexcept {
- return (mode != any_policy::empty);
- }
- /**
- * @brief Returns false if the wrapper does not contain the expected type,
- * true otherwise.
- * @param req Expected type.
- * @return False if the wrapper does not contain the expected type, true
- * otherwise.
- */
- [[nodiscard]] bool has_value(const type_info &req) const noexcept {
- return (underlying_type == req.hash());
- }
- /**
- * @brief Returns false if the wrapper does not contain the expected type,
- * true otherwise.
- * @tparam Type Expected type.
- * @return False if the wrapper does not contain the expected type, true
- * otherwise.
- */
- template<typename Type>
- [[nodiscard]] bool has_value() const noexcept {
- static_assert(std::is_same_v<std::remove_const_t<Type>, Type>, "Invalid type");
- return (underlying_type == type_hash<Type>::value());
- }
- /**
- * @brief Returns the object type info if any, `type_id<void>()` otherwise.
- * @return The object type info if any, `type_id<void>()` otherwise.
- */
- [[nodiscard]] const type_info &info() const noexcept {
- return *static_cast<const type_info *>(vtable(request::info, *this, nullptr));
- }
- /*! @copydoc info */
- [[deprecated("use ::info instead")]] [[nodiscard]] const type_info &type() const noexcept {
- return info();
- }
- /**
- * @brief Returns an opaque pointer to the contained instance.
- * @return An opaque pointer the contained instance, if any.
- */
- [[nodiscard]] const void *data() const noexcept {
- if constexpr(base_type::has_buffer) {
- return (mode == any_policy::embedded) ? &this->buffer : this->instance;
- } else {
- return this->instance;
- }
- }
- /**
- * @brief Returns an opaque pointer to the contained instance.
- * @param req Expected type.
- * @return An opaque pointer the contained instance, if any.
- */
- [[nodiscard]] const void *data(const type_info &req) const noexcept {
- return has_value(req) ? data() : nullptr;
- }
- /**
- * @brief Returns an opaque pointer to the contained instance.
- * @tparam Type Expected type.
- * @return An opaque pointer the contained instance, if any.
- */
- template<typename Type>
- [[nodiscard]] const Type *data() const noexcept {
- return has_value<std::remove_const_t<Type>>() ? static_cast<const Type *>(data()) : nullptr;
- }
- /**
- * @brief Returns an opaque pointer to the contained instance.
- * @return An opaque pointer the contained instance, if any.
- */
- [[nodiscard]] void *data() noexcept {
- return (mode == any_policy::cref) ? nullptr : const_cast<void *>(std::as_const(*this).data());
- }
- /**
- * @brief Returns an opaque pointer to the contained instance.
- * @param req Expected type.
- * @return An opaque pointer the contained instance, if any.
- */
- [[nodiscard]] void *data(const type_info &req) noexcept {
- return (mode == any_policy::cref) ? nullptr : const_cast<void *>(std::as_const(*this).data(req));
- }
- /**
- * @brief Returns an opaque pointer to the contained instance.
- * @tparam Type Expected type.
- * @return An opaque pointer the contained instance, if any.
- */
- template<typename Type>
- [[nodiscard]] Type *data() noexcept {
- if constexpr(std::is_const_v<Type>) {
- return std::as_const(*this).template data<std::remove_const_t<Type>>();
- } else {
- return (mode == any_policy::cref) ? nullptr : const_cast<Type *>(std::as_const(*this).template data<std::remove_const_t<Type>>());
- }
- }
- /**
- * @brief Replaces the contained object by creating a new instance directly.
- * @tparam Type Type of object to use to initialize the wrapper.
- * @tparam Args Types of arguments to use to construct the new instance.
- * @param args Parameters to use to construct the instance.
- */
- template<typename Type, typename... Args>
- void emplace(Args &&...args) {
- invoke_deleter_if_exists();
- initialize<Type>(std::forward<Args>(args)...);
- }
- /**
- * @brief Assigns a value to the contained object without replacing it.
- * @param other The value to assign to the contained object.
- * @return True in case of success, false otherwise.
- */
- bool assign(const basic_any &other) {
- if(other && (mode != any_policy::cref) && (underlying_type == other.underlying_type)) {
- return (vtable(request::assign, *this, other.data()) != nullptr);
- }
- return false;
- }
- /*! @copydoc assign */
- // NOLINTNEXTLINE(cppcoreguidelines-rvalue-reference-param-not-moved)
- bool assign(basic_any &&other) {
- if(other && (mode != any_policy::cref) && (underlying_type == other.underlying_type)) {
- return (other.mode == any_policy::cref) ? (vtable(request::assign, *this, std::as_const(other).data()) != nullptr) : (vtable(request::transfer, *this, other.data()) != nullptr);
- }
- return false;
- }
- /*! @brief Destroys contained object */
- void reset() {
- invoke_deleter_if_exists();
- initialize<void>();
- }
- /**
- * @brief Returns false if a wrapper is empty, true otherwise.
- * @return False if the wrapper is empty, true otherwise.
- */
- [[nodiscard]] explicit operator bool() const noexcept {
- return has_value();
- }
- /**
- * @brief Checks if two wrappers differ in their content.
- * @param other Wrapper with which to compare.
- * @return False if the two objects differ in their content, true otherwise.
- */
- [[nodiscard]] bool operator==(const basic_any &other) const noexcept {
- if(other && (underlying_type == other.underlying_type)) {
- return (vtable(request::compare, *this, other.data()) != nullptr);
- }
- return (!*this && !other);
- }
- /**
- * @brief Checks if two wrappers differ in their content.
- * @param other Wrapper with which to compare.
- * @return True if the two objects differ in their content, false otherwise.
- */
- [[nodiscard]] bool operator!=(const basic_any &other) const noexcept {
- return !(*this == other);
- }
- /**
- * @brief Aliasing constructor.
- * @return A wrapper that shares a reference to an unmanaged object.
- */
- [[nodiscard]] basic_any as_ref() noexcept {
- basic_any other = std::as_const(*this).as_ref();
- other.mode = (mode == any_policy::cref ? any_policy::cref : any_policy::ref);
- return other;
- }
- /*! @copydoc as_ref */
- [[nodiscard]] basic_any as_ref() const noexcept {
- basic_any other{};
- other.instance = data();
- other.vtable = vtable;
- other.underlying_type = underlying_type;
- other.mode = any_policy::cref;
- return other;
- }
- /**
- * @brief Returns true if a wrapper owns its object, false otherwise.
- * @return True if the wrapper owns its object, false otherwise.
- */
- [[nodiscard]] bool owner() const noexcept {
- return (mode == any_policy::dynamic || mode == any_policy::embedded);
- }
- /**
- * @brief Returns the current mode of an any object.
- * @return The current mode of the any object.
- */
- [[nodiscard]] any_policy policy() const noexcept {
- return mode;
- }
- private:
- vtable_type *vtable{};
- deleter_type *deleter{};
- id_type underlying_type{};
- any_policy mode{};
- };
- /**
- * @brief Performs type-safe access to the contained object.
- * @tparam Type Type to which conversion is required.
- * @tparam Len Size of the buffer reserved for the small buffer optimization.
- * @tparam Align Alignment requirement.
- * @param data Target any object.
- * @return The element converted to the requested type.
- */
- template<typename Type, std::size_t Len, std::size_t Align>
- [[nodiscard]] std::remove_const_t<Type> any_cast(const basic_any<Len, Align> &data) noexcept {
- const auto *const instance = any_cast<std::remove_reference_t<Type>>(&data);
- ENTT_ASSERT(instance, "Invalid instance");
- return static_cast<Type>(*instance);
- }
- /*! @copydoc any_cast */
- template<typename Type, std::size_t Len, std::size_t Align>
- [[nodiscard]] std::remove_const_t<Type> any_cast(basic_any<Len, Align> &data) noexcept {
- // forces const on non-reference types to make them work also with wrappers for const references
- auto *const instance = any_cast<std::remove_reference_t<const Type>>(&data);
- ENTT_ASSERT(instance, "Invalid instance");
- return static_cast<Type>(*instance);
- }
- /*! @copydoc any_cast */
- template<typename Type, std::size_t Len, std::size_t Align>
- // NOLINTNEXTLINE(cppcoreguidelines-rvalue-reference-param-not-moved)
- [[nodiscard]] std::remove_const_t<Type> any_cast(basic_any<Len, Align> &&data) noexcept {
- if constexpr(std::is_copy_constructible_v<std::remove_const_t<std::remove_reference_t<Type>>>) {
- if(auto *const instance = any_cast<std::remove_reference_t<Type>>(&data); instance) {
- return static_cast<Type>(std::move(*instance));
- }
- return any_cast<Type>(data);
- } else {
- auto *const instance = any_cast<std::remove_reference_t<Type>>(&data);
- ENTT_ASSERT(instance, "Invalid instance");
- return static_cast<Type>(std::move(*instance));
- }
- }
- /*! @copydoc any_cast */
- template<typename Type, std::size_t Len, std::size_t Align>
- [[nodiscard]] const Type *any_cast(const basic_any<Len, Align> *data) noexcept {
- return data->template data<std::remove_const_t<Type>>();
- }
- /*! @copydoc any_cast */
- template<typename Type, std::size_t Len, std::size_t Align>
- [[nodiscard]] Type *any_cast(basic_any<Len, Align> *data) noexcept {
- if constexpr(std::is_const_v<Type>) {
- // last attempt to make wrappers for const references return their values
- return any_cast<Type>(&std::as_const(*data));
- } else {
- return data->template data<Type>();
- }
- }
- /**
- * @brief Constructs a wrapper from a given type, passing it all arguments.
- * @tparam Type Type of object to use to initialize the wrapper.
- * @tparam Len Size of the buffer reserved for the small buffer optimization.
- * @tparam Align Optional alignment requirement.
- * @tparam Args Types of arguments to use to construct the new instance.
- * @param args Parameters to use to construct the instance.
- * @return A properly initialized wrapper for an object of the given type.
- */
- template<typename Type, std::size_t Len = basic_any<>::length, std::size_t Align = basic_any<Len>::alignment, typename... Args>
- [[nodiscard]] basic_any<Len, Align> make_any(Args &&...args) {
- return basic_any<Len, Align>{std::in_place_type<Type>, std::forward<Args>(args)...};
- }
- /**
- * @brief Forwards its argument and avoids copies for lvalue references.
- * @tparam Len Size of the buffer reserved for the small buffer optimization.
- * @tparam Align Optional alignment requirement.
- * @tparam Type Type of argument to use to construct the new instance.
- * @param value Parameter to use to construct the instance.
- * @return A properly initialized and not necessarily owning wrapper.
- */
- template<std::size_t Len = basic_any<>::length, std::size_t Align = basic_any<Len>::alignment, typename Type>
- [[nodiscard]] basic_any<Len, Align> forward_as_any(Type &&value) {
- return basic_any<Len, Align>{std::in_place_type<Type &&>, std::forward<Type>(value)};
- }
- } // namespace entt
- #endif
- // #include "../core/fwd.hpp"
- // #include "../core/iterator.hpp"
- #ifndef ENTT_CORE_ITERATOR_HPP
- #define ENTT_CORE_ITERATOR_HPP
- #include <iterator>
- #include <memory>
- #include <type_traits>
- #include <utility>
- namespace entt {
- /**
- * @brief Helper type to use as pointer with input iterators.
- * @tparam Type of wrapped value.
- */
- template<typename Type>
- struct input_iterator_pointer final {
- /*! @brief Value type. */
- using value_type = Type;
- /*! @brief Pointer type. */
- using pointer = Type *;
- /*! @brief Reference type. */
- using reference = Type &;
- /**
- * @brief Constructs a proxy object by move.
- * @param val Value to use to initialize the proxy object.
- */
- constexpr input_iterator_pointer(value_type &&val) noexcept(std::is_nothrow_move_constructible_v<value_type>)
- : value{std::move(val)} {}
- /**
- * @brief Access operator for accessing wrapped values.
- * @return A pointer to the wrapped value.
- */
- [[nodiscard]] constexpr pointer operator->() noexcept {
- return std::addressof(value);
- }
- /**
- * @brief Dereference operator for accessing wrapped values.
- * @return A reference to the wrapped value.
- */
- [[nodiscard]] constexpr reference operator*() noexcept {
- return value;
- }
- private:
- Type value;
- };
- /**
- * @brief Plain iota iterator (waiting for C++20).
- * @tparam Type Value type.
- */
- template<typename Type>
- class iota_iterator final {
- static_assert(std::is_integral_v<Type>, "Not an integral type");
- public:
- /*! @brief Value type, likely an integral one. */
- using value_type = Type;
- /*! @brief Invalid pointer type. */
- using pointer = void;
- /*! @brief Non-reference type, same as value type. */
- using reference = value_type;
- /*! @brief Difference type. */
- using difference_type = std::ptrdiff_t;
- /*! @brief Iterator category. */
- using iterator_category = std::input_iterator_tag;
- /*! @brief Default constructor. */
- constexpr iota_iterator() noexcept
- : current{} {}
- /**
- * @brief Constructs an iota iterator from a given value.
- * @param init The initial value assigned to the iota iterator.
- */
- constexpr iota_iterator(const value_type init) noexcept
- : current{init} {}
- /**
- * @brief Pre-increment operator.
- * @return This iota iterator.
- */
- constexpr iota_iterator &operator++() noexcept {
- return ++current, *this;
- }
- /**
- * @brief Post-increment operator.
- * @return This iota iterator.
- */
- constexpr iota_iterator operator++(int) noexcept {
- const iota_iterator orig = *this;
- return ++(*this), orig;
- }
- /**
- * @brief Dereference operator.
- * @return The underlying value.
- */
- [[nodiscard]] constexpr reference operator*() const noexcept {
- return current;
- }
- private:
- value_type current;
- };
- /**
- * @brief Comparison operator.
- * @tparam Type Value type of the iota iterator.
- * @param lhs A properly initialized iota iterator.
- * @param rhs A properly initialized iota iterator.
- * @return True if the two iterators are identical, false otherwise.
- */
- template<typename Type>
- [[nodiscard]] constexpr bool operator==(const iota_iterator<Type> &lhs, const iota_iterator<Type> &rhs) noexcept {
- return *lhs == *rhs;
- }
- /**
- * @brief Comparison operator.
- * @tparam Type Value type of the iota iterator.
- * @param lhs A properly initialized iota iterator.
- * @param rhs A properly initialized iota iterator.
- * @return True if the two iterators differ, false otherwise.
- */
- template<typename Type>
- [[nodiscard]] constexpr bool operator!=(const iota_iterator<Type> &lhs, const iota_iterator<Type> &rhs) noexcept {
- return !(lhs == rhs);
- }
- /**
- * @brief Utility class to create an iterable object from a pair of iterators.
- * @tparam It Type of iterator.
- * @tparam Sentinel Type of sentinel.
- */
- template<typename It, typename Sentinel = It>
- struct iterable_adaptor final {
- /*! @brief Value type. */
- using value_type = typename std::iterator_traits<It>::value_type;
- /*! @brief Iterator type. */
- using iterator = It;
- /*! @brief Sentinel type. */
- using sentinel = Sentinel;
- /*! @brief Default constructor. */
- constexpr iterable_adaptor() noexcept(std::is_nothrow_default_constructible_v<iterator> && std::is_nothrow_default_constructible_v<sentinel>)
- : first{},
- last{} {}
- /**
- * @brief Creates an iterable object from a pair of iterators.
- * @param from Begin iterator.
- * @param to End iterator.
- */
- constexpr iterable_adaptor(iterator from, sentinel to) noexcept(std::is_nothrow_move_constructible_v<iterator> && std::is_nothrow_move_constructible_v<sentinel>)
- : first{std::move(from)},
- last{std::move(to)} {}
- /**
- * @brief Returns an iterator to the beginning.
- * @return An iterator to the first element of the range.
- */
- [[nodiscard]] constexpr iterator begin() const noexcept {
- return first;
- }
- /**
- * @brief Returns an iterator to the end.
- * @return An iterator to the element following the last element of the
- * range.
- */
- [[nodiscard]] constexpr sentinel end() const noexcept {
- return last;
- }
- /*! @copydoc begin */
- [[nodiscard]] constexpr iterator cbegin() const noexcept {
- return begin();
- }
- /*! @copydoc end */
- [[nodiscard]] constexpr sentinel cend() const noexcept {
- return end();
- }
- private:
- It first;
- Sentinel last;
- };
- } // namespace entt
- #endif
- // #include "../core/type_info.hpp"
- #ifndef ENTT_CORE_TYPE_INFO_HPP
- #define ENTT_CORE_TYPE_INFO_HPP
- #include <string_view>
- #include <type_traits>
- #include <utility>
- // #include "../config/config.h"
- // #include "fwd.hpp"
- // #include "hashed_string.hpp"
- namespace entt {
- /*! @cond TURN_OFF_DOXYGEN */
- namespace internal {
- struct ENTT_API type_index final {
- [[nodiscard]] static id_type next() noexcept {
- static ENTT_MAYBE_ATOMIC(id_type) value{};
- return value++;
- }
- };
- template<typename Type>
- [[nodiscard]] constexpr const char *pretty_function() noexcept {
- #if defined ENTT_PRETTY_FUNCTION
- return static_cast<const char *>(ENTT_PRETTY_FUNCTION);
- #else
- return "";
- #endif
- }
- template<typename Type>
- [[nodiscard]] constexpr auto stripped_type_name() noexcept {
- #if defined ENTT_PRETTY_FUNCTION
- const std::string_view full_name{pretty_function<Type>()};
- auto first = full_name.find_first_not_of(' ', full_name.find_first_of(ENTT_PRETTY_FUNCTION_PREFIX) + 1);
- auto value = full_name.substr(first, full_name.find_last_of(ENTT_PRETTY_FUNCTION_SUFFIX) - first);
- return value;
- #else
- return std::string_view{};
- #endif
- }
- template<typename Type, auto = stripped_type_name<Type>().find_first_of('.')>
- [[nodiscard]] constexpr std::string_view type_name(int) noexcept {
- constexpr auto value = stripped_type_name<Type>();
- return value;
- }
- template<typename Type>
- [[nodiscard]] std::string_view type_name(char) noexcept {
- static const auto value = stripped_type_name<Type>();
- return value;
- }
- template<typename Type, auto = stripped_type_name<Type>().find_first_of('.')>
- [[nodiscard]] constexpr id_type type_hash(int) noexcept {
- constexpr auto stripped = stripped_type_name<Type>();
- constexpr auto value = hashed_string::value(stripped.data(), stripped.size());
- return value;
- }
- template<typename Type>
- [[nodiscard]] id_type type_hash(char) noexcept {
- static const auto value = [](const auto stripped) {
- return hashed_string::value(stripped.data(), stripped.size());
- }(stripped_type_name<Type>());
- return value;
- }
- } // namespace internal
- /*! @endcond */
- /**
- * @brief Type sequential identifier.
- * @tparam Type Type for which to generate a sequential identifier.
- */
- template<typename Type, typename = void>
- struct ENTT_API type_index final {
- /**
- * @brief Returns the sequential identifier of a given type.
- * @return The sequential identifier of a given type.
- */
- [[nodiscard]] static id_type value() noexcept {
- static const id_type value = internal::type_index::next();
- return value;
- }
- /*! @copydoc value */
- [[nodiscard]] constexpr operator id_type() const noexcept {
- return value();
- }
- };
- /**
- * @brief Type hash.
- * @tparam Type Type for which to generate a hash value.
- */
- template<typename Type, typename = void>
- struct type_hash final {
- /**
- * @brief Returns the numeric representation of a given type.
- * @return The numeric representation of the given type.
- */
- #if defined ENTT_PRETTY_FUNCTION
- [[nodiscard]] static constexpr id_type value() noexcept {
- return internal::type_hash<Type>(0);
- #else
- [[nodiscard]] static constexpr id_type value() noexcept {
- return type_index<Type>::value();
- #endif
- }
- /*! @copydoc value */
- [[nodiscard]] constexpr operator id_type() const noexcept {
- return value();
- }
- };
- /**
- * @brief Type name.
- * @tparam Type Type for which to generate a name.
- */
- template<typename Type, typename = void>
- struct type_name final {
- /**
- * @brief Returns the name of a given type.
- * @return The name of the given type.
- */
- [[nodiscard]] static constexpr std::string_view value() noexcept {
- return internal::type_name<Type>(0);
- }
- /*! @copydoc value */
- [[nodiscard]] constexpr operator std::string_view() const noexcept {
- return value();
- }
- };
- /*! @brief Implementation specific information about a type. */
- struct type_info final {
- /**
- * @brief Constructs a type info object for a given type.
- * @tparam Type Type for which to construct a type info object.
- */
- template<typename Type>
- // NOLINTBEGIN(modernize-use-transparent-functors)
- constexpr type_info(std::in_place_type_t<Type>) noexcept
- : seq{type_index<std::remove_const_t<std::remove_reference_t<Type>>>::value()},
- identifier{type_hash<std::remove_const_t<std::remove_reference_t<Type>>>::value()},
- alias{type_name<std::remove_const_t<std::remove_reference_t<Type>>>::value()} {}
- // NOLINTEND(modernize-use-transparent-functors)
- /**
- * @brief Type index.
- * @return Type index.
- */
- [[nodiscard]] constexpr id_type index() const noexcept {
- return seq;
- }
- /**
- * @brief Type hash.
- * @return Type hash.
- */
- [[nodiscard]] constexpr id_type hash() const noexcept {
- return identifier;
- }
- /**
- * @brief Type name.
- * @return Type name.
- */
- [[nodiscard]] constexpr std::string_view name() const noexcept {
- return alias;
- }
- private:
- id_type seq;
- id_type identifier;
- std::string_view alias;
- };
- /**
- * @brief Compares the contents of two type info objects.
- * @param lhs A type info object.
- * @param rhs A type info object.
- * @return True if the two type info objects are identical, false otherwise.
- */
- [[nodiscard]] constexpr bool operator==(const type_info &lhs, const type_info &rhs) noexcept {
- return lhs.hash() == rhs.hash();
- }
- /**
- * @brief Compares the contents of two type info objects.
- * @param lhs A type info object.
- * @param rhs A type info object.
- * @return True if the two type info objects differ, false otherwise.
- */
- [[nodiscard]] constexpr bool operator!=(const type_info &lhs, const type_info &rhs) noexcept {
- return !(lhs == rhs);
- }
- /**
- * @brief Compares two type info objects.
- * @param lhs A valid type info object.
- * @param rhs A valid type info object.
- * @return True if the first element is less than the second, false otherwise.
- */
- [[nodiscard]] constexpr bool operator<(const type_info &lhs, const type_info &rhs) noexcept {
- return lhs.index() < rhs.index();
- }
- /**
- * @brief Compares two type info objects.
- * @param lhs A valid type info object.
- * @param rhs A valid type info object.
- * @return True if the first element is less than or equal to the second, false
- * otherwise.
- */
- [[nodiscard]] constexpr bool operator<=(const type_info &lhs, const type_info &rhs) noexcept {
- return !(rhs < lhs);
- }
- /**
- * @brief Compares two type info objects.
- * @param lhs A valid type info object.
- * @param rhs A valid type info object.
- * @return True if the first element is greater than the second, false
- * otherwise.
- */
- [[nodiscard]] constexpr bool operator>(const type_info &lhs, const type_info &rhs) noexcept {
- return rhs < lhs;
- }
- /**
- * @brief Compares two type info objects.
- * @param lhs A valid type info object.
- * @param rhs A valid type info object.
- * @return True if the first element is greater than or equal to the second,
- * false otherwise.
- */
- [[nodiscard]] constexpr bool operator>=(const type_info &lhs, const type_info &rhs) noexcept {
- return !(lhs < rhs);
- }
- /**
- * @brief Returns the type info object associated to a given type.
- *
- * The returned element refers to an object with static storage duration.<br/>
- * The type doesn't need to be a complete type. If the type is a reference, the
- * result refers to the referenced type. In all cases, top-level cv-qualifiers
- * are ignored.
- *
- * @tparam Type Type for which to generate a type info object.
- * @return A reference to a properly initialized type info object.
- */
- template<typename Type>
- [[nodiscard]] const type_info &type_id() noexcept {
- if constexpr(std::is_same_v<Type, std::remove_const_t<std::remove_reference_t<Type>>>) {
- static const type_info instance{std::in_place_type<Type>};
- return instance;
- } else {
- return type_id<std::remove_const_t<std::remove_reference_t<Type>>>();
- }
- }
- /*! @copydoc type_id */
- template<typename Type>
- // NOLINTNEXTLINE(cppcoreguidelines-missing-std-forward)
- [[nodiscard]] const type_info &type_id(Type &&) noexcept {
- return type_id<std::remove_const_t<std::remove_reference_t<Type>>>();
- }
- } // namespace entt
- #endif
- // #include "../core/type_traits.hpp"
- // #include "../core/utility.hpp"
- // #include "../locator/locator.hpp"
- #ifndef ENTT_LOCATOR_LOCATOR_HPP
- #define ENTT_LOCATOR_LOCATOR_HPP
- #include <memory>
- #include <utility>
- // #include "../config/config.h"
- #ifndef ENTT_CONFIG_CONFIG_H
- #define ENTT_CONFIG_CONFIG_H
- // #include "version.h"
- #ifndef ENTT_CONFIG_VERSION_H
- #define ENTT_CONFIG_VERSION_H
- // #include "macro.h"
- #ifndef ENTT_CONFIG_MACRO_H
- #define ENTT_CONFIG_MACRO_H
- // NOLINTBEGIN(cppcoreguidelines-macro-usage)
- #define ENTT_STR(arg) #arg
- #define ENTT_XSTR(arg) ENTT_STR(arg)
- // NOLINTEND(cppcoreguidelines-macro-usage)
- #endif
- // NOLINTBEGIN(cppcoreguidelines-macro-*,modernize-macro-*)
- #define ENTT_VERSION_MAJOR 3
- #define ENTT_VERSION_MINOR 16
- #define ENTT_VERSION_PATCH 0
- #define ENTT_VERSION \
- ENTT_XSTR(ENTT_VERSION_MAJOR) \
- "." ENTT_XSTR(ENTT_VERSION_MINOR) "." ENTT_XSTR(ENTT_VERSION_PATCH)
- // NOLINTEND(cppcoreguidelines-macro-*,modernize-macro-*)
- #endif
- // NOLINTBEGIN(cppcoreguidelines-macro-usage)
- #if defined(__cpp_exceptions) && !defined(ENTT_NOEXCEPTION)
- # define ENTT_CONSTEXPR
- # define ENTT_THROW throw
- # define ENTT_TRY try
- # define ENTT_CATCH catch(...)
- #else
- # define ENTT_CONSTEXPR constexpr // use only with throwing functions (waiting for C++20)
- # define ENTT_THROW
- # define ENTT_TRY if(true)
- # define ENTT_CATCH if(false)
- #endif
- #if __has_include(<version>)
- # include <version>
- #
- # if defined(__cpp_consteval)
- # define ENTT_CONSTEVAL consteval
- # endif
- #endif
- #ifndef ENTT_CONSTEVAL
- # define ENTT_CONSTEVAL constexpr
- #endif
- #ifdef ENTT_USE_ATOMIC
- # include <atomic>
- # define ENTT_MAYBE_ATOMIC(Type) std::atomic<Type>
- #else
- # define ENTT_MAYBE_ATOMIC(Type) Type
- #endif
- #ifndef ENTT_ID_TYPE
- # include <cstdint>
- # define ENTT_ID_TYPE std::uint32_t
- #else
- # include <cstdint> // provides coverage for types in the std namespace
- #endif
- #ifndef ENTT_SPARSE_PAGE
- # define ENTT_SPARSE_PAGE 4096
- #endif
- #ifndef ENTT_PACKED_PAGE
- # define ENTT_PACKED_PAGE 1024
- #endif
- #ifdef ENTT_DISABLE_ASSERT
- # undef ENTT_ASSERT
- # define ENTT_ASSERT(condition, msg) (void(0))
- #elif !defined ENTT_ASSERT
- # include <cassert>
- # define ENTT_ASSERT(condition, msg) assert(((condition) && (msg)))
- #endif
- #ifdef ENTT_DISABLE_ASSERT
- # undef ENTT_ASSERT_CONSTEXPR
- # define ENTT_ASSERT_CONSTEXPR(condition, msg) (void(0))
- #elif !defined ENTT_ASSERT_CONSTEXPR
- # define ENTT_ASSERT_CONSTEXPR(condition, msg) ENTT_ASSERT(condition, msg)
- #endif
- #define ENTT_FAIL(msg) ENTT_ASSERT(false, msg);
- #ifdef ENTT_NO_ETO
- # define ENTT_ETO_TYPE(Type) void
- #else
- # define ENTT_ETO_TYPE(Type) Type
- #endif
- #ifdef ENTT_NO_MIXIN
- # define ENTT_STORAGE(Mixin, ...) __VA_ARGS__
- #else
- # define ENTT_STORAGE(Mixin, ...) Mixin<__VA_ARGS__>
- #endif
- #ifdef ENTT_STANDARD_CPP
- # define ENTT_NONSTD false
- #else
- # define ENTT_NONSTD true
- # if defined __clang__ || defined __GNUC__
- # define ENTT_PRETTY_FUNCTION __PRETTY_FUNCTION__
- # define ENTT_PRETTY_FUNCTION_PREFIX '='
- # define ENTT_PRETTY_FUNCTION_SUFFIX ']'
- # elif defined _MSC_VER
- # define ENTT_PRETTY_FUNCTION __FUNCSIG__
- # define ENTT_PRETTY_FUNCTION_PREFIX '<'
- # define ENTT_PRETTY_FUNCTION_SUFFIX '>'
- # endif
- #endif
- #ifndef ENTT_EXPORT
- # if defined _WIN32 || defined __CYGWIN__ || defined _MSC_VER
- # define ENTT_EXPORT __declspec(dllexport)
- # define ENTT_IMPORT __declspec(dllimport)
- # define ENTT_HIDDEN
- # elif defined __GNUC__ && __GNUC__ >= 4
- # define ENTT_EXPORT __attribute__((visibility("default")))
- # define ENTT_IMPORT __attribute__((visibility("default")))
- # define ENTT_HIDDEN __attribute__((visibility("hidden")))
- # else /* Unsupported compiler */
- # define ENTT_EXPORT
- # define ENTT_IMPORT
- # define ENTT_HIDDEN
- # endif
- #endif
- #ifndef ENTT_API
- # if defined ENTT_API_EXPORT
- # define ENTT_API ENTT_EXPORT
- # elif defined ENTT_API_IMPORT
- # define ENTT_API ENTT_IMPORT
- # else /* No API */
- # define ENTT_API
- # endif
- #endif
- #if defined _MSC_VER
- # pragma detect_mismatch("entt.version", ENTT_VERSION)
- # pragma detect_mismatch("entt.noexcept", ENTT_XSTR(ENTT_TRY))
- # pragma detect_mismatch("entt.id", ENTT_XSTR(ENTT_ID_TYPE))
- # pragma detect_mismatch("entt.nonstd", ENTT_XSTR(ENTT_NONSTD))
- #endif
- // NOLINTEND(cppcoreguidelines-macro-usage)
- #endif
- namespace entt {
- /**
- * @brief Service locator, nothing more.
- *
- * A service locator is used to do what it promises: locate services.<br/>
- * Usually service locators are tightly bound to the services they expose and
- * thus it's hard to define a general purpose class to do that. This tiny class
- * tries to fill the gap and to get rid of the burden of defining a different
- * specific locator for each application.
- *
- * @note
- * Users shouldn't retain references to a service. The recommended way is to
- * retrieve the service implementation currently set each and every time the
- * need for it arises. The risk is to incur in unexpected behaviors otherwise.
- *
- * @tparam Service Service type.
- */
- template<typename Service>
- class locator final {
- class service_handle {
- friend class locator<Service>;
- std::shared_ptr<Service> value{};
- };
- public:
- /*! @brief Service type. */
- using type = Service;
- /*! @brief Service node type. */
- using node_type = service_handle;
- /*! @brief Default constructor, deleted on purpose. */
- locator() = delete;
- /*! @brief Default copy constructor, deleted on purpose. */
- locator(const locator &) = delete;
- /*! @brief Default destructor, deleted on purpose. */
- ~locator() = delete;
- /**
- * @brief Default copy assignment operator, deleted on purpose.
- * @return This locator.
- */
- locator &operator=(const locator &) = delete;
- /**
- * @brief Checks whether a service locator contains a value.
- * @return True if the service locator contains a value, false otherwise.
- */
- [[nodiscard]] static bool has_value() noexcept {
- return (service != nullptr);
- }
- /**
- * @brief Returns a reference to a valid service, if any.
- *
- * @warning
- * Invoking this function can result in undefined behavior if the service
- * hasn't been set yet.
- *
- * @return A reference to the service currently set, if any.
- */
- [[nodiscard]] static Service &value() noexcept {
- ENTT_ASSERT(has_value(), "Service not available");
- return *service;
- }
- /**
- * @brief Returns a service if available or sets it from a fallback type.
- *
- * Arguments are used only if a service doesn't already exist. In all other
- * cases, they are discarded.
- *
- * @tparam Args Types of arguments to use to construct the fallback service.
- * @tparam Type Fallback service type.
- * @param args Parameters to use to construct the fallback service.
- * @return A reference to a valid service.
- */
- template<typename Type = Service, typename... Args>
- [[nodiscard]] static Service &value_or(Args &&...args) {
- return service ? *service : emplace<Type>(std::forward<Args>(args)...);
- }
- /**
- * @brief Sets or replaces a service.
- * @tparam Type Service type.
- * @tparam Args Types of arguments to use to construct the service.
- * @param args Parameters to use to construct the service.
- * @return A reference to a valid service.
- */
- template<typename Type = Service, typename... Args>
- static Service &emplace(Args &&...args) {
- service = std::make_shared<Type>(std::forward<Args>(args)...);
- return *service;
- }
- /**
- * @brief Sets or replaces a service using a given allocator.
- * @tparam Type Service type.
- * @tparam Allocator Type of allocator used to manage memory and elements.
- * @tparam Args Types of arguments to use to construct the service.
- * @param alloc The allocator to use.
- * @param args Parameters to use to construct the service.
- * @return A reference to a valid service.
- */
- template<typename Type = Service, typename Allocator, typename... Args>
- static Service &emplace(std::allocator_arg_t, Allocator alloc, Args &&...args) {
- service = std::allocate_shared<Type>(alloc, std::forward<Args>(args)...);
- return *service;
- }
- /**
- * @brief Returns a handle to the underlying service.
- * @return A handle to the underlying service.
- */
- static node_type handle() noexcept {
- node_type node{};
- node.value = service;
- return node;
- }
- /**
- * @brief Resets or replaces a service.
- * @param other Optional handle with which to replace the service.
- */
- static void reset(const node_type &other = {}) noexcept {
- service = other.value;
- }
- /**
- * @brief Resets or replaces a service.
- * @tparam Type Service type.
- * @tparam Deleter Deleter type.
- * @param elem A pointer to a service to manage.
- * @param deleter A deleter to use to destroy the service.
- */
- template<typename Type, typename Deleter = std::default_delete<Type>>
- static void reset(Type *elem, Deleter deleter = {}) {
- service = std::shared_ptr<Service>{elem, std::move(deleter)};
- }
- private:
- // std::shared_ptr because of its type erased allocator which is useful here
- // NOLINTNEXTLINE(cppcoreguidelines-avoid-non-const-global-variables)
- inline static std::shared_ptr<Service> service{};
- };
- } // namespace entt
- #endif
- // #include "adl_pointer.hpp"
- #ifndef ENTT_META_ADL_POINTER_HPP
- #define ENTT_META_ADL_POINTER_HPP
- namespace entt {
- /**
- * @brief ADL based lookup function for dereferencing meta pointer-like types.
- * @tparam Type Element type.
- * @param value A pointer-like object.
- * @return The value returned from the dereferenced pointer.
- */
- template<typename Type>
- decltype(auto) dereference_meta_pointer_like(const Type &value) {
- return *value;
- }
- /**
- * @brief Fake ADL based lookup function for meta pointer-like types.
- * @tparam Type Element type.
- */
- template<typename Type>
- struct adl_meta_pointer_like {
- /**
- * @brief Uses the default ADL based lookup method to resolve the call.
- * @param value A pointer-like object.
- * @return The value returned from the dereferenced pointer.
- */
- static decltype(auto) dereference(const Type &value) {
- return dereference_meta_pointer_like(value);
- }
- };
- } // namespace entt
- #endif
- // #include "context.hpp"
- // #include "fwd.hpp"
- // #include "node.hpp"
- #ifndef ENTT_META_NODE_HPP
- #define ENTT_META_NODE_HPP
- #include <array>
- #include <cstddef>
- #include <memory>
- #include <type_traits>
- #include <utility>
- #include <vector>
- // #include "../config/config.h"
- // #include "../core/bit.hpp"
- #ifndef ENTT_CORE_BIT_HPP
- #define ENTT_CORE_BIT_HPP
- #include <cstddef>
- #include <limits>
- #include <type_traits>
- // #include "../config/config.h"
- namespace entt {
- /**
- * @brief Returns the number of set bits in a value (waiting for C++20 and
- * `std::popcount`).
- * @tparam Type Unsigned integer type.
- * @param value A value of unsigned integer type.
- * @return The number of set bits in the value.
- */
- template<typename Type>
- [[nodiscard]] constexpr std::enable_if_t<std::is_unsigned_v<Type>, int> popcount(const Type value) noexcept {
- return value ? (int(value & 1) + popcount(static_cast<Type>(value >> 1))) : 0;
- }
- /**
- * @brief Checks whether a value is a power of two or not (waiting for C++20 and
- * `std::has_single_bit`).
- * @tparam Type Unsigned integer type.
- * @param value A value of unsigned integer type.
- * @return True if the value is a power of two, false otherwise.
- */
- template<typename Type>
- [[nodiscard]] constexpr std::enable_if_t<std::is_unsigned_v<Type>, bool> has_single_bit(const Type value) noexcept {
- return value && ((value & (value - 1)) == 0);
- }
- /**
- * @brief Computes the smallest power of two greater than or equal to a value
- * (waiting for C++20 and `std::bit_ceil`).
- * @tparam Type Unsigned integer type.
- * @param value A value of unsigned integer type.
- * @return The smallest power of two greater than or equal to the given value.
- */
- template<typename Type>
- [[nodiscard]] constexpr std::enable_if_t<std::is_unsigned_v<Type>, Type> next_power_of_two(const Type value) noexcept {
- // NOLINTNEXTLINE(bugprone-assert-side-effect)
- ENTT_ASSERT_CONSTEXPR(value < (Type{1u} << (std::numeric_limits<Type>::digits - 1)), "Numeric limits exceeded");
- Type curr = value - (value != 0u);
- for(int next = 1; next < std::numeric_limits<Type>::digits; next = next * 2) {
- curr |= (curr >> next);
- }
- return ++curr;
- }
- /**
- * @brief Fast module utility function (powers of two only).
- * @tparam Type Unsigned integer type.
- * @param value A value of unsigned integer type.
- * @param mod _Modulus_, it must be a power of two.
- * @return The common remainder.
- */
- template<typename Type>
- [[nodiscard]] constexpr std::enable_if_t<std::is_unsigned_v<Type>, Type> fast_mod(const Type value, const std::size_t mod) noexcept {
- ENTT_ASSERT_CONSTEXPR(has_single_bit(mod), "Value must be a power of two");
- return static_cast<Type>(value & (mod - 1u));
- }
- } // namespace entt
- #endif
- // #include "../core/enum.hpp"
- #ifndef ENTT_CORE_ENUM_HPP
- #define ENTT_CORE_ENUM_HPP
- #include <type_traits>
- namespace entt {
- /**
- * @brief Enable bitmask support for enum classes.
- * @tparam Type The enum type for which to enable bitmask support.
- */
- template<typename Type, typename = void>
- struct enum_as_bitmask: std::false_type {};
- /*! @copydoc enum_as_bitmask */
- template<typename Type>
- struct enum_as_bitmask<Type, std::void_t<decltype(Type::_entt_enum_as_bitmask)>>: std::is_enum<Type> {};
- /**
- * @brief Helper variable template.
- * @tparam Type The enum class type for which to enable bitmask support.
- */
- template<typename Type>
- inline constexpr bool enum_as_bitmask_v = enum_as_bitmask<Type>::value;
- } // namespace entt
- /**
- * @brief Operator available for enums for which bitmask support is enabled.
- * @tparam Type Enum class type.
- * @param lhs The first value to use.
- * @param rhs The second value to use.
- * @return The result of invoking the operator on the underlying types of the
- * two values provided.
- */
- template<typename Type>
- [[nodiscard]] constexpr std::enable_if_t<entt::enum_as_bitmask_v<Type>, Type>
- operator|(const Type lhs, const Type rhs) noexcept {
- return static_cast<Type>(static_cast<std::underlying_type_t<Type>>(lhs) | static_cast<std::underlying_type_t<Type>>(rhs));
- }
- /*! @copydoc operator| */
- template<typename Type>
- [[nodiscard]] constexpr std::enable_if_t<entt::enum_as_bitmask_v<Type>, Type>
- operator&(const Type lhs, const Type rhs) noexcept {
- return static_cast<Type>(static_cast<std::underlying_type_t<Type>>(lhs) & static_cast<std::underlying_type_t<Type>>(rhs));
- }
- /*! @copydoc operator| */
- template<typename Type>
- [[nodiscard]] constexpr std::enable_if_t<entt::enum_as_bitmask_v<Type>, Type>
- operator^(const Type lhs, const Type rhs) noexcept {
- return static_cast<Type>(static_cast<std::underlying_type_t<Type>>(lhs) ^ static_cast<std::underlying_type_t<Type>>(rhs));
- }
- /**
- * @brief Operator available for enums for which bitmask support is enabled.
- * @tparam Type Enum class type.
- * @param value The value to use.
- * @return The result of invoking the operator on the underlying types of the
- * value provided.
- */
- template<typename Type>
- [[nodiscard]] constexpr std::enable_if_t<entt::enum_as_bitmask_v<Type>, Type>
- operator~(const Type value) noexcept {
- return static_cast<Type>(~static_cast<std::underlying_type_t<Type>>(value));
- }
- /*! @copydoc operator~ */
- template<typename Type>
- [[nodiscard]] constexpr std::enable_if_t<entt::enum_as_bitmask_v<Type>, bool>
- operator!(const Type value) noexcept {
- return !static_cast<std::underlying_type_t<Type>>(value);
- }
- /*! @copydoc operator| */
- template<typename Type>
- constexpr std::enable_if_t<entt::enum_as_bitmask_v<Type>, Type &>
- operator|=(Type &lhs, const Type rhs) noexcept {
- return (lhs = (lhs | rhs));
- }
- /*! @copydoc operator| */
- template<typename Type>
- constexpr std::enable_if_t<entt::enum_as_bitmask_v<Type>, Type &>
- operator&=(Type &lhs, const Type rhs) noexcept {
- return (lhs = (lhs & rhs));
- }
- /*! @copydoc operator| */
- template<typename Type>
- constexpr std::enable_if_t<entt::enum_as_bitmask_v<Type>, Type &>
- operator^=(Type &lhs, const Type rhs) noexcept {
- return (lhs = (lhs ^ rhs));
- }
- #endif
- // #include "../core/fwd.hpp"
- // #include "../core/type_info.hpp"
- // #include "../core/type_traits.hpp"
- // #include "../core/utility.hpp"
- // #include "context.hpp"
- // #include "type_traits.hpp"
- #ifndef ENTT_META_TYPE_TRAITS_HPP
- #define ENTT_META_TYPE_TRAITS_HPP
- #include <type_traits>
- #include <utility>
- namespace entt {
- /**
- * @brief Traits class template to be specialized to enable support for meta
- * template information.
- */
- template<typename>
- struct meta_template_traits;
- /**
- * @brief Traits class template to be specialized to enable support for meta
- * sequence containers.
- */
- template<typename>
- struct meta_sequence_container_traits;
- /**
- * @brief Traits class template to be specialized to enable support for meta
- * associative containers.
- */
- template<typename>
- struct meta_associative_container_traits;
- /**
- * @brief Provides the member constant `value` to true if a given type is a
- * pointer-like type from the point of view of the meta system, false otherwise.
- */
- template<typename, typename = void>
- struct is_meta_pointer_like: std::false_type {};
- /**
- * @brief Partial specialization to ensure that const pointer-like types are
- * also accepted.
- * @tparam Type Potentially pointer-like type.
- */
- template<typename Type>
- struct is_meta_pointer_like<const Type>: is_meta_pointer_like<Type> {};
- /**
- * @brief Helper variable template.
- * @tparam Type Potentially pointer-like type.
- */
- template<typename Type>
- inline constexpr auto is_meta_pointer_like_v = is_meta_pointer_like<Type>::value;
- } // namespace entt
- #endif
- namespace entt {
- class meta_any;
- class meta_type;
- class meta_handle;
- /*! @cond TURN_OFF_DOXYGEN */
- namespace internal {
- enum class meta_traits : std::uint32_t {
- is_none = 0x0000,
- is_const = 0x0001,
- is_static = 0x0002,
- is_arithmetic = 0x0004,
- is_integral = 0x0008,
- is_signed = 0x0010,
- is_array = 0x0020,
- is_enum = 0x0040,
- is_class = 0x0080,
- is_pointer = 0x0100,
- is_pointer_like = 0x0200,
- is_sequence_container = 0x0400,
- is_associative_container = 0x0800,
- _user_defined_traits = 0xFFFF,
- _entt_enum_as_bitmask = 0xFFFF
- };
- template<typename Type>
- [[nodiscard]] auto meta_to_user_traits(const meta_traits traits) noexcept {
- static_assert(std::is_enum_v<Type>, "Invalid enum type");
- constexpr auto shift = popcount(static_cast<std::underlying_type_t<meta_traits>>(meta_traits::_user_defined_traits));
- return Type{static_cast<std::underlying_type_t<Type>>(static_cast<std::underlying_type_t<meta_traits>>(traits) >> shift)};
- }
- template<typename Type>
- [[nodiscard]] auto user_to_meta_traits(const Type value) noexcept {
- static_assert(std::is_enum_v<Type>, "Invalid enum type");
- constexpr auto shift = popcount(static_cast<std::underlying_type_t<meta_traits>>(meta_traits::_user_defined_traits));
- const auto traits = static_cast<std::underlying_type_t<internal::meta_traits>>(static_cast<std::underlying_type_t<Type>>(value));
- ENTT_ASSERT(traits < ((~static_cast<std::underlying_type_t<meta_traits>>(meta_traits::_user_defined_traits)) >> shift), "Invalid traits");
- return meta_traits{traits << shift};
- }
- struct meta_type_node;
- struct meta_custom_node {
- id_type type{};
- std::shared_ptr<void> value{};
- };
- struct meta_base_node {
- id_type type{};
- const meta_type_node &(*resolve)(const meta_context &) noexcept {};
- const void *(*cast)(const void *) noexcept {};
- };
- struct meta_conv_node {
- id_type type{};
- meta_any (*conv)(const meta_ctx &, const void *){};
- };
- struct meta_ctor_node {
- using size_type = std::size_t;
- id_type id{};
- size_type arity{0u};
- meta_type (*arg)(const meta_ctx &, const size_type) noexcept {};
- meta_any (*invoke)(const meta_ctx &, meta_any *const){};
- };
- struct meta_data_node {
- using size_type = std::size_t;
- id_type id{};
- const char *name{};
- meta_traits traits{meta_traits::is_none};
- size_type arity{0u};
- const meta_type_node &(*type)(const meta_context &) noexcept {};
- meta_type (*arg)(const meta_ctx &, const size_type) noexcept {};
- bool (*set)(meta_handle, meta_any){};
- meta_any (*get)(meta_handle){};
- meta_custom_node custom{};
- };
- struct meta_func_node {
- using size_type = std::size_t;
- id_type id{};
- const char *name{};
- meta_traits traits{meta_traits::is_none};
- size_type arity{0u};
- const meta_type_node &(*ret)(const meta_context &) noexcept {};
- meta_type (*arg)(const meta_ctx &, const size_type) noexcept {};
- meta_any (*invoke)(meta_handle, meta_any *const){};
- std::unique_ptr<meta_func_node> next;
- meta_custom_node custom{};
- };
- struct meta_template_node {
- using size_type = std::size_t;
- size_type arity{0u};
- const meta_type_node &(*resolve)(const meta_context &) noexcept {};
- const meta_type_node &(*arg)(const meta_context &, const size_type) noexcept {};
- };
- struct meta_type_descriptor {
- std::vector<meta_ctor_node> ctor{};
- std::vector<meta_base_node> base{};
- std::vector<meta_conv_node> conv{};
- std::vector<meta_data_node> data{};
- std::vector<meta_func_node> func{};
- };
- struct meta_type_node {
- using size_type = std::size_t;
- const type_info *info{};
- id_type id{};
- const char *name{};
- meta_traits traits{meta_traits::is_none};
- size_type size_of{0u};
- const meta_type_node &(*remove_pointer)(const meta_context &) noexcept {};
- meta_any (*default_constructor)(const meta_ctx &){};
- double (*conversion_helper)(void *, const void *){};
- meta_any (*from_void)(const meta_ctx &, void *, const void *){};
- meta_template_node templ{};
- meta_custom_node custom{};
- std::unique_ptr<meta_type_descriptor> details{};
- };
- template<auto Member, typename Type, typename Value>
- [[nodiscard]] auto *find_member(Type &from, const Value value) {
- for(auto &&elem: from) {
- if((elem.*Member) == value) {
- return &elem;
- }
- }
- return static_cast<typename Type::value_type *>(nullptr);
- }
- [[nodiscard]] inline auto *find_overload(meta_func_node *curr, std::remove_pointer_t<decltype(meta_func_node::invoke)> *const ref) {
- while((curr != nullptr) && (curr->invoke != ref)) { curr = curr->next.get(); }
- return curr;
- }
- template<auto Member>
- [[nodiscard]] auto *look_for(const meta_context &context, const meta_type_node &node, const id_type id, bool recursive) {
- using value_type = typename std::remove_reference_t<decltype((node.details.get()->*Member))>::value_type;
- if(node.details) {
- if(auto *member = find_member<&value_type::id>((node.details.get()->*Member), id); member != nullptr) {
- return member;
- }
- if(recursive) {
- for(auto &&curr: node.details->base) {
- if(auto *elem = look_for<Member>(context, curr.resolve(context), id, recursive); elem) {
- return elem;
- }
- }
- }
- }
- return static_cast<value_type *>(nullptr);
- }
- template<typename Type>
- const meta_type_node &resolve(const meta_context &) noexcept;
- template<typename... Args>
- [[nodiscard]] const meta_type_node &meta_arg_node(const meta_context &context, type_list<Args...>, const std::size_t index) noexcept {
- using resolve_type = const meta_type_node &(*)(const meta_context &) noexcept;
- constexpr std::array<resolve_type, sizeof...(Args)> list{&resolve<std::remove_const_t<std::remove_reference_t<Args>>>...};
- ENTT_ASSERT(index < sizeof...(Args), "Out of bounds");
- return list[index](context);
- }
- [[nodiscard]] inline const void *try_cast(const meta_context &context, const meta_type_node &from, const id_type to, const void *instance) noexcept {
- if(from.details) {
- for(auto &&curr: from.details->base) {
- if(const void *other = curr.cast(instance); curr.type == to) {
- return other;
- } else if(const void *elem = try_cast(context, curr.resolve(context), to, other); elem) {
- return elem;
- }
- }
- }
- return nullptr;
- }
- template<typename Type>
- auto setup_node_for() noexcept {
- meta_type_node node{
- &type_id<Type>(),
- type_id<Type>().hash(),
- nullptr,
- (std::is_arithmetic_v<Type> ? meta_traits::is_arithmetic : meta_traits::is_none)
- | (std::is_integral_v<Type> ? meta_traits::is_integral : meta_traits::is_none)
- | (std::is_signed_v<Type> ? meta_traits::is_signed : meta_traits::is_none)
- | (std::is_array_v<Type> ? meta_traits::is_array : meta_traits::is_none)
- | (std::is_enum_v<Type> ? meta_traits::is_enum : meta_traits::is_none)
- | (std::is_class_v<Type> ? meta_traits::is_class : meta_traits::is_none)
- | (std::is_pointer_v<Type> ? meta_traits::is_pointer : meta_traits::is_none)
- | (is_meta_pointer_like_v<Type> ? meta_traits::is_pointer_like : meta_traits::is_none)
- | (is_complete_v<meta_sequence_container_traits<Type>> ? meta_traits::is_sequence_container : meta_traits::is_none)
- | (is_complete_v<meta_associative_container_traits<Type>> ? meta_traits::is_associative_container : meta_traits::is_none),
- size_of_v<Type>,
- &resolve<std::remove_const_t<std::remove_pointer_t<Type>>>};
- if constexpr(std::is_default_constructible_v<Type>) {
- node.default_constructor = +[](const meta_ctx &ctx) {
- return meta_any{ctx, std::in_place_type<Type>};
- };
- }
- if constexpr(std::is_arithmetic_v<Type>) {
- node.conversion_helper = +[](void *lhs, const void *rhs) {
- return lhs ? static_cast<double>(*static_cast<Type *>(lhs) = static_cast<Type>(*static_cast<const double *>(rhs))) : static_cast<double>(*static_cast<const Type *>(rhs));
- };
- } else if constexpr(std::is_enum_v<Type>) {
- node.conversion_helper = +[](void *lhs, const void *rhs) {
- return lhs ? static_cast<double>(*static_cast<Type *>(lhs) = static_cast<Type>(static_cast<std::underlying_type_t<Type>>(*static_cast<const double *>(rhs)))) : static_cast<double>(*static_cast<const Type *>(rhs));
- };
- }
- if constexpr(!std::is_void_v<Type> && !std::is_function_v<Type>) {
- node.from_void = +[](const meta_ctx &ctx, void *elem, const void *celem) {
- if(elem && celem) { // ownership construction request
- return meta_any{ctx, std::in_place, static_cast<std::decay_t<Type> *>(elem)};
- }
- if(elem) { // non-const reference construction request
- return meta_any{ctx, std::in_place_type<std::decay_t<Type> &>, *static_cast<std::decay_t<Type> *>(elem)};
- }
- // const reference construction request
- return meta_any{ctx, std::in_place_type<const std::decay_t<Type> &>, *static_cast<const std::decay_t<Type> *>(celem)};
- };
- }
- if constexpr(is_complete_v<meta_template_traits<Type>>) {
- node.templ = meta_template_node{
- meta_template_traits<Type>::args_type::size,
- &resolve<typename meta_template_traits<Type>::class_type>,
- +[](const meta_context &area, const std::size_t index) noexcept -> decltype(auto) { return meta_arg_node(area, typename meta_template_traits<Type>::args_type{}, index); }};
- }
- return node;
- }
- [[nodiscard]] inline const meta_type_node *try_resolve(const meta_context &context, const type_info &info) noexcept {
- const auto it = context.value.find(info.hash());
- return (it != context.value.end()) ? it->second.get() : nullptr;
- }
- template<typename Type>
- [[nodiscard]] const meta_type_node &resolve(const meta_context &context) noexcept {
- static_assert(std::is_same_v<Type, std::remove_const_t<std::remove_reference_t<Type>>>, "Invalid type");
- static const meta_type_node node = setup_node_for<Type>();
- const auto *elem = try_resolve(context, *node.info);
- return (elem == nullptr) ? node : *elem;
- }
- } // namespace internal
- /*! @endcond */
- } // namespace entt
- #endif
- // #include "range.hpp"
- #ifndef ENTT_META_RANGE_HPP
- #define ENTT_META_RANGE_HPP
- #include <cstddef>
- #include <iterator>
- #include <utility>
- // #include "../core/fwd.hpp"
- // #include "../core/iterator.hpp"
- // #include "context.hpp"
- namespace entt {
- /*! @cond TURN_OFF_DOXYGEN */
- namespace internal {
- struct meta_base_node;
- template<typename Type, typename It>
- struct meta_range_iterator final {
- using value_type = std::pair<id_type, Type>;
- using pointer = input_iterator_pointer<value_type>;
- using reference = value_type;
- using difference_type = std::ptrdiff_t;
- using iterator_category = std::input_iterator_tag;
- using iterator_concept = std::random_access_iterator_tag;
- constexpr meta_range_iterator() noexcept
- : it{},
- ctx{} {}
- constexpr meta_range_iterator(const meta_ctx &area, const It iter) noexcept
- : it{iter},
- ctx{&area} {}
- constexpr meta_range_iterator &operator++() noexcept {
- return ++it, *this;
- }
- constexpr meta_range_iterator operator++(int) noexcept {
- const meta_range_iterator orig = *this;
- return ++(*this), orig;
- }
- constexpr meta_range_iterator &operator--() noexcept {
- return --it, *this;
- }
- constexpr meta_range_iterator operator--(int) noexcept {
- const meta_range_iterator orig = *this;
- return operator--(), orig;
- }
- constexpr meta_range_iterator &operator+=(const difference_type value) noexcept {
- it += value;
- return *this;
- }
- constexpr meta_range_iterator operator+(const difference_type value) const noexcept {
- meta_range_iterator copy = *this;
- return (copy += value);
- }
- constexpr meta_range_iterator &operator-=(const difference_type value) noexcept {
- return (*this += -value);
- }
- constexpr meta_range_iterator operator-(const difference_type value) const noexcept {
- return (*this + -value);
- }
- [[nodiscard]] constexpr reference operator[](const difference_type value) const noexcept {
- if constexpr(std::is_same_v<It, typename decltype(meta_context::value)::const_iterator>) {
- return {it[value].first, Type{*ctx, *it[value].second}};
- } else if constexpr(std::is_same_v<typename std::iterator_traits<It>::value_type, meta_base_node>) {
- return {it[value].type, Type{*ctx, it[value]}};
- } else {
- return {it[value].id, Type{*ctx, it[value]}};
- }
- }
- [[nodiscard]] constexpr pointer operator->() const noexcept {
- return operator*();
- }
- [[nodiscard]] constexpr reference operator*() const noexcept {
- return operator[](0);
- }
- template<typename... Args>
- friend constexpr std::ptrdiff_t operator-(const meta_range_iterator<Args...> &, const meta_range_iterator<Args...> &) noexcept;
- template<typename... Args>
- friend constexpr bool operator==(const meta_range_iterator<Args...> &, const meta_range_iterator<Args...> &) noexcept;
- template<typename... Args>
- friend constexpr bool operator<(const meta_range_iterator<Args...> &, const meta_range_iterator<Args...> &) noexcept;
- private:
- It it;
- const meta_ctx *ctx;
- };
- template<typename... Args>
- [[nodiscard]] constexpr std::ptrdiff_t operator-(const meta_range_iterator<Args...> &lhs, const meta_range_iterator<Args...> &rhs) noexcept {
- return lhs.it - rhs.it;
- }
- template<typename... Args>
- [[nodiscard]] constexpr bool operator==(const meta_range_iterator<Args...> &lhs, const meta_range_iterator<Args...> &rhs) noexcept {
- return lhs.it == rhs.it;
- }
- template<typename... Args>
- [[nodiscard]] constexpr bool operator!=(const meta_range_iterator<Args...> &lhs, const meta_range_iterator<Args...> &rhs) noexcept {
- return !(lhs == rhs);
- }
- template<typename... Args>
- [[nodiscard]] constexpr bool operator<(const meta_range_iterator<Args...> &lhs, const meta_range_iterator<Args...> &rhs) noexcept {
- return lhs.it < rhs.it;
- }
- template<typename... Args>
- [[nodiscard]] constexpr bool operator>(const meta_range_iterator<Args...> &lhs, const meta_range_iterator<Args...> &rhs) noexcept {
- return rhs < lhs;
- }
- template<typename... Args>
- [[nodiscard]] constexpr bool operator<=(const meta_range_iterator<Args...> &lhs, const meta_range_iterator<Args...> &rhs) noexcept {
- return !(lhs > rhs);
- }
- template<typename... Args>
- [[nodiscard]] constexpr bool operator>=(const meta_range_iterator<Args...> &lhs, const meta_range_iterator<Args...> &rhs) noexcept {
- return !(lhs < rhs);
- }
- } // namespace internal
- /*! @endcond */
- /**
- * @brief Iterable range to use to iterate all types of meta objects.
- * @tparam Type Type of meta objects returned.
- * @tparam It Type of forward iterator.
- */
- template<typename Type, typename It>
- using meta_range = iterable_adaptor<internal::meta_range_iterator<Type, It>>;
- } // namespace entt
- #endif
- // #include "type_traits.hpp"
- namespace entt {
- class meta_any;
- class meta_type;
- /*! @brief Proxy object for sequence containers. */
- class meta_sequence_container {
- class meta_iterator;
- public:
- /*! @brief Unsigned integer type. */
- using size_type = std::size_t;
- /*! @brief Meta iterator type. */
- using iterator = meta_iterator;
- /*! @brief Default constructor. */
- meta_sequence_container() = default;
- /**
- * @brief Context aware constructor.
- * @tparam Type Type of container to wrap.
- * @param area The context from which to search for meta types.
- * @param instance The container to wrap.
- */
- template<typename Type>
- meta_sequence_container(const meta_ctx &area, Type &instance) noexcept
- : ctx{&area},
- data{&instance},
- value_type_node{&internal::resolve<typename Type::value_type>},
- const_reference_node{&internal::resolve<std::remove_const_t<std::remove_reference_t<typename Type::const_reference>>>},
- size_fn{meta_sequence_container_traits<std::remove_const_t<Type>>::size},
- clear_fn{meta_sequence_container_traits<std::remove_const_t<Type>>::clear},
- reserve_fn{meta_sequence_container_traits<std::remove_const_t<Type>>::reserve},
- resize_fn{meta_sequence_container_traits<std::remove_const_t<Type>>::resize},
- begin_end_fn{meta_sequence_container_traits<std::remove_const_t<Type>>::iter},
- insert_fn{meta_sequence_container_traits<std::remove_const_t<Type>>::insert},
- erase_fn{meta_sequence_container_traits<std::remove_const_t<Type>>::erase},
- const_only{std::is_const_v<Type>} {}
- [[nodiscard]] inline meta_type value_type() const noexcept;
- [[nodiscard]] inline size_type size() const noexcept;
- inline bool resize(size_type);
- inline bool clear();
- inline bool reserve(size_type);
- [[nodiscard]] inline iterator begin();
- [[nodiscard]] inline iterator end();
- inline iterator insert(const iterator &, meta_any);
- inline iterator erase(const iterator &);
- [[nodiscard]] inline meta_any operator[](size_type);
- [[nodiscard]] inline explicit operator bool() const noexcept;
- private:
- const meta_ctx *ctx{};
- const void *data{};
- const internal::meta_type_node &(*value_type_node)(const internal::meta_context &){};
- const internal::meta_type_node &(*const_reference_node)(const internal::meta_context &){};
- size_type (*size_fn)(const void *){};
- bool (*clear_fn)(void *){};
- bool (*reserve_fn)(void *, const size_type){};
- bool (*resize_fn)(void *, const size_type){};
- iterator (*begin_end_fn)(const meta_ctx &, void *, const void *, const bool){};
- iterator (*insert_fn)(const meta_ctx &, void *, const void *, const void *, const iterator &){};
- iterator (*erase_fn)(const meta_ctx &, void *, const iterator &){};
- bool const_only{};
- };
- /*! @brief Proxy object for associative containers. */
- class meta_associative_container {
- class meta_iterator;
- public:
- /*! @brief Unsigned integer type. */
- using size_type = std::size_t;
- /*! @brief Meta iterator type. */
- using iterator = meta_iterator;
- /*! @brief Default constructor. */
- meta_associative_container() = default;
- /**
- * @brief Context aware constructor.
- * @tparam Type Type of container to wrap.
- * @param area The context from which to search for meta types.
- * @param instance The container to wrap.
- */
- template<typename Type>
- meta_associative_container(const meta_ctx &area, Type &instance) noexcept
- : ctx{&area},
- data{&instance},
- key_type_node{&internal::resolve<typename Type::key_type>},
- value_type_node{&internal::resolve<typename Type::value_type>},
- size_fn{&meta_associative_container_traits<std::remove_const_t<Type>>::size},
- clear_fn{&meta_associative_container_traits<std::remove_const_t<Type>>::clear},
- reserve_fn{&meta_associative_container_traits<std::remove_const_t<Type>>::reserve},
- begin_end_fn{&meta_associative_container_traits<std::remove_const_t<Type>>::iter},
- insert_fn{&meta_associative_container_traits<std::remove_const_t<Type>>::insert},
- erase_fn{&meta_associative_container_traits<std::remove_const_t<Type>>::erase},
- find_fn{&meta_associative_container_traits<std::remove_const_t<Type>>::find},
- const_only{std::is_const_v<Type>} {
- if constexpr(!meta_associative_container_traits<std::remove_const_t<Type>>::key_only) {
- mapped_type_node = &internal::resolve<typename Type::mapped_type>;
- }
- }
- [[nodiscard]] inline meta_type key_type() const noexcept;
- [[nodiscard]] inline meta_type mapped_type() const noexcept;
- [[nodiscard]] inline meta_type value_type() const noexcept;
- [[nodiscard]] inline size_type size() const noexcept;
- inline bool clear();
- inline bool reserve(size_type);
- [[nodiscard]] inline iterator begin();
- [[nodiscard]] inline iterator end();
- inline bool insert(meta_any, meta_any);
- inline size_type erase(meta_any);
- [[nodiscard]] inline iterator find(meta_any);
- [[nodiscard]] inline explicit operator bool() const noexcept;
- private:
- const meta_ctx *ctx{};
- const void *data{};
- const internal::meta_type_node &(*key_type_node)(const internal::meta_context &){};
- const internal::meta_type_node &(*mapped_type_node)(const internal::meta_context &){};
- const internal::meta_type_node &(*value_type_node)(const internal::meta_context &){};
- size_type (*size_fn)(const void *){};
- bool (*clear_fn)(void *){};
- bool (*reserve_fn)(void *, const size_type){};
- iterator (*begin_end_fn)(const meta_ctx &, void *, const void *, const bool){};
- bool (*insert_fn)(void *, const void *, const void *){};
- size_type (*erase_fn)(void *, const void *){};
- iterator (*find_fn)(const meta_ctx &, void *, const void *, const void *){};
- bool const_only{};
- };
- /*! @brief Opaque wrapper for values of any type. */
- class meta_any {
- using vtable_type = void(const internal::meta_traits, const meta_any &, const void *);
- template<typename Type>
- static void basic_vtable(const internal::meta_traits req, const meta_any &value, [[maybe_unused]] const void *other) {
- static_assert(std::is_same_v<std::remove_const_t<std::remove_reference_t<Type>>, Type>, "Invalid type");
- if(req == internal::meta_traits::is_none) {
- value.node = &internal::resolve<Type>(internal::meta_context::from(*value.ctx));
- }
- if constexpr(is_meta_pointer_like_v<Type>) {
- if(req == internal::meta_traits::is_pointer_like) {
- if constexpr(std::is_function_v<typename std::pointer_traits<Type>::element_type>) {
- const_cast<meta_any &>(value).emplace<Type>(*static_cast<const Type *>(other));
- } else if constexpr(!std::is_void_v<std::remove_const_t<typename std::pointer_traits<Type>::element_type>>) {
- using in_place_type = decltype(adl_meta_pointer_like<Type>::dereference(std::declval<const Type &>()));
- if constexpr(std::is_constructible_v<bool, Type>) {
- if(const auto &pointer_like = *static_cast<const Type *>(other); pointer_like) {
- const_cast<meta_any &>(value).emplace<in_place_type>(adl_meta_pointer_like<Type>::dereference(pointer_like));
- }
- } else {
- const_cast<meta_any &>(value).emplace<in_place_type>(adl_meta_pointer_like<Type>::dereference(*static_cast<const Type *>(other)));
- }
- }
- }
- }
- if constexpr(is_complete_v<meta_sequence_container_traits<Type>> || is_complete_v<meta_associative_container_traits<Type>>) {
- if(constexpr auto flag = (is_complete_v<meta_sequence_container_traits<Type>> ? internal::meta_traits::is_sequence_container : internal::meta_traits::is_associative_container); !!(req & flag)) {
- using container_type = std::conditional_t<is_complete_v<meta_sequence_container_traits<Type>>, meta_sequence_container, meta_associative_container>;
- if(!!(req & internal::meta_traits::is_const) || (value.storage.policy() == any_policy::cref)) {
- // NOLINTNEXTLINE(bugprone-casting-through-void)
- *static_cast<container_type *>(const_cast<void *>(other)) = container_type{*value.ctx, any_cast<const Type &>(value.storage)};
- } else {
- // NOLINTNEXTLINE(bugprone-casting-through-void)
- *static_cast<container_type *>(const_cast<void *>(other)) = container_type{*value.ctx, any_cast<Type &>(const_cast<meta_any &>(value).storage)};
- }
- }
- }
- }
- [[nodiscard]] const auto &fetch_node() const {
- if(node == nullptr) {
- ENTT_ASSERT(*this, "Invalid vtable function");
- vtable(internal::meta_traits::is_none, *this, nullptr);
- }
- ENTT_ASSERT(node != nullptr, "Invalid pointer to node");
- return *node;
- }
- meta_any(const meta_any &other, any elem)
- : storage{std::move(elem)},
- ctx{other.ctx},
- node{other.node},
- vtable{other.vtable} {}
- public:
- /*! Default constructor. */
- meta_any() = default;
- /**
- * @brief Context aware constructor.
- * @param area The context from which to search for meta types.
- */
- meta_any(meta_ctx_arg_t, const meta_ctx &area)
- : ctx{&area} {}
- /**
- * @brief Constructs a wrapper by directly initializing the new object.
- * @tparam Type Type of object to use to initialize the wrapper.
- * @tparam Args Types of arguments to use to construct the new instance.
- * @param args Parameters to use to construct the instance.
- */
- template<typename Type, typename... Args>
- explicit meta_any(std::in_place_type_t<Type>, Args &&...args)
- : meta_any{locator<meta_ctx>::value_or(), std::in_place_type<Type>, std::forward<Args>(args)...} {}
- /**
- * @brief Constructs a wrapper by directly initializing the new object.
- * @tparam Type Type of object to use to initialize the wrapper.
- * @tparam Args Types of arguments to use to construct the new instance.
- * @param area The context from which to search for meta types.
- * @param args Parameters to use to construct the instance.
- */
- template<typename Type, typename... Args>
- explicit meta_any(const meta_ctx &area, std::in_place_type_t<Type>, Args &&...args)
- : storage{std::in_place_type<Type>, std::forward<Args>(args)...},
- ctx{&area},
- vtable{&basic_vtable<std::remove_const_t<std::remove_reference_t<Type>>>} {}
- /**
- * @brief Constructs a wrapper taking ownership of the passed object.
- * @tparam Type Type of object to use to initialize the wrapper.
- * @param value A pointer to an object to take ownership of.
- */
- template<typename Type>
- explicit meta_any(std::in_place_t, Type *value)
- : meta_any{locator<meta_ctx>::value_or(), std::in_place, value} {}
- /**
- * @brief Constructs a wrapper taking ownership of the passed object.
- * @tparam Type Type of object to use to initialize the wrapper.
- * @param area The context from which to search for meta types.
- * @param value A pointer to an object to take ownership of.
- */
- template<typename Type>
- explicit meta_any(const meta_ctx &area, std::in_place_t, Type *value)
- : storage{std::in_place, value},
- ctx{&area},
- vtable{storage ? &basic_vtable<Type> : nullptr} {
- }
- /**
- * @brief Constructs a wrapper from a given value.
- * @tparam Type Type of object to use to initialize the wrapper.
- * @param value An instance of an object to use to initialize the wrapper.
- */
- template<typename Type, typename = std::enable_if_t<!std::is_same_v<std::decay_t<Type>, meta_any>>>
- meta_any(Type &&value)
- : meta_any{locator<meta_ctx>::value_or(), std::forward<Type>(value)} {}
- /**
- * @brief Constructs a wrapper from a given value.
- * @tparam Type Type of object to use to initialize the wrapper.
- * @param area The context from which to search for meta types.
- * @param value An instance of an object to use to initialize the wrapper.
- */
- template<typename Type, typename = std::enable_if_t<!std::is_same_v<std::decay_t<Type>, meta_any>>>
- meta_any(const meta_ctx &area, Type &&value)
- : meta_any{area, std::in_place_type<std::decay_t<Type>>, std::forward<Type>(value)} {}
- /**
- * @brief Context aware copy constructor.
- * @param area The context from which to search for meta types.
- * @param other The instance to copy from.
- */
- meta_any(const meta_ctx &area, const meta_any &other)
- : storage{other.storage},
- ctx{&area},
- node{(ctx == other.ctx) ? other.node : nullptr},
- vtable{other.vtable} {}
- /**
- * @brief Context aware move constructor.
- * @param area The context from which to search for meta types.
- * @param other The instance to move from.
- */
- meta_any(const meta_ctx &area, meta_any &&other)
- : storage{std::move(other.storage)},
- ctx{&area},
- node{(ctx == other.ctx) ? std::exchange(other.node, nullptr) : nullptr},
- vtable{std::exchange(other.vtable, nullptr)} {}
- /**
- * @brief Copy constructor.
- * @param other The instance to copy from.
- */
- meta_any(const meta_any &other) = default;
- /**
- * @brief Move constructor.
- * @param other The instance to move from.
- */
- meta_any(meta_any &&other) noexcept
- : storage{std::move(other.storage)},
- ctx{other.ctx},
- node{std::exchange(other.node, nullptr)},
- vtable{std::exchange(other.vtable, nullptr)} {}
- /*! @brief Default destructor. */
- ~meta_any() = default;
- /**
- * @brief Copy assignment operator.
- * @param other The instance to copy from.
- * @return This meta any object.
- */
- meta_any &operator=(const meta_any &other) {
- if(this != &other) {
- storage = other.storage;
- ctx = other.ctx;
- node = other.node;
- vtable = other.vtable;
- }
- return *this;
- }
- /**
- * @brief Move assignment operator.
- * @param other The instance to move from.
- * @return This meta any object.
- */
- meta_any &operator=(meta_any &&other) noexcept {
- storage = std::move(other.storage);
- ctx = other.ctx;
- node = std::exchange(other.node, nullptr);
- vtable = std::exchange(other.vtable, nullptr);
- return *this;
- }
- /**
- * @brief Value assignment operator.
- * @tparam Type Type of object to use to initialize the wrapper.
- * @param value An instance of an object to use to initialize the wrapper.
- * @return This meta any object.
- */
- template<typename Type, typename = std::enable_if_t<!std::is_same_v<std::decay_t<Type>, meta_any>>>
- meta_any &operator=(Type &&value) {
- emplace<std::decay_t<Type>>(std::forward<Type>(value));
- return *this;
- }
- /*! @copydoc any::info */
- [[nodiscard]] inline meta_type type() const noexcept;
- /**
- * @brief Invokes the underlying function, if possible.
- * @tparam Args Types of arguments to use to invoke the function.
- * @param id Unique identifier.
- * @param args Parameters to use to invoke the function.
- * @return A wrapper containing the returned value, if any.
- */
- template<typename... Args>
- meta_any invoke(id_type id, Args &&...args) const;
- /*! @copydoc invoke */
- template<typename... Args>
- meta_any invoke(id_type id, Args &&...args);
- /**
- * @brief Sets the value of a given variable.
- * @tparam Type Type of value to assign.
- * @param id Unique identifier.
- * @param value Parameter to use to set the underlying variable.
- * @return True in case of success, false otherwise.
- */
- template<typename Type>
- bool set(id_type id, Type &&value);
- /**
- * @brief Gets the value of a given variable.
- * @param id Unique identifier.
- * @return A wrapper containing the value of the underlying variable.
- */
- [[nodiscard]] meta_any get(id_type id) const;
- /*! @copydoc get */
- [[nodiscard]] meta_any get(id_type id);
- /**
- * @brief Tries to cast an instance to a given type.
- * @tparam Type Type to which to cast the instance.
- * @return A (possibly null) pointer to the contained instance.
- */
- template<typename Type>
- [[nodiscard]] const Type *try_cast() const {
- const auto *elem = any_cast<const Type>(&storage);
- return ((elem != nullptr) || !*this) ? elem : static_cast<const Type *>(internal::try_cast(internal::meta_context::from(*ctx), fetch_node(), type_hash<std::remove_const_t<Type>>::value(), storage.data()));
- }
- /*! @copydoc try_cast */
- template<typename Type>
- [[nodiscard]] Type *try_cast() {
- return ((storage.policy() == any_policy::cref) && !std::is_const_v<Type>) ? nullptr : const_cast<Type *>(std::as_const(*this).try_cast<std::remove_const_t<Type>>());
- }
- /**
- * @brief Tries to cast an instance to a given type.
- * @tparam Type Type to which to cast the instance.
- * @return A reference to the contained instance.
- */
- template<typename Type>
- [[nodiscard]] std::remove_const_t<Type> cast() const {
- auto *const instance = try_cast<std::remove_reference_t<Type>>();
- ENTT_ASSERT(instance, "Invalid instance");
- return static_cast<Type>(*instance);
- }
- /*! @copydoc cast */
- template<typename Type>
- [[nodiscard]] std::remove_const_t<Type> cast() {
- // forces const on non-reference types to make them work also with wrappers for const references
- auto *const instance = try_cast<std::remove_reference_t<const Type>>();
- ENTT_ASSERT(instance, "Invalid instance");
- return static_cast<Type>(*instance);
- }
- /**
- * @brief Converts an object in such a way that a given cast becomes viable.
- * @param type Meta type to which the cast is requested.
- * @return A valid meta object if convertible, an invalid one otherwise.
- */
- [[nodiscard]] meta_any allow_cast(const meta_type &type) const;
- /**
- * @brief Converts an object in such a way that a given cast becomes viable.
- * @param type Meta type to which the cast is requested.
- * @return True if convertible, false otherwise.
- */
- [[nodiscard]] bool allow_cast(const meta_type &type);
- /**
- * @brief Converts an object in such a way that a given cast becomes viable.
- * @tparam Type Type to which the cast is requested.
- * @return A valid meta object if convertible, an invalid one otherwise.
- */
- template<typename Type>
- [[nodiscard]] meta_any allow_cast() const {
- if constexpr(!std::is_reference_v<Type> || std::is_const_v<std::remove_reference_t<Type>>) {
- if(storage.has_value<std::remove_const_t<std::remove_reference_t<Type>>>()) {
- return as_ref();
- } else if(*this) {
- if constexpr(std::is_arithmetic_v<std::remove_const_t<std::remove_reference_t<Type>>> || std::is_enum_v<std::remove_const_t<std::remove_reference_t<Type>>>) {
- if(const auto &from = fetch_node(); from.conversion_helper) {
- return meta_any{*ctx, static_cast<Type>(from.conversion_helper(nullptr, storage.data()))};
- }
- }
- if(const auto &from = fetch_node(); from.details != nullptr) {
- if(const auto *elem = internal::find_member<&internal::meta_conv_node::type>(from.details->conv, entt::type_hash<std::remove_const_t<std::remove_reference_t<Type>>>::value()); elem != nullptr) {
- return elem->conv(*ctx, storage.data());
- }
- for(auto &&curr: from.details->base) {
- if(auto other = curr.resolve(internal::meta_context::from(*ctx)).from_void(*ctx, nullptr, curr.cast(storage.data())); curr.type == entt::type_hash<std::remove_const_t<std::remove_reference_t<Type>>>::value()) {
- return other;
- } else if(auto from_base = std::as_const(other).template allow_cast<Type>(); from_base) {
- return from_base;
- }
- }
- }
- }
- }
- return meta_any{meta_ctx_arg, *ctx};
- }
- /**
- * @brief Converts an object in such a way that a given cast becomes viable.
- * @tparam Type Type to which the cast is requested.
- * @return True if convertible, false otherwise.
- */
- template<typename Type>
- [[nodiscard]] bool allow_cast() {
- if constexpr(std::is_reference_v<Type> && !std::is_const_v<std::remove_reference_t<Type>>) {
- return allow_cast<const std::remove_reference_t<Type> &>() && (storage.policy() != any_policy::cref);
- } else {
- if(storage.has_value<std::remove_const_t<std::remove_reference_t<Type>>>()) {
- return true;
- } else if(auto other = std::as_const(*this).allow_cast<std::remove_const_t<std::remove_reference_t<Type>>>(); other) {
- if(other.storage.owner()) {
- std::swap(*this, other);
- }
- return true;
- }
- return false;
- }
- }
- /*! @copydoc any::emplace */
- template<typename Type, typename... Args>
- void emplace(Args &&...args) {
- storage.emplace<Type>(std::forward<Args>(args)...);
- auto *prev = std::exchange(vtable, &basic_vtable<std::remove_const_t<std::remove_reference_t<Type>>>);
- node = (prev == vtable) ? node : nullptr;
- }
- /*! @copydoc any::assign */
- bool assign(const meta_any &other);
- /*! @copydoc any::assign */
- bool assign(meta_any &&other);
- /*! @copydoc any::reset */
- void reset() {
- storage.reset();
- node = nullptr;
- vtable = nullptr;
- }
- /**
- * @brief Returns a sequence container proxy.
- * @return A sequence container proxy for the underlying object.
- */
- [[nodiscard]] meta_sequence_container as_sequence_container() noexcept {
- meta_sequence_container proxy{};
- if(*this) { vtable(internal::meta_traits::is_sequence_container, *this, &proxy); }
- return proxy;
- }
- /*! @copydoc as_sequence_container */
- [[nodiscard]] meta_sequence_container as_sequence_container() const noexcept {
- meta_sequence_container proxy{};
- if(*this) { vtable(internal::meta_traits::is_sequence_container | internal::meta_traits::is_const, *this, &proxy); }
- return proxy;
- }
- /**
- * @brief Returns an associative container proxy.
- * @return An associative container proxy for the underlying object.
- */
- [[nodiscard]] meta_associative_container as_associative_container() noexcept {
- meta_associative_container proxy{};
- if(*this) { vtable(internal::meta_traits::is_associative_container, *this, &proxy); }
- return proxy;
- }
- /*! @copydoc as_associative_container */
- [[nodiscard]] meta_associative_container as_associative_container() const noexcept {
- meta_associative_container proxy{};
- if(*this) { vtable(internal::meta_traits::is_associative_container | internal::meta_traits::is_const, *this, &proxy); }
- return proxy;
- }
- /**
- * @brief Indirection operator for dereferencing opaque objects.
- * @return A wrapper that shares a reference to an unmanaged object if the
- * wrapped element is dereferenceable, an invalid meta any otherwise.
- */
- [[nodiscard]] meta_any operator*() const noexcept {
- meta_any ret{meta_ctx_arg, *ctx};
- if(*this) { vtable(internal::meta_traits::is_pointer_like, ret, storage.data()); }
- return ret;
- }
- /*! @copydoc any::operator bool */
- [[nodiscard]] explicit operator bool() const noexcept {
- return !(vtable == nullptr);
- }
- /*! @copydoc any::operator== */
- [[nodiscard]] bool operator==(const meta_any &other) const noexcept {
- return (ctx == other.ctx) && (!*this == !other) && (storage == other.storage);
- }
- /*! @copydoc any::operator!= */
- [[nodiscard]] bool operator!=(const meta_any &other) const noexcept {
- return !(*this == other);
- }
- /*! @copydoc any::as_ref */
- [[nodiscard]] meta_any as_ref() noexcept {
- return meta_any{*this, storage.as_ref()};
- }
- /*! @copydoc any::as_ref */
- [[nodiscard]] meta_any as_ref() const noexcept {
- return meta_any{*this, storage.as_ref()};
- }
- /**
- * @brief Returns the underlying storage.
- * @return The underlyig storage.
- */
- [[nodiscard]] const any &base() const noexcept {
- return storage;
- }
- /**
- * @brief Returns the underlying meta context.
- * @return The underlying meta context.
- */
- [[nodiscard]] const meta_ctx &context() const noexcept {
- return *ctx;
- }
- private:
- any storage{};
- const meta_ctx *ctx{&locator<meta_ctx>::value_or()};
- mutable const internal::meta_type_node *node{};
- vtable_type *vtable{};
- };
- /**
- * @brief Forwards its argument and avoids copies for lvalue references.
- * @tparam Type Type of argument to use to construct the new instance.
- * @param value Parameter to use to construct the instance.
- * @param ctx The context from which to search for meta types.
- * @return A properly initialized and not necessarily owning wrapper.
- */
- template<typename Type>
- [[nodiscard]] meta_any forward_as_meta(const meta_ctx &ctx, Type &&value) {
- return meta_any{ctx, std::in_place_type<Type &&>, std::forward<Type>(value)};
- }
- /**
- * @brief Forwards its argument and avoids copies for lvalue references.
- * @tparam Type Type of argument to use to construct the new instance.
- * @param value Parameter to use to construct the instance.
- * @return A properly initialized and not necessarily owning wrapper.
- */
- template<typename Type>
- [[nodiscard]] meta_any forward_as_meta(Type &&value) {
- return forward_as_meta(locator<meta_ctx>::value_or(), std::forward<Type>(value));
- }
- /*! @brief Opaque pointers to instances of any type. */
- class meta_handle {
- template<typename Type, typename... Args, typename = std::enable_if_t<std::is_same_v<std::decay_t<Type>, meta_any>>>
- meta_handle(int, Type &value, Args &&...args)
- : any{std::forward<Args>(args)..., value.as_ref()} {}
- template<typename Type, typename... Args>
- meta_handle(char, Type &value, Args &&...args)
- : any{std::forward<Args>(args)..., std::in_place_type<Type &>, value} {}
- public:
- /*! Default constructor. */
- meta_handle() = default;
- /**
- * @brief Creates a handle that points to an unmanaged object.
- * @tparam Type Type of object to use to initialize the handle.
- * @param ctx The context from which to search for meta types.
- * @param value An instance of an object to use to initialize the handle.
- */
- template<typename Type, typename = std::enable_if_t<!std::is_same_v<std::decay_t<Type>, meta_handle>>>
- meta_handle(const meta_ctx &ctx, Type &value)
- : meta_handle{0, value, ctx} {}
- /**
- * @brief Creates a handle that points to an unmanaged object.
- * @tparam Type Type of object to use to initialize the handle.
- * @param value An instance of an object to use to initialize the handle.
- */
- template<typename Type, typename = std::enable_if_t<!std::is_same_v<std::decay_t<Type>, meta_handle>>>
- meta_handle(Type &value)
- : meta_handle{0, value} {}
- /**
- * @brief Context aware move constructor.
- * @param area The context from which to search for meta types.
- * @param other The instance to move from.
- */
- meta_handle(const meta_ctx &area, meta_handle &&other)
- : any{area, std::move(other.any)} {}
- /*! @brief Default copy constructor, deleted on purpose. */
- meta_handle(const meta_handle &) = delete;
- /*! @brief Default move constructor. */
- meta_handle(meta_handle &&) = default;
- /*! @brief Default destructor. */
- ~meta_handle() = default;
- /**
- * @brief Default copy assignment operator, deleted on purpose.
- * @return This meta handle.
- */
- meta_handle &operator=(const meta_handle &) = delete;
- /**
- * @brief Default move assignment operator.
- * @return This meta handle.
- */
- meta_handle &operator=(meta_handle &&) = default;
- /**
- * @brief Returns false if a handle is invalid, true otherwise.
- * @return False if the handle is invalid, true otherwise.
- */
- [[nodiscard]] explicit operator bool() const noexcept {
- return static_cast<bool>(any);
- }
- /**
- * @brief Access operator for accessing the contained opaque object.
- * @return A wrapper that shares a reference to an unmanaged object.
- */
- [[nodiscard]] meta_any *operator->() {
- return &any;
- }
- /*! @copydoc operator-> */
- [[deprecated("do not use const handles")]] [[nodiscard]] const meta_any *operator->() const {
- return &any;
- }
- private:
- meta_any any{};
- };
- /*! @brief Opaque wrapper for user defined data of any type. */
- struct meta_custom {
- /*! @brief Default constructor. */
- meta_custom() noexcept = default;
- /**
- * @brief Basic constructor for meta objects.
- * @param curr The underlying node with which to construct the instance.
- */
- meta_custom(const internal::meta_custom_node &curr) noexcept
- : node{&curr} {}
- /**
- * @brief Generic conversion operator.
- * @tparam Type Type to which conversion is requested.
- */
- template<typename Type>
- [[nodiscard]] operator Type *() const noexcept {
- return ((node != nullptr) && (type_hash<std::remove_const_t<Type>>::value() == node->type)) ? static_cast<Type *>(node->value.get()) : nullptr;
- }
- /**
- * @brief Generic conversion operator.
- * @tparam Type Type to which conversion is requested.
- */
- template<typename Type>
- [[nodiscard]] operator Type &() const noexcept {
- ENTT_ASSERT(static_cast<Type *>(*this) != nullptr, "Invalid type");
- return *static_cast<Type *>(node->value.get());
- }
- private:
- const internal::meta_custom_node *node{};
- };
- /*! @brief Opaque wrapper for data members. */
- class meta_data {
- [[nodiscard]] auto &node_or_assert() const noexcept {
- ENTT_ASSERT(node != nullptr, "Invalid pointer to node");
- return *node;
- }
- public:
- /*! @brief Unsigned integer type. */
- using size_type = typename internal::meta_data_node::size_type;
- /*! @brief Default constructor. */
- meta_data() noexcept = default;
- /**
- * @brief Context aware constructor for meta objects.
- * @param area The context from which to search for meta types.
- * @param curr The underlying node with which to construct the instance.
- */
- meta_data(const meta_ctx &area, const internal::meta_data_node &curr) noexcept
- : node{&curr},
- ctx{&area} {}
- /**
- * @brief Returns the name assigned to a data member, if any.
- * @return The name assigned to the data member, if any.
- */
- [[nodiscard]] const char *name() const noexcept {
- return node_or_assert().name;
- }
- /**
- * @brief Returns the number of setters available.
- * @return The number of setters available.
- */
- [[nodiscard]] size_type arity() const noexcept {
- return node_or_assert().arity;
- }
- /**
- * @brief Indicates whether a data member is constant or not.
- * @return True if the data member is constant, false otherwise.
- */
- [[nodiscard]] bool is_const() const noexcept {
- return !!(node_or_assert().traits & internal::meta_traits::is_const);
- }
- /**
- * @brief Indicates whether a data member is static or not.
- * @return True if the data member is static, false otherwise.
- */
- [[nodiscard]] bool is_static() const noexcept {
- return !!(node_or_assert().traits & internal::meta_traits::is_static);
- }
- /*! @copydoc meta_any::type */
- [[nodiscard]] inline meta_type type() const noexcept;
- /**
- * @brief Sets the value of a given variable.
- * @tparam Instance Type of instance to operate on.
- * @tparam Type Type of value to assign.
- * @param instance An instance that fits the underlying type.
- * @param value Parameter to use to set the underlying variable.
- * @return True in case of success, false otherwise.
- */
- template<typename Instance = meta_handle, typename Type>
- // NOLINTNEXTLINE(modernize-use-nodiscard)
- bool set(Instance &&instance, Type &&value) const {
- return node_or_assert().set(meta_handle{*ctx, std::forward<Instance>(instance)}, meta_any{*ctx, std::forward<Type>(value)});
- }
- /**
- * @brief Gets the value of a given variable.
- * @tparam Instance Type of instance to operate on.
- * @param instance An instance that fits the underlying type.
- * @return A wrapper containing the value of the underlying variable.
- */
- template<typename Instance = meta_handle>
- [[nodiscard]] meta_any get(Instance &&instance) const {
- return node_or_assert().get(meta_handle{*ctx, std::forward<Instance>(instance)});
- }
- /**
- * @brief Returns the type accepted by the i-th setter.
- * @param index Index of the setter of which to return the accepted type.
- * @return The type accepted by the i-th setter.
- */
- [[nodiscard]] inline meta_type arg(size_type index) const noexcept;
- /**
- * @brief Returns all meta traits for a given meta object.
- * @tparam Type The type to convert the meta traits to.
- * @return The registered meta traits, if any.
- */
- template<typename Type>
- [[nodiscard]] Type traits() const noexcept {
- return internal::meta_to_user_traits<Type>(node_or_assert().traits);
- }
- /**
- * @brief Returns user defined data for a given meta object.
- * @return User defined arbitrary data.
- */
- [[nodiscard]] meta_custom custom() const noexcept {
- return {node_or_assert().custom};
- }
- /**
- * @brief Returns true if an object is valid, false otherwise.
- * @return True if the object is valid, false otherwise.
- */
- [[nodiscard]] explicit operator bool() const noexcept {
- return (node != nullptr);
- }
- /**
- * @brief Checks if two objects refer to the same type.
- * @param other The object with which to compare.
- * @return True if the objects refer to the same type, false otherwise.
- */
- [[nodiscard]] bool operator==(const meta_data &other) const noexcept {
- return (ctx == other.ctx) && (node == other.node);
- }
- private:
- const internal::meta_data_node *node{};
- const meta_ctx *ctx{&locator<meta_ctx>::value_or()};
- };
- /**
- * @brief Checks if two objects refer to the same type.
- * @param lhs An object, either valid or not.
- * @param rhs An object, either valid or not.
- * @return False if the objects refer to the same node, true otherwise.
- */
- [[nodiscard]] inline bool operator!=(const meta_data &lhs, const meta_data &rhs) noexcept {
- return !(lhs == rhs);
- }
- /*! @brief Opaque wrapper for member functions. */
- class meta_func {
- [[nodiscard]] auto &node_or_assert() const noexcept {
- ENTT_ASSERT(node != nullptr, "Invalid pointer to node");
- return *node;
- }
- public:
- /*! @brief Unsigned integer type. */
- using size_type = typename internal::meta_func_node::size_type;
- /*! @brief Default constructor. */
- meta_func() noexcept = default;
- /**
- * @brief Context aware constructor for meta objects.
- * @param area The context from which to search for meta types.
- * @param curr The underlying node with which to construct the instance.
- */
- meta_func(const meta_ctx &area, const internal::meta_func_node &curr) noexcept
- : node{&curr},
- ctx{&area} {}
- /**
- * @brief Returns the name assigned to a member function, if any.
- * @return The name assigned to the member function, if any.
- */
- [[nodiscard]] const char *name() const noexcept {
- return node_or_assert().name;
- }
- /**
- * @brief Returns the number of arguments accepted by a member function.
- * @return The number of arguments accepted by the member function.
- */
- [[nodiscard]] size_type arity() const noexcept {
- return node_or_assert().arity;
- }
- /**
- * @brief Indicates whether a member function is constant or not.
- * @return True if the member function is constant, false otherwise.
- */
- [[nodiscard]] bool is_const() const noexcept {
- return !!(node_or_assert().traits & internal::meta_traits::is_const);
- }
- /**
- * @brief Indicates whether a member function is static or not.
- * @return True if the member function is static, false otherwise.
- */
- [[nodiscard]] bool is_static() const noexcept {
- return !!(node_or_assert().traits & internal::meta_traits::is_static);
- }
- /**
- * @brief Returns the return type of a member function.
- * @return The return type of the member function.
- */
- [[nodiscard]] inline meta_type ret() const noexcept;
- /**
- * @brief Returns the type of the i-th argument of a member function.
- * @param index Index of the argument of which to return the type.
- * @return The type of the i-th argument of a member function.
- */
- [[nodiscard]] inline meta_type arg(size_type index) const noexcept;
- /**
- * @brief Invokes the underlying function, if possible.
- * @tparam Instance Type of instance to operate on.
- * @param instance An instance that fits the underlying type.
- * @param args Parameters to use to invoke the function.
- * @param sz Number of parameters to use to invoke the function.
- * @return A wrapper containing the returned value, if any.
- */
- template<typename Instance = meta_handle>
- meta_any invoke(Instance &&instance, meta_any *const args, const size_type sz) const {
- return (sz == arity()) ? node_or_assert().invoke(meta_handle{*ctx, std::forward<Instance>(instance)}, args) : meta_any{meta_ctx_arg, *ctx};
- }
- /**
- * @copybrief invoke
- * @tparam Instance Type of instance to operate on.
- * @tparam Args Types of arguments to use to invoke the function.
- * @param instance An instance that fits the underlying type.
- * @param args Parameters to use to invoke the function.
- * @return A wrapper containing the returned value, if any.
- */
- template<typename Instance = meta_handle, typename... Args>
- // NOLINTNEXTLINE(modernize-use-nodiscard)
- meta_any invoke(Instance &&instance, Args &&...args) const {
- return invoke(std::forward<Instance>(instance), std::array<meta_any, sizeof...(Args)>{meta_any{*ctx, std::forward<Args>(args)}...}.data(), sizeof...(Args));
- }
- /*! @copydoc meta_data::traits */
- template<typename Type>
- [[nodiscard]] Type traits() const noexcept {
- return internal::meta_to_user_traits<Type>(node_or_assert().traits);
- }
- /*! @copydoc meta_data::custom */
- [[nodiscard]] meta_custom custom() const noexcept {
- return {node_or_assert().custom};
- }
- /**
- * @brief Returns the next overload of a given function, if any.
- * @return The next overload of the given function, if any.
- */
- [[nodiscard]] meta_func next() const {
- return (node_or_assert().next != nullptr) ? meta_func{*ctx, *node_or_assert().next} : meta_func{};
- }
- /*! @copydoc meta_data::operator bool */
- [[nodiscard]] explicit operator bool() const noexcept {
- return (node != nullptr);
- }
- /*! @copydoc meta_data::operator== */
- [[nodiscard]] bool operator==(const meta_func &other) const noexcept {
- return (ctx == other.ctx) && (node == other.node);
- }
- private:
- const internal::meta_func_node *node{};
- const meta_ctx *ctx{&locator<meta_ctx>::value_or()};
- };
- /*! @copydoc operator!=(const meta_data &, const meta_data &) */
- [[nodiscard]] inline bool operator!=(const meta_func &lhs, const meta_func &rhs) noexcept {
- return !(lhs == rhs);
- }
- /*! @brief Opaque wrapper for types. */
- class meta_type {
- [[nodiscard]] const auto &fetch_node() const {
- return (node == nullptr) ? internal::resolve<void>(internal::meta_context::from(*ctx)) : *node;
- }
- template<typename Func>
- [[nodiscard]] auto lookup(meta_any *const args, const typename internal::meta_type_node::size_type sz, [[maybe_unused]] bool constness, Func next) const {
- decltype(next()) candidate = nullptr;
- size_type same{};
- bool ambiguous{};
- for(auto curr = next(); curr; curr = next()) {
- if constexpr(std::is_same_v<std::decay_t<decltype(*curr)>, internal::meta_func_node>) {
- if(constness && !(curr->traits & internal::meta_traits::is_const)) {
- continue;
- }
- }
- if(curr->arity == sz) {
- size_type match{};
- size_type pos{};
- // NOLINTBEGIN(cppcoreguidelines-pro-bounds-pointer-arithmetic) - waiting for C++20 (and std::span)
- for(; pos < sz && args[pos]; ++pos) {
- const auto other = curr->arg(*ctx, pos);
- const auto type = args[pos].type();
- if(const auto &info = other.info(); info == type.info()) {
- ++match;
- } else if(!(type.fetch_node().conversion_helper && other.fetch_node().conversion_helper) && !(type.fetch_node().details && (internal::find_member<&internal::meta_base_node::type>(type.fetch_node().details->base, info.hash()) || internal::find_member<&internal::meta_conv_node::type>(type.fetch_node().details->conv, info.hash())))) {
- break;
- }
- }
- // NOLINTEND(cppcoreguidelines-pro-bounds-pointer-arithmetic)
- if(pos == sz) {
- if(!candidate || match > same) {
- candidate = curr;
- same = match;
- ambiguous = false;
- } else if(match == same) {
- if constexpr(std::is_same_v<std::decay_t<decltype(*curr)>, internal::meta_func_node>) {
- if(!!(curr->traits & internal::meta_traits::is_const) != !!(candidate->traits & internal::meta_traits::is_const)) {
- candidate = !!(candidate->traits & internal::meta_traits::is_const) ? curr : candidate;
- ambiguous = false;
- continue;
- }
- }
- ambiguous = true;
- }
- }
- }
- }
- return ambiguous ? nullptr : candidate;
- }
- public:
- /*! @brief Unsigned integer type. */
- using size_type = typename internal::meta_type_node::size_type;
- /*! @brief Default constructor. */
- meta_type() noexcept = default;
- /**
- * @brief Context aware constructor for meta objects.
- * @param area The context from which to search for meta types.
- * @param curr The underlying node with which to construct the instance.
- */
- meta_type(const meta_ctx &area, const internal::meta_type_node &curr) noexcept
- : node{&curr},
- ctx{&area} {}
- /**
- * @brief Context aware constructor for meta objects.
- * @param area The context from which to search for meta types.
- * @param curr The underlying node with which to construct the instance.
- */
- meta_type(const meta_ctx &area, const internal::meta_base_node &curr) noexcept
- : meta_type{area, curr.resolve(internal::meta_context::from(area))} {}
- /**
- * @brief Returns the type info object of the underlying type.
- * @return The type info object of the underlying type.
- */
- [[nodiscard]] const type_info &info() const noexcept {
- return *fetch_node().info;
- }
- /**
- * @brief Returns the identifier assigned to a type.
- * @return The identifier assigned to the type.
- */
- [[nodiscard]] id_type id() const noexcept {
- return fetch_node().id;
- }
- /**
- * @brief Returns the name assigned to a type, if any.
- * @return The name assigned to the type, if any.
- */
- [[nodiscard]] const char *name() const noexcept {
- return fetch_node().name;
- }
- /**
- * @brief Returns the size of the underlying type if known.
- * @return The size of the underlying type if known, 0 otherwise.
- */
- [[nodiscard]] size_type size_of() const noexcept {
- return fetch_node().size_of;
- }
- /**
- * @brief Checks whether a type refers to an arithmetic type or not.
- * @return True if the underlying type is an arithmetic type, false
- * otherwise.
- */
- [[nodiscard]] bool is_arithmetic() const noexcept {
- return !!(fetch_node().traits & internal::meta_traits::is_arithmetic);
- }
- /**
- * @brief Checks whether a type refers to an integral type or not.
- * @return True if the underlying type is an integral type, false otherwise.
- */
- [[nodiscard]] bool is_integral() const noexcept {
- return !!(fetch_node().traits & internal::meta_traits::is_integral);
- }
- /**
- * @brief Checks whether a type refers to a signed type or not.
- * @return True if the underlying type is a signed type, false otherwise.
- */
- [[nodiscard]] bool is_signed() const noexcept {
- return !!(fetch_node().traits & internal::meta_traits::is_signed);
- }
- /**
- * @brief Checks whether a type refers to an array type or not.
- * @return True if the underlying type is an array type, false otherwise.
- */
- [[nodiscard]] bool is_array() const noexcept {
- return !!(fetch_node().traits & internal::meta_traits::is_array);
- }
- /**
- * @brief Checks whether a type refers to an enum or not.
- * @return True if the underlying type is an enum, false otherwise.
- */
- [[nodiscard]] bool is_enum() const noexcept {
- return !!(fetch_node().traits & internal::meta_traits::is_enum);
- }
- /**
- * @brief Checks whether a type refers to a class or not.
- * @return True if the underlying type is a class, false otherwise.
- */
- [[nodiscard]] bool is_class() const noexcept {
- return !!(fetch_node().traits & internal::meta_traits::is_class);
- }
- /**
- * @brief Checks whether a type refers to a pointer or not.
- * @return True if the underlying type is a pointer, false otherwise.
- */
- [[nodiscard]] bool is_pointer() const noexcept {
- return !!(fetch_node().traits & internal::meta_traits::is_pointer);
- }
- /**
- * @brief Provides the type for which the pointer is defined.
- * @return The type for which the pointer is defined or this type if it
- * doesn't refer to a pointer type.
- */
- [[nodiscard]] meta_type remove_pointer() const noexcept {
- return meta_type{*ctx, fetch_node().remove_pointer(internal::meta_context::from(*ctx))};
- }
- /**
- * @brief Checks whether a type is a pointer-like type or not.
- * @return True if the underlying type is pointer-like, false otherwise.
- */
- [[nodiscard]] bool is_pointer_like() const noexcept {
- return !!(fetch_node().traits & internal::meta_traits::is_pointer_like);
- }
- /**
- * @brief Checks whether a type refers to a sequence container or not.
- * @return True if the type is a sequence container, false otherwise.
- */
- [[nodiscard]] bool is_sequence_container() const noexcept {
- return !!(fetch_node().traits & internal::meta_traits::is_sequence_container);
- }
- /**
- * @brief Checks whether a type refers to an associative container or not.
- * @return True if the type is an associative container, false otherwise.
- */
- [[nodiscard]] bool is_associative_container() const noexcept {
- return !!(fetch_node().traits & internal::meta_traits::is_associative_container);
- }
- /**
- * @brief Checks whether a type refers to a template specialization or not.
- * @return True if the type is a template specialization, false otherwise.
- */
- [[nodiscard]] bool is_template_specialization() const noexcept {
- return (fetch_node().templ.arity != 0u);
- }
- /**
- * @brief Returns the number of template arguments.
- * @return The number of template arguments.
- */
- [[nodiscard]] size_type template_arity() const noexcept {
- return fetch_node().templ.arity;
- }
- /**
- * @brief Returns a tag for the class template of the underlying type.
- * @return The tag for the class template of the underlying type.
- */
- [[nodiscard]] meta_type template_type() const noexcept {
- return (fetch_node().templ.resolve != nullptr) ? meta_type{*ctx, fetch_node().templ.resolve(internal::meta_context::from(*ctx))} : meta_type{};
- }
- /**
- * @brief Returns the type of the i-th template argument of a type.
- * @param index Index of the template argument of which to return the type.
- * @return The type of the i-th template argument of a type.
- */
- [[nodiscard]] meta_type template_arg(const size_type index) const noexcept {
- return index < template_arity() ? meta_type{*ctx, fetch_node().templ.arg(internal::meta_context::from(*ctx), index)} : meta_type{};
- }
- /**
- * @brief Checks if a type supports direct casting to another type.
- * @param other The meta type to test for.
- * @return True if direct casting is allowed, false otherwise.
- */
- [[nodiscard]] bool can_cast(const meta_type &other) const noexcept {
- // casting this is UB in all cases but we aren't going to use the resulting pointer, so...
- return other && ((*this == other) || (internal::try_cast(internal::meta_context::from(*ctx), fetch_node(), other.fetch_node().info->hash(), this) != nullptr));
- }
- /**
- * @brief Checks whether a type supports conversion to another type.
- * @param other The meta type to test for.
- * @return True if the conversion is allowed, false otherwise.
- */
- [[nodiscard]] bool can_convert(const meta_type &other) const noexcept {
- if(const auto &to = other.info().hash(); (info().hash() == to) || ((fetch_node().conversion_helper != nullptr) && (other.is_arithmetic() || other.is_enum()))) {
- return true;
- } else if(const auto &from = fetch_node(); from.details) {
- if(const auto *elem = internal::find_member<&internal::meta_conv_node::type>(from.details->conv, to); elem != nullptr) {
- return true;
- }
- for(auto &&curr: from.details->base) {
- if(curr.type == to || meta_type{*ctx, curr.resolve(internal::meta_context::from(*ctx))}.can_convert(other)) {
- return true;
- }
- }
- }
- return false;
- }
- /**
- * @brief Returns a range to visit registered top-level base meta types.
- * @return An iterable range to visit registered top-level base meta types.
- */
- [[nodiscard]] meta_range<meta_type, typename decltype(internal::meta_type_descriptor::base)::const_iterator> base() const noexcept {
- using range_type = meta_range<meta_type, typename decltype(internal::meta_type_descriptor::base)::const_iterator>;
- return fetch_node().details ? range_type{{*ctx, fetch_node().details->base.cbegin()}, {*ctx, fetch_node().details->base.cend()}} : range_type{};
- }
- /**
- * @brief Returns a range to visit registered top-level meta data.
- * @return An iterable range to visit registered top-level meta data.
- */
- [[nodiscard]] meta_range<meta_data, typename decltype(internal::meta_type_descriptor::data)::const_iterator> data() const noexcept {
- using range_type = meta_range<meta_data, typename decltype(internal::meta_type_descriptor::data)::const_iterator>;
- return fetch_node().details ? range_type{{*ctx, fetch_node().details->data.cbegin()}, {*ctx, fetch_node().details->data.cend()}} : range_type{};
- }
- /**
- * @brief Lookup utility for meta data (bases are also visited).
- * @param id Unique identifier.
- * @param recursive True for a search in the base classes, false otherwise.
- * @return The registered meta data for the given identifier, if any.
- */
- [[nodiscard]] meta_data data(const id_type id, const bool recursive = true) const {
- const auto *elem = internal::look_for<&internal::meta_type_descriptor::data>(internal::meta_context::from(*ctx), fetch_node(), id, recursive);
- return (elem != nullptr) ? meta_data{*ctx, *elem} : meta_data{};
- }
- /**
- * @brief Returns a range to visit registered top-level functions.
- * @return An iterable range to visit registered top-level functions.
- */
- [[nodiscard]] meta_range<meta_func, typename decltype(internal::meta_type_descriptor::func)::const_iterator> func() const noexcept {
- using return_type = meta_range<meta_func, typename decltype(internal::meta_type_descriptor::func)::const_iterator>;
- return fetch_node().details ? return_type{{*ctx, fetch_node().details->func.cbegin()}, {*ctx, fetch_node().details->func.cend()}} : return_type{};
- }
- /**
- * @brief Lookup utility for meta functions (bases are also visited).
- * @param id Unique identifier.
- * @param recursive True for a search in the base classes, false otherwise.
- * @return The registered meta function for the given identifier, if any.
- */
- [[nodiscard]] meta_func func(const id_type id, const bool recursive = true) const {
- const auto *elem = internal::look_for<&internal::meta_type_descriptor::func>(internal::meta_context::from(*ctx), fetch_node(), id, recursive);
- return (elem != nullptr) ? meta_func{*ctx, *elem} : meta_func{};
- }
- /**
- * @brief Creates an instance of the underlying type, if possible.
- * @param args Parameters to use to construct the instance.
- * @param sz Number of parameters to use to construct the instance.
- * @return A wrapper containing the new instance, if any.
- */
- [[nodiscard]] meta_any construct(meta_any *const args, const size_type sz) const {
- if(const auto &ref = fetch_node(); ref.details) {
- if(const auto *candidate = lookup(args, sz, false, [first = ref.details->ctor.cbegin(), last = ref.details->ctor.cend()]() mutable { return first == last ? nullptr : &*(first++); }); candidate) {
- return candidate->invoke(*ctx, args);
- }
- }
- if(const auto &ref = fetch_node(); (sz == 0u) && (ref.default_constructor != nullptr)) {
- return ref.default_constructor(*ctx);
- }
- return meta_any{meta_ctx_arg, *ctx};
- }
- /**
- * @copybrief construct
- * @tparam Args Types of arguments to use to construct the instance.
- * @param args Parameters to use to construct the instance.
- * @return A wrapper containing the new instance, if any.
- */
- template<typename... Args>
- [[nodiscard]] meta_any construct(Args &&...args) const {
- return construct(std::array<meta_any, sizeof...(Args)>{meta_any{*ctx, std::forward<Args>(args)}...}.data(), sizeof...(Args));
- // NOLINTNEXTLINE(clang-analyzer-cplusplus.NewDeleteLeaks)
- }
- /**
- * @brief Wraps an opaque element of the underlying type.
- * @param elem A valid pointer to an element of the underlying type.
- * @param transfer_ownership True to transfer ownership, false otherwise.
- * @return A wrapper that references the given instance.
- */
- [[nodiscard]] meta_any from_void(void *elem, bool transfer_ownership = false) const {
- return ((elem != nullptr) && (fetch_node().from_void != nullptr)) ? fetch_node().from_void(*ctx, elem, transfer_ownership ? elem : nullptr) : meta_any{meta_ctx_arg, *ctx};
- }
- /**
- * @brief Wraps an opaque element of the underlying type.
- * @param elem A valid pointer to an element of the underlying type.
- * @return A wrapper that references the given instance.
- */
- [[nodiscard]] meta_any from_void(const void *elem) const {
- return ((elem != nullptr) && (fetch_node().from_void != nullptr)) ? fetch_node().from_void(*ctx, nullptr, elem) : meta_any{meta_ctx_arg, *ctx};
- }
- /**
- * @brief Invokes a function given an identifier, if possible.
- * @tparam Instance Type of instance to operate on.
- * @param id Unique identifier.
- * @param instance An instance that fits the underlying type.
- * @param args Parameters to use to invoke the function.
- * @param sz Number of parameters to use to invoke the function.
- * @return A wrapper containing the returned value, if any.
- */
- template<typename Instance = meta_handle>
- // NOLINTNEXTLINE(modernize-use-nodiscard)
- meta_any invoke(const id_type id, Instance &&instance, meta_any *const args, const size_type sz) const {
- meta_handle wrapped{*ctx, std::forward<Instance>(instance)};
- if(const auto &ref = fetch_node(); ref.details) {
- if(auto *elem = internal::find_member<&internal::meta_func_node::id>(ref.details->func, id); elem != nullptr) {
- if(const auto *candidate = lookup(args, sz, (wrapped->base().policy() == any_policy::cref), [curr = elem]() mutable { return (curr != nullptr) ? std::exchange(curr, curr->next.get()) : nullptr; }); candidate) {
- return candidate->invoke(std::move(wrapped), args);
- }
- }
- }
- for(auto &&curr: base()) {
- if(auto elem = curr.second.invoke(id, *wrapped.operator->(), args, sz); elem) {
- return elem;
- }
- }
- return meta_any{meta_ctx_arg, *ctx};
- }
- /**
- * @copybrief invoke
- * @param id Unique identifier.
- * @tparam Instance Type of instance to operate on.
- * @tparam Args Types of arguments to use to invoke the function.
- * @param instance An instance that fits the underlying type.
- * @param args Parameters to use to invoke the function.
- * @return A wrapper containing the returned value, if any.
- */
- template<typename Instance = meta_handle, typename... Args>
- // NOLINTNEXTLINE(modernize-use-nodiscard)
- meta_any invoke(const id_type id, Instance &&instance, Args &&...args) const {
- return invoke(id, std::forward<Instance>(instance), std::array<meta_any, sizeof...(Args)>{meta_any{*ctx, std::forward<Args>(args)}...}.data(), sizeof...(Args));
- }
- /**
- * @brief Sets the value of a given variable.
- * @tparam Instance Type of instance to operate on.
- * @tparam Type Type of value to assign.
- * @param id Unique identifier.
- * @param instance An instance that fits the underlying type.
- * @param value Parameter to use to set the underlying variable.
- * @return True in case of success, false otherwise.
- */
- template<typename Instance = meta_handle, typename Type>
- // NOLINTNEXTLINE(modernize-use-nodiscard)
- bool set(const id_type id, Instance &&instance, Type &&value) const {
- const auto candidate = data(id);
- return candidate && candidate.set(std::forward<Instance>(instance), std::forward<Type>(value));
- }
- /**
- * @brief Gets the value of a given variable.
- * @tparam Instance Type of instance to operate on.
- * @param id Unique identifier.
- * @param instance An instance that fits the underlying type.
- * @return A wrapper containing the value of the underlying variable.
- */
- template<typename Instance = meta_handle>
- [[nodiscard]] meta_any get(const id_type id, Instance &&instance) const {
- const auto candidate = data(id);
- return candidate ? candidate.get(std::forward<Instance>(instance)) : meta_any{meta_ctx_arg, *ctx};
- }
- /*! @copydoc meta_data::traits */
- template<typename Type>
- [[nodiscard]] Type traits() const noexcept {
- return internal::meta_to_user_traits<Type>(fetch_node().traits);
- }
- /*! @copydoc meta_data::custom */
- [[nodiscard]] meta_custom custom() const noexcept {
- return fetch_node().custom;
- }
- /*! @copydoc meta_data::operator bool */
- [[nodiscard]] explicit operator bool() const noexcept {
- return (node != nullptr);
- }
- /*! @copydoc meta_data::operator== */
- [[nodiscard]] bool operator==(const meta_type &other) const noexcept {
- return (ctx == other.ctx) && (fetch_node().id == other.fetch_node().id);
- }
- private:
- mutable const internal::meta_type_node *node{};
- const meta_ctx *ctx{&locator<meta_ctx>::value_or()};
- };
- /*! @copydoc operator!=(const meta_data &, const meta_data &) */
- [[nodiscard]] inline bool operator!=(const meta_type &lhs, const meta_type &rhs) noexcept {
- return !(lhs == rhs);
- }
- [[nodiscard]] inline meta_type meta_any::type() const noexcept {
- return *this ? meta_type{*ctx, fetch_node()} : meta_type{};
- }
- template<typename... Args>
- // NOLINTNEXTLINE(modernize-use-nodiscard)
- meta_any meta_any::invoke(const id_type id, Args &&...args) const {
- return type().invoke(id, *this, std::forward<Args>(args)...);
- }
- template<typename... Args>
- meta_any meta_any::invoke(const id_type id, Args &&...args) {
- return type().invoke(id, *this, std::forward<Args>(args)...);
- }
- template<typename Type>
- bool meta_any::set(const id_type id, Type &&value) {
- return type().set(id, *this, std::forward<Type>(value));
- }
- [[nodiscard]] inline meta_any meta_any::get(const id_type id) const {
- return type().get(id, *this);
- }
- [[nodiscard]] inline meta_any meta_any::get(const id_type id) {
- return type().get(id, *this);
- }
- [[nodiscard]] inline meta_any meta_any::allow_cast(const meta_type &type) const {
- if(storage.has_value(type.info())) {
- return as_ref();
- } else if(*this) {
- if(const auto &from = fetch_node(); (from.conversion_helper != nullptr) && (type.is_arithmetic() || type.is_enum())) {
- auto other = type.construct();
- const auto value = from.conversion_helper(nullptr, storage.data());
- other.fetch_node().conversion_helper(other.storage.data(), &value);
- return other;
- }
- if(const auto &from = fetch_node(); from.details) {
- if(const auto *elem = internal::find_member<&internal::meta_conv_node::type>(from.details->conv, type.info().hash()); elem != nullptr) {
- return elem->conv(*ctx, storage.data());
- }
- for(auto &&curr: from.details->base) {
- if(auto other = curr.resolve(internal::meta_context::from(*ctx)).from_void(*ctx, nullptr, curr.cast(storage.data())); curr.type == type.info().hash()) {
- return other;
- } else if(auto from_base = std::as_const(other).allow_cast(type); from_base) {
- return from_base;
- }
- }
- }
- }
- return meta_any{meta_ctx_arg, *ctx};
- }
- [[nodiscard]] inline bool meta_any::allow_cast(const meta_type &type) {
- if(storage.has_value(type.info())) {
- return true;
- } else if(auto other = std::as_const(*this).allow_cast(type); other) {
- if(other.storage.owner()) {
- std::swap(*this, other);
- }
- return true;
- }
- return false;
- }
- inline bool meta_any::assign(const meta_any &other) {
- if(!storage.assign(other.storage)) {
- auto value = other.allow_cast(type());
- return storage.assign(value.storage);
- }
- return true;
- }
- inline bool meta_any::assign(meta_any &&other) {
- return storage.assign(std::move(other.storage)) || storage.assign(std::as_const(other).allow_cast(type()).storage);
- }
- [[nodiscard]] inline meta_type meta_data::type() const noexcept {
- return meta_type{*ctx, node_or_assert().type(internal::meta_context::from(*ctx))};
- }
- [[nodiscard]] inline meta_type meta_data::arg(const size_type index) const noexcept {
- return index < arity() ? node_or_assert().arg(*ctx, index) : meta_type{};
- }
- [[nodiscard]] inline meta_type meta_func::ret() const noexcept {
- return meta_type{*ctx, node_or_assert().ret(internal::meta_context::from(*ctx))};
- }
- [[nodiscard]] inline meta_type meta_func::arg(const size_type index) const noexcept {
- return index < arity() ? node_or_assert().arg(*ctx, index) : meta_type{};
- }
- /*! @cond TURN_OFF_DOXYGEN */
- class meta_sequence_container::meta_iterator final {
- using vtable_type = void(const void *, const std::ptrdiff_t, meta_any *);
- template<typename It>
- static void basic_vtable(const void *value, const std::ptrdiff_t offset, meta_any *other) {
- const auto &it = *static_cast<const It *>(value);
- other ? other->emplace<decltype(*it)>(*it) : std::advance(const_cast<It &>(it), offset);
- }
- public:
- using value_type = meta_any;
- using pointer = input_iterator_pointer<value_type>;
- using reference = value_type;
- using difference_type = std::ptrdiff_t;
- using iterator_category = std::input_iterator_tag;
- using iterator_concept = std::bidirectional_iterator_tag;
- meta_iterator() = default;
- template<typename It>
- meta_iterator(const meta_ctx &area, It iter) noexcept
- : ctx{&area},
- vtable{&basic_vtable<It>},
- handle{iter} {}
- meta_iterator &operator++() noexcept {
- return vtable(handle.data(), 1, nullptr), *this;
- }
- meta_iterator operator++(int value) noexcept {
- meta_iterator orig = *this;
- vtable(handle.data(), ++value, nullptr);
- return orig;
- }
- meta_iterator &operator--() noexcept {
- return vtable(handle.data(), -1, nullptr), *this;
- }
- meta_iterator operator--(int value) noexcept {
- meta_iterator orig = *this;
- vtable(handle.data(), --value, nullptr);
- return orig;
- }
- [[nodiscard]] reference operator*() const {
- reference other{meta_ctx_arg, *ctx};
- vtable(handle.data(), 0, &other);
- return other;
- }
- [[nodiscard]] pointer operator->() const {
- return operator*();
- }
- [[nodiscard]] explicit operator bool() const noexcept {
- return (vtable != nullptr);
- }
- [[nodiscard]] bool operator==(const meta_iterator &other) const noexcept {
- return handle == other.handle;
- }
- [[nodiscard]] const any &base() const noexcept {
- return handle;
- }
- private:
- const meta_ctx *ctx{};
- vtable_type *vtable{};
- any handle{};
- };
- [[nodiscard]] inline bool operator!=(const meta_sequence_container::iterator &lhs, const meta_sequence_container::iterator &rhs) noexcept {
- return !(lhs == rhs);
- }
- class meta_associative_container::meta_iterator final {
- using vtable_type = void(const void *, std::pair<meta_any, meta_any> *);
- template<bool KeyOnly, typename It>
- static void basic_vtable(const void *value, std::pair<meta_any, meta_any> *other) {
- if(const auto &it = *static_cast<const It *>(value); other) {
- if constexpr(KeyOnly) {
- other->first.emplace<decltype(*it)>(*it);
- } else {
- other->first.emplace<decltype((it->first))>(it->first);
- other->second.emplace<decltype((it->second))>(it->second);
- }
- } else {
- ++const_cast<It &>(it);
- }
- }
- public:
- using value_type = std::pair<meta_any, meta_any>;
- using pointer = input_iterator_pointer<value_type>;
- using reference = value_type;
- using difference_type = std::ptrdiff_t;
- using iterator_category = std::input_iterator_tag;
- using iterator_concept = std::forward_iterator_tag;
- meta_iterator() = default;
- template<bool KeyOnly, typename It>
- meta_iterator(const meta_ctx &area, std::bool_constant<KeyOnly>, It iter) noexcept
- : ctx{&area},
- vtable{&basic_vtable<KeyOnly, It>},
- handle{iter} {}
- meta_iterator &operator++() noexcept {
- return vtable(handle.data(), nullptr), *this;
- }
- meta_iterator operator++(int) noexcept {
- meta_iterator orig = *this;
- vtable(handle.data(), nullptr);
- return orig;
- }
- [[nodiscard]] reference operator*() const {
- reference other{{meta_ctx_arg, *ctx}, {meta_ctx_arg, *ctx}};
- vtable(handle.data(), &other);
- return other;
- }
- [[nodiscard]] pointer operator->() const {
- return operator*();
- }
- [[nodiscard]] explicit operator bool() const noexcept {
- return (vtable != nullptr);
- }
- [[nodiscard]] bool operator==(const meta_iterator &other) const noexcept {
- return handle == other.handle;
- }
- private:
- const meta_ctx *ctx{};
- vtable_type *vtable{};
- any handle{};
- };
- [[nodiscard]] inline bool operator!=(const meta_associative_container::iterator &lhs, const meta_associative_container::iterator &rhs) noexcept {
- return !(lhs == rhs);
- }
- /*! @endcond */
- /**
- * @brief Returns the meta value type of a container.
- * @return The meta value type of the container.
- */
- [[nodiscard]] inline meta_type meta_sequence_container::value_type() const noexcept {
- return (value_type_node != nullptr) ? meta_type{*ctx, value_type_node(internal::meta_context::from(*ctx))} : meta_type{};
- }
- /**
- * @brief Returns the size of a container.
- * @return The size of the container.
- */
- [[nodiscard]] inline meta_sequence_container::size_type meta_sequence_container::size() const noexcept {
- return size_fn(data);
- }
- /**
- * @brief Resizes a container to contain a given number of elements.
- * @param sz The new size of the container.
- * @return True in case of success, false otherwise.
- */
- inline bool meta_sequence_container::resize(const size_type sz) {
- return !const_only && resize_fn(const_cast<void *>(data), sz);
- }
- /**
- * @brief Clears the content of a container.
- * @return True in case of success, false otherwise.
- */
- inline bool meta_sequence_container::clear() {
- return !const_only && clear_fn(const_cast<void *>(data));
- }
- /**
- * @brief Reserves storage for at least the given number of elements.
- * @param sz The new capacity of the container.
- * @return True in case of success, false otherwise.
- */
- inline bool meta_sequence_container::reserve(const size_type sz) {
- return !const_only && reserve_fn(const_cast<void *>(data), sz);
- }
- /**
- * @brief Returns an iterator to the first element of a container.
- * @return An iterator to the first element of the container.
- */
- [[nodiscard]] inline meta_sequence_container::iterator meta_sequence_container::begin() {
- return begin_end_fn(*ctx, const_only ? nullptr : const_cast<void *>(data), data, false);
- }
- /**
- * @brief Returns an iterator that is past the last element of a container.
- * @return An iterator that is past the last element of the container.
- */
- [[nodiscard]] inline meta_sequence_container::iterator meta_sequence_container::end() {
- return begin_end_fn(*ctx, const_only ? nullptr : const_cast<void *>(data), data, true);
- }
- /**
- * @brief Inserts an element at a specified location of a container.
- * @param it Iterator before which the element will be inserted.
- * @param value Element value to insert.
- * @return A possibly invalid iterator to the inserted element.
- */
- inline meta_sequence_container::iterator meta_sequence_container::insert(const iterator &it, meta_any value) {
- // this abomination is necessary because only on macos value_type and const_reference are different types for std::vector<bool>
- if(const auto &vtype = value_type_node(internal::meta_context::from(*ctx)); !const_only && (value.allow_cast({*ctx, vtype}) || value.allow_cast({*ctx, const_reference_node(internal::meta_context::from(*ctx))}))) {
- const bool is_value_type = (value.type().info() == *vtype.info);
- return insert_fn(*ctx, const_cast<void *>(data), is_value_type ? value.base().data() : nullptr, is_value_type ? nullptr : value.base().data(), it);
- }
- return iterator{};
- }
- /**
- * @brief Removes a given element from a container.
- * @param it Iterator to the element to remove.
- * @return A possibly invalid iterator following the last removed element.
- */
- inline meta_sequence_container::iterator meta_sequence_container::erase(const iterator &it) {
- return const_only ? iterator{} : erase_fn(*ctx, const_cast<void *>(data), it);
- }
- /**
- * @brief Returns a reference to the element at a given location of a container.
- * @param pos The position of the element to return.
- * @return A reference to the requested element properly wrapped.
- */
- [[nodiscard]] inline meta_any meta_sequence_container::operator[](const size_type pos) {
- auto it = begin();
- it.operator++(static_cast<int>(pos) - 1);
- return *it;
- }
- /**
- * @brief Returns false if a proxy is invalid, true otherwise.
- * @return False if the proxy is invalid, true otherwise.
- */
- [[nodiscard]] inline meta_sequence_container::operator bool() const noexcept {
- return (data != nullptr);
- }
- /**
- * @brief Returns the meta key type of a container.
- * @return The meta key type of the a container.
- */
- [[nodiscard]] inline meta_type meta_associative_container::key_type() const noexcept {
- return (key_type_node != nullptr) ? meta_type{*ctx, key_type_node(internal::meta_context::from(*ctx))} : meta_type{};
- }
- /**
- * @brief Returns the meta mapped type of a container.
- * @return The meta mapped type of the a container.
- */
- [[nodiscard]] inline meta_type meta_associative_container::mapped_type() const noexcept {
- return (mapped_type_node != nullptr) ? meta_type{*ctx, mapped_type_node(internal::meta_context::from(*ctx))} : meta_type{};
- }
- /*! @copydoc meta_sequence_container::value_type */
- [[nodiscard]] inline meta_type meta_associative_container::value_type() const noexcept {
- return (value_type_node != nullptr) ? meta_type{*ctx, value_type_node(internal::meta_context::from(*ctx))} : meta_type{};
- }
- /*! @copydoc meta_sequence_container::size */
- [[nodiscard]] inline meta_associative_container::size_type meta_associative_container::size() const noexcept {
- return size_fn(data);
- }
- /*! @copydoc meta_sequence_container::clear */
- inline bool meta_associative_container::clear() {
- return !const_only && clear_fn(const_cast<void *>(data));
- }
- /*! @copydoc meta_sequence_container::reserve */
- inline bool meta_associative_container::reserve(const size_type sz) {
- return !const_only && reserve_fn(const_cast<void *>(data), sz);
- }
- /*! @copydoc meta_sequence_container::begin */
- [[nodiscard]] inline meta_associative_container::iterator meta_associative_container::begin() {
- return begin_end_fn(*ctx, const_only ? nullptr : const_cast<void *>(data), data, false);
- }
- /*! @copydoc meta_sequence_container::end */
- [[nodiscard]] inline meta_associative_container::iterator meta_associative_container::end() {
- return begin_end_fn(*ctx, const_only ? nullptr : const_cast<void *>(data), data, true);
- }
- /**
- * @brief Inserts a key-only or key/value element into a container.
- * @param key The key of the element to insert.
- * @param value The value of the element to insert, if needed.
- * @return A bool denoting whether the insertion took place.
- */
- inline bool meta_associative_container::insert(meta_any key, meta_any value = {}) {
- return !const_only && key.allow_cast(meta_type{*ctx, key_type_node(internal::meta_context::from(*ctx))})
- && ((mapped_type_node == nullptr) || value.allow_cast(meta_type{*ctx, mapped_type_node(internal::meta_context::from(*ctx))}))
- && insert_fn(const_cast<void *>(data), key.base().data(), value.base().data());
- }
- /**
- * @brief Removes the specified element from a container.
- * @param key The key of the element to remove.
- * @return A bool denoting whether the removal took place.
- */
- inline meta_associative_container::size_type meta_associative_container::erase(meta_any key) {
- return (!const_only && key.allow_cast(meta_type{*ctx, key_type_node(internal::meta_context::from(*ctx))})) ? erase_fn(const_cast<void *>(data), key.base().data()) : 0u;
- }
- /**
- * @brief Returns an iterator to the element with a given key, if any.
- * @param key The key of the element to search.
- * @return An iterator to the element with the given key, if any.
- */
- [[nodiscard]] inline meta_associative_container::iterator meta_associative_container::find(meta_any key) {
- return key.allow_cast(meta_type{*ctx, key_type_node(internal::meta_context::from(*ctx))}) ? find_fn(*ctx, const_only ? nullptr : const_cast<void *>(data), data, key.base().data()) : iterator{};
- }
- /**
- * @brief Returns false if a proxy is invalid, true otherwise.
- * @return False if the proxy is invalid, true otherwise.
- */
- [[nodiscard]] inline meta_associative_container::operator bool() const noexcept {
- return (data != nullptr);
- }
- } // namespace entt
- #endif
- // #include "type_traits.hpp"
- namespace entt {
- /*! @cond TURN_OFF_DOXYGEN */
- namespace internal {
- template<typename Type, typename = void>
- struct sequence_container_extent: integral_constant<meta_dynamic_extent> {};
- template<typename Type>
- struct sequence_container_extent<Type, std::enable_if_t<is_complete_v<std::tuple_size<Type>>>>: integral_constant<std::tuple_size_v<Type>> {};
- template<typename Type>
- inline constexpr std::size_t sequence_container_extent_v = sequence_container_extent<Type>::value;
- template<typename, typename = void>
- struct key_only_associative_container: std::true_type {};
- template<typename Type>
- struct key_only_associative_container<Type, std::void_t<typename Type::mapped_type>>: std::false_type {};
- template<typename Type>
- inline constexpr bool key_only_associative_container_v = key_only_associative_container<Type>::value;
- template<typename, typename = void>
- struct reserve_aware_container: std::false_type {};
- template<typename Type>
- struct reserve_aware_container<Type, std::void_t<decltype(&Type::reserve)>>: std::true_type {};
- template<typename Type>
- inline constexpr bool reserve_aware_container_v = reserve_aware_container<Type>::value;
- } // namespace internal
- /*! @endcond */
- /**
- * @brief General purpose implementation of meta sequence container traits.
- * @tparam Type Type of underlying sequence container.
- */
- template<typename Type>
- struct basic_meta_sequence_container_traits {
- static_assert(std::is_same_v<Type, std::remove_const_t<std::remove_reference_t<Type>>>, "Unexpected type");
- /*! @brief Unsigned integer type. */
- using size_type = typename meta_sequence_container::size_type;
- /*! @brief Meta iterator type. */
- using iterator = typename meta_sequence_container::iterator;
- /*! @brief Number of elements, or `meta_dynamic_extent` if dynamic. */
- static constexpr std::size_t extent = internal::sequence_container_extent_v<Type>;
- /*! @brief True in case of fixed size containers, false otherwise. */
- [[deprecated("use ::extent instead")]] static constexpr bool fixed_size = (extent != meta_dynamic_extent);
- /**
- * @brief Returns the number of elements in a container.
- * @param container Opaque pointer to a container of the given type.
- * @return Number of elements.
- */
- [[nodiscard]] static size_type size(const void *container) {
- return static_cast<const Type *>(container)->size();
- }
- /**
- * @brief Clears a container.
- * @param container Opaque pointer to a container of the given type.
- * @return True in case of success, false otherwise.
- */
- [[nodiscard]] static bool clear([[maybe_unused]] void *container) {
- if constexpr(extent == meta_dynamic_extent) {
- static_cast<Type *>(container)->clear();
- return true;
- } else {
- return false;
- }
- }
- /**
- * @brief Increases the capacity of a container.
- * @param container Opaque pointer to a container of the given type.
- * @param sz Desired capacity.
- * @return True in case of success, false otherwise.
- */
- [[nodiscard]] static bool reserve([[maybe_unused]] void *container, [[maybe_unused]] const size_type sz) {
- if constexpr(internal::reserve_aware_container_v<Type>) {
- static_cast<Type *>(container)->reserve(sz);
- return true;
- } else {
- return false;
- }
- }
- /**
- * @brief Resizes a container.
- * @param container Opaque pointer to a container of the given type.
- * @param sz The new number of elements.
- * @return True in case of success, false otherwise.
- */
- [[nodiscard]] static bool resize([[maybe_unused]] void *container, [[maybe_unused]] const size_type sz) {
- if constexpr((extent == meta_dynamic_extent) && std::is_default_constructible_v<typename Type::value_type>) {
- static_cast<Type *>(container)->resize(sz);
- return true;
- } else {
- return false;
- }
- }
- /**
- * @brief Returns a possibly const iterator to the beginning or the end.
- * @param area The context to pass to the newly created iterator.
- * @param container Opaque pointer to a container of the given type.
- * @param as_const Const opaque pointer fallback.
- * @param end False to get a pointer that is past the last element.
- * @return An iterator to the first or past the last element of the
- * container.
- */
- static iterator iter(const meta_ctx &area, void *container, const void *as_const, const bool end) {
- return (container == nullptr)
- ? iterator{area, end ? static_cast<const Type *>(as_const)->cend() : static_cast<const Type *>(as_const)->cbegin()}
- : iterator{area, end ? static_cast<Type *>(container)->end() : static_cast<Type *>(container)->begin()};
- }
- /**
- * @brief Assigns one element to a container and constructs its object from
- * a given opaque instance.
- * @param area The context to pass to the newly created iterator.
- * @param container Opaque pointer to a container of the given type.
- * @param value Optional opaque instance of the object to construct (as
- * value type).
- * @param cref Optional opaque instance of the object to construct (as
- * decayed const reference type).
- * @param it Iterator before which the element will be inserted.
- * @return A possibly invalid iterator to the inserted element.
- */
- [[nodiscard]] static iterator insert([[maybe_unused]] const meta_ctx &area, [[maybe_unused]] void *container, [[maybe_unused]] const void *value, [[maybe_unused]] const void *cref, [[maybe_unused]] const iterator &it) {
- if constexpr(extent == meta_dynamic_extent) {
- auto *const non_const = any_cast<typename Type::iterator>(&it.base());
- return {area, static_cast<Type *>(container)->insert(
- non_const ? *non_const : any_cast<const typename Type::const_iterator &>(it.base()),
- (value != nullptr) ? *static_cast<const typename Type::value_type *>(value) : *static_cast<const std::remove_reference_t<typename Type::const_reference> *>(cref))};
- } else {
- return iterator{};
- }
- }
- /**
- * @brief Erases an element from a container.
- * @param area The context to pass to the newly created iterator.
- * @param container Opaque pointer to a container of the given type.
- * @param it An opaque iterator to the element to erase.
- * @return A possibly invalid iterator following the last removed element.
- */
- [[nodiscard]] static iterator erase([[maybe_unused]] const meta_ctx &area, [[maybe_unused]] void *container, [[maybe_unused]] const iterator &it) {
- if constexpr(extent == meta_dynamic_extent) {
- auto *const non_const = any_cast<typename Type::iterator>(&it.base());
- return {area, static_cast<Type *>(container)->erase(non_const ? *non_const : any_cast<const typename Type::const_iterator &>(it.base()))};
- } else {
- return iterator{};
- }
- }
- };
- /**
- * @brief General purpose implementation of meta associative container traits.
- * @tparam Type Type of underlying associative container.
- */
- template<typename Type>
- struct basic_meta_associative_container_traits {
- static_assert(std::is_same_v<Type, std::remove_const_t<std::remove_reference_t<Type>>>, "Unexpected type");
- /*! @brief Unsigned integer type. */
- using size_type = typename meta_associative_container::size_type;
- /*! @brief Meta iterator type. */
- using iterator = typename meta_associative_container::iterator;
- /*! @brief True in case of key-only containers, false otherwise. */
- static constexpr bool key_only = internal::key_only_associative_container_v<Type>;
- /**
- * @brief Returns the number of elements in a container.
- * @param container Opaque pointer to a container of the given type.
- * @return Number of elements.
- */
- [[nodiscard]] static size_type size(const void *container) {
- return static_cast<const Type *>(container)->size();
- }
- /**
- * @brief Clears a container.
- * @param container Opaque pointer to a container of the given type.
- * @return True in case of success, false otherwise.
- */
- [[nodiscard]] static bool clear(void *container) {
- static_cast<Type *>(container)->clear();
- return true;
- }
- /**
- * @brief Increases the capacity of a container.
- * @param container Opaque pointer to a container of the given type.
- * @param sz Desired capacity.
- * @return True in case of success, false otherwise.
- */
- [[nodiscard]] static bool reserve([[maybe_unused]] void *container, [[maybe_unused]] const size_type sz) {
- if constexpr(internal::reserve_aware_container_v<Type>) {
- static_cast<Type *>(container)->reserve(sz);
- return true;
- } else {
- return false;
- }
- }
- /**
- * @brief Returns a possibly const iterator to the beginning or the end.
- * @param area The context to pass to the newly created iterator.
- * @param container Opaque pointer to a container of the given type.
- * @param as_const Const opaque pointer fallback.
- * @param end False to get a pointer that is past the last element.
- * @return An iterator to the first or past the last element of the
- * container.
- */
- static iterator iter(const meta_ctx &area, void *container, const void *as_const, const bool end) {
- return (container == nullptr)
- ? iterator{area, std::bool_constant<key_only>{}, end ? static_cast<const Type *>(as_const)->cend() : static_cast<const Type *>(as_const)->cbegin()}
- : iterator{area, std::bool_constant<key_only>{}, end ? static_cast<Type *>(container)->end() : static_cast<Type *>(container)->begin()};
- }
- /**
- * @brief Inserts an element into a container, if the key does not exist.
- * @param container Opaque pointer to a container of the given type.
- * @param key An opaque key value of an element to insert.
- * @param value Optional opaque value to insert (key-value containers).
- * @return True if the insertion took place, false otherwise.
- */
- [[nodiscard]] static bool insert(void *container, const void *key, [[maybe_unused]] const void *value) {
- if constexpr(key_only) {
- return static_cast<Type *>(container)->insert(*static_cast<const typename Type::key_type *>(key)).second;
- } else {
- return static_cast<Type *>(container)->emplace(*static_cast<const typename Type::key_type *>(key), *static_cast<const typename Type::mapped_type *>(value)).second;
- }
- }
- /**
- * @brief Removes an element from a container.
- * @param container Opaque pointer to a container of the given type.
- * @param key An opaque key value of an element to remove.
- * @return Number of elements removed (either 0 or 1).
- */
- [[nodiscard]] static size_type erase(void *container, const void *key) {
- return static_cast<Type *>(container)->erase(*static_cast<const typename Type::key_type *>(key));
- }
- /**
- * @brief Finds an element with a given key.
- * @param area The context to pass to the newly created iterator.
- * @param container Opaque pointer to a container of the given type.
- * @param as_const Const opaque pointer fallback.
- * @param key Opaque key value of an element to search for.
- * @return An iterator to the element with the given key, if any.
- */
- static iterator find(const meta_ctx &area, void *container, const void *as_const, const void *key) {
- return (container != nullptr) ? iterator{area, std::bool_constant<key_only>{}, static_cast<Type *>(container)->find(*static_cast<const typename Type::key_type *>(key))}
- : iterator{area, std::bool_constant<key_only>{}, static_cast<const Type *>(as_const)->find(*static_cast<const typename Type::key_type *>(key))};
- }
- };
- /**
- * @brief Meta sequence container traits for `std::vector`s of any type.
- * @tparam Args Template arguments for the container.
- */
- template<typename... Args>
- struct meta_sequence_container_traits<std::vector<Args...>>
- : basic_meta_sequence_container_traits<std::vector<Args...>> {};
- /**
- * @brief Meta sequence container traits for `std::array`s of any type.
- * @tparam Type Template arguments for the container.
- * @tparam N Template arguments for the container.
- */
- template<typename Type, auto N>
- struct meta_sequence_container_traits<std::array<Type, N>>
- : basic_meta_sequence_container_traits<std::array<Type, N>> {};
- /**
- * @brief Meta sequence container traits for `std::list`s of any type.
- * @tparam Args Template arguments for the container.
- */
- template<typename... Args>
- struct meta_sequence_container_traits<std::list<Args...>>
- : basic_meta_sequence_container_traits<std::list<Args...>> {};
- /**
- * @brief Meta sequence container traits for `std::deque`s of any type.
- * @tparam Args Template arguments for the container.
- */
- template<typename... Args>
- struct meta_sequence_container_traits<std::deque<Args...>>
- : basic_meta_sequence_container_traits<std::deque<Args...>> {};
- /**
- * @brief Meta associative container traits for `std::map`s of any type.
- * @tparam Args Template arguments for the container.
- */
- template<typename... Args>
- struct meta_associative_container_traits<std::map<Args...>>
- : basic_meta_associative_container_traits<std::map<Args...>> {};
- /**
- * @brief Meta associative container traits for `std::unordered_map`s of any
- * type.
- * @tparam Args Template arguments for the container.
- */
- template<typename... Args>
- struct meta_associative_container_traits<std::unordered_map<Args...>>
- : basic_meta_associative_container_traits<std::unordered_map<Args...>> {};
- /**
- * @brief Meta associative container traits for `std::set`s of any type.
- * @tparam Args Template arguments for the container.
- */
- template<typename... Args>
- struct meta_associative_container_traits<std::set<Args...>>
- : basic_meta_associative_container_traits<std::set<Args...>> {};
- /**
- * @brief Meta associative container traits for `std::unordered_set`s of any
- * type.
- * @tparam Args Template arguments for the container.
- */
- template<typename... Args>
- struct meta_associative_container_traits<std::unordered_set<Args...>>
- : basic_meta_associative_container_traits<std::unordered_set<Args...>> {};
- /**
- * @brief Meta associative container traits for `dense_map`s of any type.
- * @tparam Args Template arguments for the container.
- */
- template<typename... Args>
- struct meta_associative_container_traits<dense_map<Args...>>
- : basic_meta_associative_container_traits<dense_map<Args...>> {};
- /**
- * @brief Meta associative container traits for `dense_set`s of any type.
- * @tparam Args Template arguments for the container.
- */
- template<typename... Args>
- struct meta_associative_container_traits<dense_set<Args...>>
- : basic_meta_associative_container_traits<dense_set<Args...>> {};
- } // namespace entt
- #endif
- // #include "meta/context.hpp"
- #ifndef ENTT_META_CTX_HPP
- #define ENTT_META_CTX_HPP
- #include <memory>
- // #include "../container/dense_map.hpp"
- // #include "../core/fwd.hpp"
- // #include "../core/utility.hpp"
- // #include "fwd.hpp"
- namespace entt {
- /*! @cond TURN_OFF_DOXYGEN */
- namespace internal {
- struct meta_type_node;
- struct meta_context {
- dense_map<id_type, std::unique_ptr<meta_type_node>, identity> value;
- [[nodiscard]] inline static meta_context &from(meta_ctx &);
- [[nodiscard]] inline static const meta_context &from(const meta_ctx &);
- };
- } // namespace internal
- /*! @endcond */
- /*! @brief Disambiguation tag for constructors and the like. */
- class meta_ctx_arg_t final {};
- /*! @brief Constant of type meta_context_arg_t used to disambiguate calls. */
- inline constexpr meta_ctx_arg_t meta_ctx_arg{};
- /*! @brief Opaque meta context type. */
- class meta_ctx: private internal::meta_context {
- // attorney idiom like model to access the base class
- friend struct internal::meta_context;
- };
- /*! @cond TURN_OFF_DOXYGEN */
- [[nodiscard]] inline internal::meta_context &internal::meta_context::from(meta_ctx &ctx) {
- return ctx;
- }
- [[nodiscard]] inline const internal::meta_context &internal::meta_context::from(const meta_ctx &ctx) {
- return ctx;
- }
- /*! @endcond */
- } // namespace entt
- #endif
- // #include "meta/factory.hpp"
- #ifndef ENTT_META_FACTORY_HPP
- #define ENTT_META_FACTORY_HPP
- #include <cstddef>
- #include <cstdint>
- #include <functional>
- #include <memory>
- #include <tuple>
- #include <type_traits>
- #include <utility>
- // #include "../config/config.h"
- // #include "../core/bit.hpp"
- // #include "../core/fwd.hpp"
- // #include "../core/hashed_string.hpp"
- #ifndef ENTT_CORE_HASHED_STRING_HPP
- #define ENTT_CORE_HASHED_STRING_HPP
- #include <cstddef>
- #include <cstdint>
- // #include "fwd.hpp"
- namespace entt {
- /*! @cond TURN_OFF_DOXYGEN */
- namespace internal {
- template<typename = id_type>
- struct fnv_1a_params;
- template<>
- struct fnv_1a_params<std::uint32_t> {
- static constexpr auto offset = 2166136261;
- static constexpr auto prime = 16777619;
- };
- template<>
- struct fnv_1a_params<std::uint64_t> {
- static constexpr auto offset = 14695981039346656037ull;
- static constexpr auto prime = 1099511628211ull;
- };
- template<typename Char>
- struct basic_hashed_string {
- using value_type = Char;
- using size_type = std::size_t;
- using hash_type = id_type;
- const value_type *repr{};
- hash_type hash{fnv_1a_params<>::offset};
- size_type length{};
- };
- } // namespace internal
- /*! @endcond */
- /**
- * @brief Zero overhead unique identifier.
- *
- * A hashed string is a compile-time tool that allows users to use
- * human-readable identifiers in the codebase while using their numeric
- * counterparts at runtime.<br/>
- * Because of that, a hashed string can also be used in constant expressions if
- * required.
- *
- * @warning
- * This class doesn't take ownership of user-supplied strings nor does it make a
- * copy of them.
- *
- * @tparam Char Character type.
- */
- template<typename Char>
- class basic_hashed_string: internal::basic_hashed_string<Char> {
- using base_type = internal::basic_hashed_string<Char>;
- using params = internal::fnv_1a_params<>;
- struct const_wrapper {
- // non-explicit constructor on purpose
- constexpr const_wrapper(const typename base_type::value_type *str) noexcept
- : repr{str} {}
- const typename base_type::value_type *repr;
- };
- public:
- /*! @brief Character type. */
- using value_type = typename base_type::value_type;
- /*! @brief Unsigned integer type. */
- using size_type = typename base_type::size_type;
- /*! @brief Unsigned integer type. */
- using hash_type = typename base_type::hash_type;
- /**
- * @brief Returns directly the numeric representation of a string view.
- * @param str Human-readable identifier.
- * @param len Length of the string to hash.
- * @return The numeric representation of the string.
- */
- [[nodiscard]] static constexpr hash_type value(const value_type *str, const size_type len) noexcept {
- return basic_hashed_string{str, len};
- }
- /**
- * @brief Returns directly the numeric representation of a string.
- * @tparam N Number of characters of the identifier.
- * @param str Human-readable identifier.
- * @return The numeric representation of the string.
- */
- template<std::size_t N>
- // NOLINTNEXTLINE(cppcoreguidelines-avoid-c-arrays, modernize-avoid-c-arrays)
- [[nodiscard]] static ENTT_CONSTEVAL hash_type value(const value_type (&str)[N]) noexcept {
- return basic_hashed_string{str};
- }
- /**
- * @brief Returns directly the numeric representation of a string.
- * @param wrapper Helps achieving the purpose by relying on overloading.
- * @return The numeric representation of the string.
- */
- [[nodiscard]] static constexpr hash_type value(const_wrapper wrapper) noexcept {
- return basic_hashed_string{wrapper};
- }
- /*! @brief Constructs an empty hashed string. */
- constexpr basic_hashed_string() noexcept
- : basic_hashed_string{nullptr, 0u} {}
- /**
- * @brief Constructs a hashed string from a string view.
- * @param str Human-readable identifier.
- * @param len Length of the string to hash.
- */
- constexpr basic_hashed_string(const value_type *str, const size_type len) noexcept
- // NOLINTNEXTLINE(cppcoreguidelines-pro-bounds-array-to-pointer-decay)
- : base_type{str} {
- // NOLINTBEGIN(cppcoreguidelines-pro-bounds-pointer-arithmetic)
- for(; base_type::length < len; ++base_type::length) {
- base_type::hash = (base_type::hash ^ static_cast<id_type>(str[base_type::length])) * params::prime;
- }
- // NOLINTEND(cppcoreguidelines-pro-bounds-pointer-arithmetic)
- }
- /**
- * @brief Constructs a hashed string from an array of const characters.
- * @tparam N Number of characters of the identifier.
- * @param str Human-readable identifier.
- */
- template<std::size_t N>
- // NOLINTNEXTLINE(cppcoreguidelines-avoid-c-arrays, modernize-avoid-c-arrays)
- ENTT_CONSTEVAL basic_hashed_string(const value_type (&str)[N]) noexcept
- // NOLINTNEXTLINE(cppcoreguidelines-pro-bounds-array-to-pointer-decay)
- : base_type{str} {
- for(; str[base_type::length]; ++base_type::length) {
- base_type::hash = (base_type::hash ^ static_cast<id_type>(str[base_type::length])) * params::prime;
- }
- }
- /**
- * @brief Explicit constructor on purpose to avoid constructing a hashed
- * string directly from a `const value_type *`.
- *
- * @warning
- * The lifetime of the string is not extended nor is it copied.
- *
- * @param wrapper Helps achieving the purpose by relying on overloading.
- */
- explicit constexpr basic_hashed_string(const_wrapper wrapper) noexcept
- : base_type{wrapper.repr} {
- // NOLINTBEGIN(cppcoreguidelines-pro-bounds-pointer-arithmetic)
- for(; wrapper.repr[base_type::length]; ++base_type::length) {
- base_type::hash = (base_type::hash ^ static_cast<id_type>(wrapper.repr[base_type::length])) * params::prime;
- }
- // NOLINTEND(cppcoreguidelines-pro-bounds-pointer-arithmetic)
- }
- /**
- * @brief Returns the size of a hashed string.
- * @return The size of the hashed string.
- */
- [[nodiscard]] constexpr size_type size() const noexcept {
- return base_type::length;
- }
- /**
- * @brief Returns the human-readable representation of a hashed string.
- * @return The string used to initialize the hashed string.
- */
- [[nodiscard]] constexpr const value_type *data() const noexcept {
- return base_type::repr;
- }
- /**
- * @brief Returns the numeric representation of a hashed string.
- * @return The numeric representation of the hashed string.
- */
- [[nodiscard]] constexpr hash_type value() const noexcept {
- return base_type::hash;
- }
- /*! @copydoc data */
- [[nodiscard]] explicit constexpr operator const value_type *() const noexcept {
- return data();
- }
- /**
- * @brief Returns the numeric representation of a hashed string.
- * @return The numeric representation of the hashed string.
- */
- [[nodiscard]] constexpr operator hash_type() const noexcept {
- return value();
- }
- };
- /**
- * @brief Deduction guide.
- * @tparam Char Character type.
- * @param str Human-readable identifier.
- * @param len Length of the string to hash.
- */
- template<typename Char>
- basic_hashed_string(const Char *str, std::size_t len) -> basic_hashed_string<Char>;
- /**
- * @brief Deduction guide.
- * @tparam Char Character type.
- * @tparam N Number of characters of the identifier.
- * @param str Human-readable identifier.
- */
- template<typename Char, std::size_t N>
- // NOLINTNEXTLINE(cppcoreguidelines-avoid-c-arrays, modernize-avoid-c-arrays)
- basic_hashed_string(const Char (&str)[N]) -> basic_hashed_string<Char>;
- /**
- * @brief Compares two hashed strings.
- * @tparam Char Character type.
- * @param lhs A valid hashed string.
- * @param rhs A valid hashed string.
- * @return True if the two hashed strings are identical, false otherwise.
- */
- template<typename Char>
- [[nodiscard]] constexpr bool operator==(const basic_hashed_string<Char> &lhs, const basic_hashed_string<Char> &rhs) noexcept {
- return lhs.value() == rhs.value();
- }
- /**
- * @brief Compares two hashed strings.
- * @tparam Char Character type.
- * @param lhs A valid hashed string.
- * @param rhs A valid hashed string.
- * @return True if the two hashed strings differ, false otherwise.
- */
- template<typename Char>
- [[nodiscard]] constexpr bool operator!=(const basic_hashed_string<Char> &lhs, const basic_hashed_string<Char> &rhs) noexcept {
- return !(lhs == rhs);
- }
- /**
- * @brief Compares two hashed strings.
- * @tparam Char Character type.
- * @param lhs A valid hashed string.
- * @param rhs A valid hashed string.
- * @return True if the first element is less than the second, false otherwise.
- */
- template<typename Char>
- [[nodiscard]] constexpr bool operator<(const basic_hashed_string<Char> &lhs, const basic_hashed_string<Char> &rhs) noexcept {
- return lhs.value() < rhs.value();
- }
- /**
- * @brief Compares two hashed strings.
- * @tparam Char Character type.
- * @param lhs A valid hashed string.
- * @param rhs A valid hashed string.
- * @return True if the first element is less than or equal to the second, false
- * otherwise.
- */
- template<typename Char>
- [[nodiscard]] constexpr bool operator<=(const basic_hashed_string<Char> &lhs, const basic_hashed_string<Char> &rhs) noexcept {
- return !(rhs < lhs);
- }
- /**
- * @brief Compares two hashed strings.
- * @tparam Char Character type.
- * @param lhs A valid hashed string.
- * @param rhs A valid hashed string.
- * @return True if the first element is greater than the second, false
- * otherwise.
- */
- template<typename Char>
- [[nodiscard]] constexpr bool operator>(const basic_hashed_string<Char> &lhs, const basic_hashed_string<Char> &rhs) noexcept {
- return rhs < lhs;
- }
- /**
- * @brief Compares two hashed strings.
- * @tparam Char Character type.
- * @param lhs A valid hashed string.
- * @param rhs A valid hashed string.
- * @return True if the first element is greater than or equal to the second,
- * false otherwise.
- */
- template<typename Char>
- [[nodiscard]] constexpr bool operator>=(const basic_hashed_string<Char> &lhs, const basic_hashed_string<Char> &rhs) noexcept {
- return !(lhs < rhs);
- }
- inline namespace literals {
- /**
- * @brief User defined literal for hashed strings.
- * @param str The literal without its suffix.
- * @return A properly initialized hashed string.
- */
- [[nodiscard]] ENTT_CONSTEVAL hashed_string operator""_hs(const char *str, std::size_t) noexcept {
- return hashed_string{str};
- }
- /**
- * @brief User defined literal for hashed wstrings.
- * @param str The literal without its suffix.
- * @return A properly initialized hashed wstring.
- */
- [[nodiscard]] ENTT_CONSTEVAL hashed_wstring operator""_hws(const wchar_t *str, std::size_t) noexcept {
- return hashed_wstring{str};
- }
- } // namespace literals
- } // namespace entt
- #endif
- // #include "../core/type_info.hpp"
- // #include "../core/type_traits.hpp"
- // #include "../locator/locator.hpp"
- // #include "context.hpp"
- // #include "fwd.hpp"
- // #include "meta.hpp"
- // #include "node.hpp"
- // #include "policy.hpp"
- #ifndef ENTT_META_POLICY_HPP
- #define ENTT_META_POLICY_HPP
- #include <type_traits>
- namespace entt {
- /*! @cond TURN_OFF_DOXYGEN */
- namespace internal {
- struct meta_policy {};
- } // namespace internal
- /*! @endcond */
- /*! @brief Empty class type used to request the _as-is_ policy. */
- struct as_value_t final: private internal::meta_policy {
- /*! @cond TURN_OFF_DOXYGEN */
- template<typename>
- static constexpr bool value = true;
- /*! @endcond */
- };
- /*! @brief Empty class type used to request the _as void_ policy. */
- struct as_void_t final: private internal::meta_policy {
- /*! @cond TURN_OFF_DOXYGEN */
- template<typename>
- static constexpr bool value = true;
- /*! @endcond */
- };
- /*! @brief Empty class type used to request the _as ref_ policy. */
- struct as_ref_t final: private internal::meta_policy {
- /*! @cond TURN_OFF_DOXYGEN */
- template<typename Type>
- static constexpr bool value = std::is_reference_v<Type> && !std::is_const_v<std::remove_reference_t<Type>>;
- /*! @endcond */
- };
- /*! @brief Empty class type used to request the _as cref_ policy. */
- struct as_cref_t final: private internal::meta_policy {
- /*! @cond TURN_OFF_DOXYGEN */
- template<typename Type>
- static constexpr bool value = std::is_reference_v<Type>;
- /*! @endcond */
- };
- /*! @brief Empty class type used to request the _as auto_ policy. */
- struct as_is_t final: private internal::meta_policy {
- /*! @cond TURN_OFF_DOXYGEN */
- template<typename>
- static constexpr bool value = true;
- /*! @endcond */
- };
- /**
- * @brief Provides the member constant `value` to true if a type also is a meta
- * policy, false otherwise.
- * @tparam Type Type to check.
- */
- template<typename Type>
- struct is_meta_policy
- : std::bool_constant<std::is_base_of_v<internal::meta_policy, Type>> {};
- /**
- * @brief Helper variable template.
- * @tparam Type Type to check.
- */
- template<typename Type>
- inline constexpr bool is_meta_policy_v = is_meta_policy<Type>::value;
- } // namespace entt
- #endif
- // #include "range.hpp"
- // #include "resolve.hpp"
- #ifndef ENTT_META_RESOLVE_HPP
- #define ENTT_META_RESOLVE_HPP
- #include <type_traits>
- // #include "../core/type_info.hpp"
- // #include "../locator/locator.hpp"
- // #include "context.hpp"
- // #include "meta.hpp"
- // #include "node.hpp"
- // #include "range.hpp"
- namespace entt {
- /**
- * @brief Returns the meta type associated with a given type.
- * @tparam Type Type to use to search for a meta type.
- * @param ctx The context from which to search for meta types.
- * @return The meta type associated with the given type, if any.
- */
- template<typename Type>
- [[nodiscard]] meta_type resolve(const meta_ctx &ctx) noexcept {
- const auto &context = internal::meta_context::from(ctx);
- return {ctx, internal::resolve<std::remove_const_t<std::remove_reference_t<Type>>>(context)};
- }
- /**
- * @brief Returns the meta type associated with a given type.
- * @tparam Type Type to use to search for a meta type.
- * @return The meta type associated with the given type, if any.
- */
- template<typename Type>
- [[nodiscard]] meta_type resolve() noexcept {
- return resolve<Type>(locator<meta_ctx>::value_or());
- }
- /**
- * @brief Returns a range to use to visit all meta types.
- * @param ctx The context from which to search for meta types.
- * @return An iterable range to use to visit all meta types.
- */
- [[nodiscard]] inline meta_range<meta_type, typename decltype(internal::meta_context::value)::const_iterator> resolve(const meta_ctx &ctx) noexcept {
- const auto &context = internal::meta_context::from(ctx);
- return {{ctx, context.value.cbegin()}, {ctx, context.value.cend()}};
- }
- /**
- * @brief Returns a range to use to visit all meta types.
- * @return An iterable range to use to visit all meta types.
- */
- [[nodiscard]] inline meta_range<meta_type, typename decltype(internal::meta_context::value)::const_iterator> resolve() noexcept {
- return resolve(locator<meta_ctx>::value_or());
- }
- /**
- * @brief Returns the meta type associated with a given identifier, if any.
- * @param ctx The context from which to search for meta types.
- * @param id Unique identifier.
- * @return The meta type associated with the given identifier, if any.
- */
- [[nodiscard]] inline meta_type resolve(const meta_ctx &ctx, const id_type id) noexcept {
- for(auto &&curr: resolve(ctx)) {
- if(curr.second.id() == id) {
- return curr.second;
- }
- }
- return meta_type{};
- }
- /**
- * @brief Returns the meta type associated with a given identifier, if any.
- * @param id Unique identifier.
- * @return The meta type associated with the given identifier, if any.
- */
- [[nodiscard]] inline meta_type resolve(const id_type id) noexcept {
- return resolve(locator<meta_ctx>::value_or(), id);
- }
- /**
- * @brief Returns the meta type associated with a given type info object.
- * @param ctx The context from which to search for meta types.
- * @param info The type info object of the requested type.
- * @return The meta type associated with the given type info object, if any.
- */
- [[nodiscard]] inline meta_type resolve(const meta_ctx &ctx, const type_info &info) noexcept {
- const auto &context = internal::meta_context::from(ctx);
- const auto *elem = internal::try_resolve(context, info);
- return (elem != nullptr) ? meta_type{ctx, *elem} : meta_type{};
- }
- /**
- * @brief Returns the meta type associated with a given type info object.
- * @param info The type info object of the requested type.
- * @return The meta type associated with the given type info object, if any.
- */
- [[nodiscard]] inline meta_type resolve(const type_info &info) noexcept {
- return resolve(locator<meta_ctx>::value_or(), info);
- }
- } // namespace entt
- #endif
- // #include "utility.hpp"
- #ifndef ENTT_META_UTILITY_HPP
- #define ENTT_META_UTILITY_HPP
- #include <cstddef>
- #include <functional>
- #include <type_traits>
- #include <utility>
- // #include "../core/type_traits.hpp"
- // #include "../locator/locator.hpp"
- // #include "meta.hpp"
- // #include "node.hpp"
- // #include "policy.hpp"
- namespace entt {
- /**
- * @brief Meta function descriptor traits.
- * @tparam Ret Function return type.
- * @tparam Args Function arguments.
- * @tparam Static Function staticness.
- * @tparam Const Function constness.
- */
- template<typename Ret, typename Args, bool Static, bool Const>
- struct meta_function_descriptor_traits {
- /*! @brief Meta function return type. */
- using return_type = Ret;
- /*! @brief Meta function arguments. */
- using args_type = Args;
- /*! @brief True if the meta function is static, false otherwise. */
- static constexpr bool is_static = Static;
- /*! @brief True if the meta function is const, false otherwise. */
- static constexpr bool is_const = Const;
- };
- /*! @brief Primary template isn't defined on purpose. */
- template<typename, typename>
- struct meta_function_descriptor;
- /**
- * @brief Meta function descriptor.
- * @tparam Type Reflected type to which the meta function is associated.
- * @tparam Ret Function return type.
- * @tparam Class Actual owner of the member function.
- * @tparam Args Function arguments.
- */
- template<typename Type, typename Ret, typename Class, typename... Args>
- struct meta_function_descriptor<Type, Ret (Class::*)(Args...) const>
- : meta_function_descriptor_traits<
- Ret,
- std::conditional_t<std::is_base_of_v<Class, Type>, type_list<Args...>, type_list<const Class &, Args...>>,
- !std::is_base_of_v<Class, Type>,
- true> {};
- /**
- * @brief Meta function descriptor.
- * @tparam Type Reflected type to which the meta function is associated.
- * @tparam Ret Function return type.
- * @tparam Class Actual owner of the member function.
- * @tparam Args Function arguments.
- */
- template<typename Type, typename Ret, typename Class, typename... Args>
- struct meta_function_descriptor<Type, Ret (Class::*)(Args...)>
- : meta_function_descriptor_traits<
- Ret,
- std::conditional_t<std::is_base_of_v<Class, Type>, type_list<Args...>, type_list<Class &, Args...>>,
- !std::is_base_of_v<Class, Type>,
- false> {};
- /**
- * @brief Meta function descriptor.
- * @tparam Type Reflected type to which the meta data is associated.
- * @tparam Class Actual owner of the data member.
- * @tparam Ret Data member type.
- */
- template<typename Type, typename Ret, typename Class>
- struct meta_function_descriptor<Type, Ret Class::*>
- : meta_function_descriptor_traits<
- Ret &,
- std::conditional_t<std::is_base_of_v<Class, Type>, type_list<>, type_list<Class &>>,
- !std::is_base_of_v<Class, Type>,
- false> {};
- /**
- * @brief Meta function descriptor.
- * @tparam Type Reflected type to which the meta function is associated.
- * @tparam Ret Function return type.
- * @tparam MaybeType First function argument.
- * @tparam Args Other function arguments.
- */
- template<typename Type, typename Ret, typename MaybeType, typename... Args>
- struct meta_function_descriptor<Type, Ret (*)(MaybeType, Args...)>
- : meta_function_descriptor_traits<
- Ret,
- std::conditional_t<
- std::is_same_v<std::remove_const_t<std::remove_reference_t<MaybeType>>, Type> || std::is_base_of_v<std::remove_const_t<std::remove_reference_t<MaybeType>>, Type>,
- type_list<Args...>,
- type_list<MaybeType, Args...>>,
- !(std::is_same_v<std::remove_const_t<std::remove_reference_t<MaybeType>>, Type> || std::is_base_of_v<std::remove_const_t<std::remove_reference_t<MaybeType>>, Type>),
- std::is_const_v<std::remove_reference_t<MaybeType>> && (std::is_same_v<std::remove_const_t<std::remove_reference_t<MaybeType>>, Type> || std::is_base_of_v<std::remove_const_t<std::remove_reference_t<MaybeType>>, Type>)> {};
- /**
- * @brief Meta function descriptor.
- * @tparam Type Reflected type to which the meta function is associated.
- * @tparam Ret Function return type.
- */
- template<typename Type, typename Ret>
- struct meta_function_descriptor<Type, Ret (*)()>
- : meta_function_descriptor_traits<
- Ret,
- type_list<>,
- true,
- false> {};
- /**
- * @brief Meta function helper.
- *
- * Converts a function type to be associated with a reflected type into its meta
- * function descriptor.
- *
- * @tparam Type Reflected type to which the meta function is associated.
- * @tparam Candidate The actual function to associate with the reflected type.
- */
- template<typename Type, typename Candidate>
- class meta_function_helper {
- template<typename Ret, typename... Args, typename Class>
- static constexpr meta_function_descriptor<Type, Ret (Class::*)(Args...) const> get_rid_of_noexcept(Ret (Class::*)(Args...) const);
- template<typename Ret, typename... Args, typename Class>
- static constexpr meta_function_descriptor<Type, Ret (Class::*)(Args...)> get_rid_of_noexcept(Ret (Class::*)(Args...));
- template<typename Ret, typename Class, typename = std::enable_if_t<std::is_member_object_pointer_v<Ret Class::*>>>
- static constexpr meta_function_descriptor<Type, Ret Class::*> get_rid_of_noexcept(Ret Class::*);
- template<typename Ret, typename... Args>
- static constexpr meta_function_descriptor<Type, Ret (*)(Args...)> get_rid_of_noexcept(Ret (*)(Args...));
- template<typename Class>
- static constexpr meta_function_descriptor<Class, decltype(&Class::operator())> get_rid_of_noexcept(Class);
- public:
- /*! @brief The meta function descriptor of the given function. */
- using type = decltype(get_rid_of_noexcept(std::declval<Candidate>()));
- };
- /**
- * @brief Helper type.
- * @tparam Type Reflected type to which the meta function is associated.
- * @tparam Candidate The actual function to associate with the reflected type.
- */
- template<typename Type, typename Candidate>
- using meta_function_helper_t = typename meta_function_helper<Type, Candidate>::type;
- /**
- * @brief Wraps a value depending on the given policy.
- *
- * This function always returns a wrapped value in the requested context.<br/>
- * Therefore, if the passed value is itself a wrapped object with a different
- * context, it undergoes a rebinding to the requested context.
- *
- * @tparam Policy Optional policy (no policy set by default).
- * @tparam Type Type of value to wrap.
- * @param ctx The context from which to search for meta types.
- * @param value Value to wrap.
- * @return A meta any containing the returned value, if any.
- */
- template<typename Policy = as_value_t, typename Type>
- [[nodiscard]] std::enable_if_t<is_meta_policy_v<Policy>, meta_any> meta_dispatch(const meta_ctx &ctx, [[maybe_unused]] Type &&value) {
- if constexpr(std::is_same_v<Policy, as_cref_t>) {
- static_assert(std::is_lvalue_reference_v<Type>, "Invalid type");
- return meta_any{ctx, std::in_place_type<const std::remove_reference_t<Type> &>, std::as_const(value)};
- } else if constexpr(std::is_same_v<Policy, as_ref_t> || (std::is_same_v<Policy, as_is_t> && std::is_lvalue_reference_v<Type>)) {
- return meta_any{ctx, std::in_place_type<Type>, value};
- } else if constexpr(std::is_same_v<Policy, as_void_t>) {
- return meta_any{ctx, std::in_place_type<void>};
- } else {
- return meta_any{ctx, std::forward<Type>(value)};
- }
- }
- /**
- * @brief Wraps a value depending on the given policy.
- * @tparam Policy Optional policy (no policy set by default).
- * @tparam Type Type of value to wrap.
- * @param value Value to wrap.
- * @return A meta any containing the returned value, if any.
- */
- template<typename Policy = as_value_t, typename Type>
- [[nodiscard]] std::enable_if_t<is_meta_policy_v<Policy>, meta_any> meta_dispatch(Type &&value) {
- return meta_dispatch<Policy, Type>(locator<meta_ctx>::value_or(), std::forward<Type>(value));
- }
- /*! @cond TURN_OFF_DOXYGEN */
- namespace internal {
- template<typename Policy, typename Candidate, typename... Args>
- [[nodiscard]] meta_any meta_invoke_with_args(const meta_ctx &ctx, Candidate &&candidate, Args &&...args) {
- if constexpr(std::is_void_v<decltype(std::invoke(std::forward<Candidate>(candidate), args...))>) {
- std::invoke(std::forward<Candidate>(candidate), args...);
- return meta_any{ctx, std::in_place_type<void>};
- } else {
- return meta_dispatch<Policy>(ctx, std::invoke(std::forward<Candidate>(candidate), args...));
- }
- }
- template<typename Type, typename Policy, typename Candidate, std::size_t... Index>
- [[nodiscard]] meta_any meta_invoke(meta_any &instance, Candidate &&candidate, [[maybe_unused]] meta_any *const args, std::index_sequence<Index...>) {
- using descriptor = meta_function_helper_t<Type, std::remove_reference_t<Candidate>>;
- // NOLINTBEGIN(cppcoreguidelines-pro-bounds-pointer-arithmetic) - waiting for C++20 (and std::span)
- if constexpr(std::is_invocable_v<std::remove_reference_t<Candidate>, const Type &, type_list_element_t<Index, typename descriptor::args_type>...>) {
- if(const auto *const clazz = instance.try_cast<const Type>(); clazz && ((args + Index)->allow_cast<type_list_element_t<Index, typename descriptor::args_type>>() && ...)) {
- return meta_invoke_with_args<Policy>(instance.context(), std::forward<Candidate>(candidate), *clazz, (args + Index)->cast<type_list_element_t<Index, typename descriptor::args_type>>()...);
- }
- } else if constexpr(std::is_invocable_v<std::remove_reference_t<Candidate>, Type &, type_list_element_t<Index, typename descriptor::args_type>...>) {
- if(auto *const clazz = instance.try_cast<Type>(); clazz && ((args + Index)->allow_cast<type_list_element_t<Index, typename descriptor::args_type>>() && ...)) {
- return meta_invoke_with_args<Policy>(instance.context(), std::forward<Candidate>(candidate), *clazz, (args + Index)->cast<type_list_element_t<Index, typename descriptor::args_type>>()...);
- }
- } else {
- if(((args + Index)->allow_cast<type_list_element_t<Index, typename descriptor::args_type>>() && ...)) {
- return meta_invoke_with_args<Policy>(instance.context(), std::forward<Candidate>(candidate), (args + Index)->cast<type_list_element_t<Index, typename descriptor::args_type>>()...);
- }
- }
- // NOLINTEND(cppcoreguidelines-pro-bounds-pointer-arithmetic)
- return meta_any{meta_ctx_arg, instance.context()};
- }
- template<typename Type, typename... Args, std::size_t... Index>
- [[nodiscard]] meta_any meta_construct(const meta_ctx &ctx, meta_any *const args, std::index_sequence<Index...>) {
- // NOLINTBEGIN(cppcoreguidelines-pro-bounds-pointer-arithmetic) - waiting for C++20 (and std::span)
- if(((args + Index)->allow_cast<Args>() && ...)) {
- return meta_any{ctx, std::in_place_type<Type>, (args + Index)->cast<Args>()...};
- }
- // NOLINTEND(cppcoreguidelines-pro-bounds-pointer-arithmetic)
- return meta_any{meta_ctx_arg, ctx};
- }
- } // namespace internal
- /*! @endcond */
- /**
- * @brief Returns the meta type of the i-th element of a list of arguments.
- * @tparam Type Type list of the actual types of arguments.
- * @param ctx The context from which to search for meta types.
- * @param index The index of the element for which to return the meta type.
- * @return The meta type of the i-th element of the list of arguments.
- */
- template<typename Type>
- [[nodiscard]] meta_type meta_arg(const meta_ctx &ctx, const std::size_t index) noexcept {
- const auto &context = internal::meta_context::from(ctx);
- return {ctx, internal::meta_arg_node(context, Type{}, index)};
- }
- /**
- * @brief Returns the meta type of the i-th element of a list of arguments.
- * @tparam Type Type list of the actual types of arguments.
- * @param index The index of the element for which to return the meta type.
- * @return The meta type of the i-th element of the list of arguments.
- */
- template<typename Type>
- [[nodiscard]] meta_type meta_arg(const std::size_t index) noexcept {
- return meta_arg<Type>(locator<meta_ctx>::value_or(), index);
- }
- /**
- * @brief Sets the value of a given variable.
- * @tparam Type Reflected type to which the variable is associated.
- * @tparam Data The actual variable to set.
- * @param instance An opaque instance of the underlying type, if required.
- * @param value Parameter to use to set the variable.
- * @return True in case of success, false otherwise.
- */
- template<typename Type, auto Data>
- [[nodiscard]] bool meta_setter([[maybe_unused]] meta_handle instance, [[maybe_unused]] meta_any value) {
- if constexpr(std::is_member_function_pointer_v<decltype(Data)> || std::is_function_v<std::remove_reference_t<std::remove_pointer_t<decltype(Data)>>>) {
- using descriptor = meta_function_helper_t<Type, decltype(Data)>;
- using data_type = type_list_element_t<descriptor::is_static, typename descriptor::args_type>;
- if(auto *const clazz = instance->try_cast<Type>(); clazz && value.allow_cast<data_type>()) {
- std::invoke(Data, *clazz, value.cast<data_type>());
- return true;
- }
- } else if constexpr(std::is_member_object_pointer_v<decltype(Data)>) {
- using data_type = std::remove_reference_t<typename meta_function_helper_t<Type, decltype(Data)>::return_type>;
- if constexpr(!std::is_array_v<data_type> && !std::is_const_v<data_type>) {
- if(auto *const clazz = instance->try_cast<Type>(); clazz && value.allow_cast<data_type>()) {
- std::invoke(Data, *clazz) = value.cast<data_type>();
- return true;
- }
- }
- } else if constexpr(std::is_pointer_v<decltype(Data)>) {
- using data_type = std::remove_reference_t<decltype(*Data)>;
- if constexpr(!std::is_array_v<data_type> && !std::is_const_v<data_type>) {
- if(value.allow_cast<data_type>()) {
- *Data = value.cast<data_type>();
- return true;
- }
- }
- }
- return false;
- }
- /**
- * @brief Gets the value of a given variable.
- * @tparam Type Reflected type to which the variable is associated.
- * @tparam Data The actual variable to get.
- * @tparam Policy Optional policy (no policy set by default).
- * @param instance An opaque instance of the underlying type, if required.
- * @return A meta any containing the value of the underlying variable.
- */
- template<typename Type, auto Data, typename Policy = as_value_t>
- [[nodiscard]] std::enable_if_t<is_meta_policy_v<Policy>, meta_any> meta_getter(meta_handle instance) {
- if constexpr(std::is_member_pointer_v<decltype(Data)> || std::is_function_v<std::remove_reference_t<std::remove_pointer_t<decltype(Data)>>>) {
- if constexpr(!std::is_array_v<std::remove_const_t<std::remove_reference_t<std::invoke_result_t<decltype(Data), Type &>>>>) {
- if constexpr(std::is_invocable_v<decltype(Data), Type &>) {
- if(auto *clazz = instance->try_cast<Type>(); clazz) {
- return meta_dispatch<Policy>(instance->context(), std::invoke(Data, *clazz));
- }
- }
- if constexpr(std::is_invocable_v<decltype(Data), const Type &>) {
- if(auto *fallback = instance->try_cast<const Type>(); fallback) {
- return meta_dispatch<Policy>(instance->context(), std::invoke(Data, *fallback));
- }
- }
- }
- return meta_any{meta_ctx_arg, instance->context()};
- } else if constexpr(std::is_pointer_v<decltype(Data)>) {
- if constexpr(std::is_array_v<std::remove_pointer_t<decltype(Data)>>) {
- return meta_any{meta_ctx_arg, instance->context()};
- } else {
- return meta_dispatch<Policy>(instance->context(), *Data);
- }
- } else {
- return meta_dispatch<Policy>(instance->context(), Data);
- }
- }
- /**
- * @brief Tries to _invoke_ an object given a list of erased parameters.
- * @tparam Type Reflected type to which the object to _invoke_ is associated.
- * @tparam Policy Optional policy (no policy set by default).
- * @tparam Candidate The type of the actual object to _invoke_.
- * @param instance An opaque instance of the underlying type, if required.
- * @param candidate The actual object to _invoke_.
- * @param args Parameters to use to _invoke_ the object.
- * @return A meta any containing the returned value, if any.
- */
- template<typename Type, typename Policy = as_value_t, typename Candidate>
- [[nodiscard]] std::enable_if_t<is_meta_policy_v<Policy>, meta_any> meta_invoke(meta_handle instance, Candidate &&candidate, meta_any *const args) {
- return internal::meta_invoke<Type, Policy>(*instance.operator->(), std::forward<Candidate>(candidate), args, std::make_index_sequence<meta_function_helper_t<Type, std::remove_reference_t<Candidate>>::args_type::size>{});
- }
- /**
- * @brief Tries to invoke a function given a list of erased parameters.
- * @tparam Type Reflected type to which the function is associated.
- * @tparam Candidate The actual function to invoke.
- * @tparam Policy Optional policy (no policy set by default).
- * @param instance An opaque instance of the underlying type, if required.
- * @param args Parameters to use to invoke the function.
- * @return A meta any containing the returned value, if any.
- */
- template<typename Type, auto Candidate, typename Policy = as_value_t>
- [[nodiscard]] std::enable_if_t<is_meta_policy_v<Policy>, meta_any> meta_invoke(meta_handle instance, meta_any *const args) {
- return internal::meta_invoke<Type, Policy>(*instance.operator->(), Candidate, args, std::make_index_sequence<meta_function_helper_t<Type, std::remove_reference_t<decltype(Candidate)>>::args_type::size>{});
- }
- /**
- * @brief Tries to construct an instance given a list of erased parameters.
- *
- * @warning
- * The context provided is used only for the return type.<br/>
- * It's up to the caller to bind the arguments to the right context(s).
- *
- * @tparam Type Actual type of the instance to construct.
- * @tparam Args Types of arguments expected.
- * @param ctx The context from which to search for meta types.
- * @param args Parameters to use to construct the instance.
- * @return A meta any containing the new instance, if any.
- */
- template<typename Type, typename... Args>
- [[nodiscard]] meta_any meta_construct(const meta_ctx &ctx, meta_any *const args) {
- return internal::meta_construct<Type, Args...>(ctx, args, std::index_sequence_for<Args...>{});
- }
- /**
- * @brief Tries to construct an instance given a list of erased parameters.
- * @tparam Type Actual type of the instance to construct.
- * @tparam Args Types of arguments expected.
- * @param args Parameters to use to construct the instance.
- * @return A meta any containing the new instance, if any.
- */
- template<typename Type, typename... Args>
- [[nodiscard]] meta_any meta_construct(meta_any *const args) {
- return meta_construct<Type, Args...>(locator<meta_ctx>::value_or(), args);
- }
- /**
- * @brief Tries to construct an instance given a list of erased parameters.
- *
- * @warning
- * The context provided is used only for the return type.<br/>
- * It's up to the caller to bind the arguments to the right context(s).
- *
- * @tparam Type Reflected type to which the object to _invoke_ is associated.
- * @tparam Policy Optional policy (no policy set by default).
- * @tparam Candidate The type of the actual object to _invoke_.
- * @param ctx The context from which to search for meta types.
- * @param candidate The actual object to _invoke_.
- * @param args Parameters to use to _invoke_ the object.
- * @return A meta any containing the returned value, if any.
- */
- template<typename Type, typename Policy = as_value_t, typename Candidate>
- [[nodiscard]] meta_any meta_construct(const meta_ctx &ctx, Candidate &&candidate, meta_any *const args) {
- if constexpr(meta_function_helper_t<Type, Candidate>::is_static || std::is_class_v<std::remove_const_t<std::remove_reference_t<Candidate>>>) {
- meta_any placeholder{meta_ctx_arg, ctx};
- return internal::meta_invoke<Type, Policy>(placeholder, std::forward<Candidate>(candidate), args, std::make_index_sequence<meta_function_helper_t<Type, std::remove_reference_t<Candidate>>::args_type::size>{});
- } else {
- // NOLINTNEXTLINE(cppcoreguidelines-pro-bounds-pointer-arithmetic) - waiting for C++20 (and std::span)
- return internal::meta_invoke<Type, Policy>(*args, std::forward<Candidate>(candidate), args + 1u, std::make_index_sequence<meta_function_helper_t<Type, std::remove_reference_t<Candidate>>::args_type::size>{});
- }
- }
- /**
- * @brief Tries to construct an instance given a list of erased parameters.
- * @tparam Type Reflected type to which the object to _invoke_ is associated.
- * @tparam Policy Optional policy (no policy set by default).
- * @tparam Candidate The type of the actual object to _invoke_.
- * @param candidate The actual object to _invoke_.
- * @param args Parameters to use to _invoke_ the object.
- * @return A meta any containing the returned value, if any.
- */
- template<typename Type, typename Policy = as_value_t, typename Candidate>
- [[nodiscard]] std::enable_if_t<is_meta_policy_v<Policy>, meta_any> meta_construct(Candidate &&candidate, meta_any *const args) {
- return meta_construct<Type, Policy>(locator<meta_ctx>::value_or(), std::forward<Candidate>(candidate), args);
- }
- /**
- * @brief Tries to construct an instance given a list of erased parameters.
- *
- * @warning
- * The context provided is used only for the return type.<br/>
- * It's up to the caller to bind the arguments to the right context(s).
- *
- * @tparam Type Reflected type to which the function is associated.
- * @tparam Candidate The actual function to invoke.
- * @tparam Policy Optional policy (no policy set by default).
- * @param ctx The context from which to search for meta types.
- * @param args Parameters to use to invoke the function.
- * @return A meta any containing the returned value, if any.
- */
- template<typename Type, auto Candidate, typename Policy = as_value_t>
- [[nodiscard]] std::enable_if_t<is_meta_policy_v<Policy>, meta_any> meta_construct(const meta_ctx &ctx, meta_any *const args) {
- return meta_construct<Type, Policy>(ctx, Candidate, args);
- }
- /**
- * @brief Tries to construct an instance given a list of erased parameters.
- * @tparam Type Reflected type to which the function is associated.
- * @tparam Candidate The actual function to invoke.
- * @tparam Policy Optional policy (no policy set by default).
- * @param args Parameters to use to invoke the function.
- * @return A meta any containing the returned value, if any.
- */
- template<typename Type, auto Candidate, typename Policy = as_value_t>
- [[nodiscard]] std::enable_if_t<is_meta_policy_v<Policy>, meta_any> meta_construct(meta_any *const args) {
- return meta_construct<Type, Candidate, Policy>(locator<meta_ctx>::value_or(), args);
- }
- } // namespace entt
- #endif
- namespace entt {
- /*! @cond TURN_OFF_DOXYGEN */
- namespace internal {
- class basic_meta_factory {
- using invoke_type = std::remove_pointer_t<decltype(meta_func_node::invoke)>;
- [[nodiscard]] auto &fetch_node() noexcept {
- return *meta_context::from(*ctx).value[parent];
- }
- [[nodiscard]] auto *find_member_or_assert() {
- auto *member = find_member<&meta_data_node::id>(fetch_node().details->data, bucket);
- ENTT_ASSERT(member != nullptr, "Cannot find member");
- return member;
- }
- [[nodiscard]] auto *find_overload_or_assert() {
- auto *overload = find_overload(find_member<&meta_func_node::id>(fetch_node().details->func, bucket), invoke);
- ENTT_ASSERT(overload != nullptr, "Cannot find overload");
- return overload;
- }
- void reset_bucket(const id_type id, invoke_type *const ref = nullptr) {
- invoke = ref;
- bucket = id;
- }
- protected:
- void type(const id_type id, const char *name) noexcept {
- reset_bucket(parent);
- auto &elem = fetch_node();
- ENTT_ASSERT(elem.id == id || !resolve(*ctx, id), "Duplicate identifier");
- elem.name = name;
- elem.id = id;
- }
- template<typename Type>
- void insert_or_assign(Type node) {
- auto &elem = fetch_node();
- reset_bucket(parent);
- if constexpr(std::is_same_v<Type, meta_base_node>) {
- auto *member = find_member<&meta_base_node::type>(elem.details->base, node.type);
- member ? (*member = node) : elem.details->base.emplace_back(node);
- } else if constexpr(std::is_same_v<Type, meta_conv_node>) {
- auto *member = find_member<&meta_conv_node::type>(elem.details->conv, node.type);
- member ? (*member = node) : elem.details->conv.emplace_back(node);
- } else {
- static_assert(std::is_same_v<Type, meta_ctor_node>, "Unexpected type");
- auto *member = find_member<&meta_ctor_node::id>(elem.details->ctor, node.id);
- member ? (*member = node) : elem.details->ctor.emplace_back(node);
- }
- }
- void data(meta_data_node node) {
- auto &elem = fetch_node();
- reset_bucket(node.id);
- if(auto *member = find_member<&meta_data_node::id>(elem.details->data, node.id); member == nullptr) {
- elem.details->data.emplace_back(std::move(node));
- } else if(member->set != node.set || member->get != node.get) {
- *member = std::move(node);
- }
- }
- void func(meta_func_node node) {
- auto &elem = fetch_node();
- reset_bucket(node.id, node.invoke);
- if(auto *member = find_member<&meta_func_node::id>(elem.details->func, node.id); member == nullptr) {
- elem.details->func.emplace_back(std::move(node));
- } else if(auto *overload = find_overload(member, node.invoke); overload == nullptr) {
- while(member->next != nullptr) { member = member->next.get(); }
- member->next = std::make_unique<meta_func_node>(std::move(node));
- }
- }
- void traits(const meta_traits value, const bool unset) {
- auto set_or_unset_on = [=](auto &node) {
- node.traits = (unset ? (node.traits & ~value) : (node.traits | value));
- };
- if(bucket == parent) {
- set_or_unset_on(fetch_node());
- } else if(invoke == nullptr) {
- set_or_unset_on(*find_member_or_assert());
- } else {
- set_or_unset_on(*find_overload_or_assert());
- }
- }
- void custom(meta_custom_node node) {
- if(bucket == parent) {
- fetch_node().custom = std::move(node);
- } else if(invoke == nullptr) {
- find_member_or_assert()->custom = std::move(node);
- } else {
- find_overload_or_assert()->custom = std::move(node);
- }
- }
- public:
- basic_meta_factory(meta_ctx &area, meta_type_node node)
- : ctx{&area},
- parent{node.info->hash()},
- bucket{parent} {
- if(auto *curr = meta_context::from(*ctx).value.try_emplace(parent, std::make_unique<meta_type_node>(std::move(node))).first->second.get(); curr->details == nullptr) {
- curr->details = std::make_unique<meta_type_descriptor>();
- }
- }
- private:
- meta_ctx *ctx{};
- id_type parent{};
- id_type bucket{};
- invoke_type *invoke{};
- };
- } // namespace internal
- /*! @endcond */
- /**
- * @brief Meta factory to be used for reflection purposes.
- * @tparam Type Type for which the factory was created.
- */
- template<typename Type>
- class meta_factory: private internal::basic_meta_factory {
- using base_type = internal::basic_meta_factory;
- public:
- /*! @brief Type of object for which this factory builds a meta type. */
- using element_type = Type;
- /*! @brief Default constructor. */
- meta_factory() noexcept
- : meta_factory{locator<meta_ctx>::value_or()} {}
- /**
- * @brief Context aware constructor.
- * @param area The context into which to construct meta types.
- */
- meta_factory(meta_ctx &area) noexcept
- : internal::basic_meta_factory{area, internal::setup_node_for<Type>()} {}
- /**
- * @brief Assigns a custom unique identifier to a meta type.
- * @param name A custom unique identifier as a **string literal**.
- * @return A meta factory for the given type.
- */
- meta_factory type(const char *name) noexcept {
- return type(hashed_string::value(name), name);
- }
- /**
- * @brief Assigns a custom unique identifier to a meta type.
- * @param id A custom unique identifier.
- * @param name An optional name for the type as a **string literal**.
- * @return A meta factory for the given type.
- */
- meta_factory type(const id_type id, const char *name = nullptr) noexcept {
- base_type::type(id, name);
- return *this;
- }
- /**
- * @brief Assigns a meta base to a meta type.
- *
- * A reflected base class must be a real base class of the reflected type.
- *
- * @tparam Base Type of the base class to assign to the meta type.
- * @return A meta factory for the parent type.
- */
- template<typename Base>
- meta_factory base() noexcept {
- static_assert(!std::is_same_v<Type, Base> && std::is_base_of_v<Base, Type>, "Invalid base type");
- auto *const op = +[](const void *instance) noexcept { return static_cast<const void *>(static_cast<const Base *>(static_cast<const Type *>(instance))); };
- base_type::insert_or_assign(internal::meta_base_node{type_id<Base>().hash(), &internal::resolve<Base>, op});
- return *this;
- }
- /**
- * @brief Assigns a meta conversion function to a meta type.
- *
- * Conversion functions can be either free functions or member
- * functions.<br/>
- * In case of free functions, they must accept a const reference to an
- * instance of the parent type as an argument. In case of member functions,
- * they should have no arguments at all.
- *
- * @tparam Candidate The actual function to use for the conversion.
- * @return A meta factory for the parent type.
- */
- template<auto Candidate>
- auto conv() noexcept {
- using conv_type = std::remove_const_t<std::remove_reference_t<std::invoke_result_t<decltype(Candidate), Type &>>>;
- auto *const op = +[](const meta_ctx &area, const void *instance) { return forward_as_meta(area, std::invoke(Candidate, *static_cast<const Type *>(instance))); };
- base_type::insert_or_assign(internal::meta_conv_node{type_id<conv_type>().hash(), op});
- return *this;
- }
- /**
- * @brief Assigns a meta conversion function to a meta type.
- *
- * The given type must be such that an instance of the reflected type can be
- * converted to it.
- *
- * @tparam To Type of the conversion function to assign to the meta type.
- * @return A meta factory for the parent type.
- */
- template<typename To>
- meta_factory conv() noexcept {
- using conv_type = std::remove_const_t<std::remove_reference_t<To>>;
- auto *const op = +[](const meta_ctx &area, const void *instance) { return forward_as_meta(area, static_cast<To>(*static_cast<const Type *>(instance))); };
- base_type::insert_or_assign(internal::meta_conv_node{type_id<conv_type>().hash(), op});
- return *this;
- }
- /**
- * @brief Assigns a meta constructor to a meta type.
- *
- * Both member functions and free function can be assigned to meta types in
- * the role of constructors. All that is required is that they return an
- * instance of the underlying type.<br/>
- * From a client's point of view, nothing changes if a constructor of a meta
- * type is a built-in one or not.
- *
- * @tparam Candidate The actual function to use as a constructor.
- * @tparam Policy Optional policy (no policy set by default).
- * @return A meta factory for the parent type.
- */
- template<auto Candidate, typename Policy = as_value_t>
- meta_factory ctor() noexcept {
- using descriptor = meta_function_helper_t<Type, decltype(Candidate)>;
- static_assert(Policy::template value<typename descriptor::return_type>, "Invalid return type for the given policy");
- static_assert(std::is_same_v<std::remove_const_t<std::remove_reference_t<typename descriptor::return_type>>, Type>, "The function doesn't return an object of the required type");
- base_type::insert_or_assign(internal::meta_ctor_node{type_id<typename descriptor::args_type>().hash(), descriptor::args_type::size, &meta_arg<typename descriptor::args_type>, &meta_construct<Type, Candidate, Policy>});
- return *this;
- }
- /**
- * @brief Assigns a meta constructor to a meta type.
- *
- * A meta constructor is uniquely identified by the types of its arguments
- * and is such that there exists an actual constructor of the underlying
- * type that can be invoked with parameters whose types are those given.
- *
- * @tparam Args Types of arguments to use to construct an instance.
- * @return A meta factory for the parent type.
- */
- template<typename... Args>
- meta_factory ctor() noexcept {
- // default constructor is already implicitly generated, no need for redundancy
- if constexpr(sizeof...(Args) != 0u) {
- using descriptor = meta_function_helper_t<Type, Type (*)(Args...)>;
- base_type::insert_or_assign(internal::meta_ctor_node{type_id<typename descriptor::args_type>().hash(), descriptor::args_type::size, &meta_arg<typename descriptor::args_type>, &meta_construct<Type, Args...>});
- }
- return *this;
- }
- /**
- * @brief Assigns a meta data to a meta type.
- * @tparam Data The actual variable to attach to the meta type.
- * @tparam Policy Optional policy (no policy set by default).
- * @param name A custom unique identifier as a **string literal**.
- * @return A meta factory for the given type.
- */
- template<auto Data, typename Policy = as_value_t>
- meta_factory data(const char *name) noexcept {
- return data<Data, Policy>(hashed_string::value(name), name);
- }
- /**
- * @brief Assigns a meta data to a meta type.
- *
- * Both data members and static and global variables, as well as constants
- * of any kind, can be assigned to a meta type.<br/>
- * From a client's point of view, all the variables associated with the
- * reflected object will appear as if they were part of the type itself.
- *
- * @tparam Data The actual variable to attach to the meta type.
- * @tparam Policy Optional policy (no policy set by default).
- * @param id Unique identifier.
- * @param name An optional name for the meta data as a **string literal**.
- * @return A meta factory for the parent type.
- */
- template<auto Data, typename Policy = as_value_t>
- meta_factory data(const id_type id, const char *name = nullptr) noexcept {
- if constexpr(std::is_member_object_pointer_v<decltype(Data)>) {
- using data_type = std::invoke_result_t<decltype(Data), Type &>;
- static_assert(Policy::template value<data_type>, "Invalid return type for the given policy");
- base_type::data(
- internal::meta_data_node{
- id,
- name,
- /* this is never static */
- std::is_const_v<std::remove_reference_t<data_type>> ? internal::meta_traits::is_const : internal::meta_traits::is_none,
- 1u,
- &internal::resolve<std::remove_const_t<std::remove_reference_t<data_type>>>,
- &meta_arg<type_list<std::remove_const_t<std::remove_reference_t<data_type>>>>,
- &meta_setter<Type, Data>,
- &meta_getter<Type, Data, Policy>});
- } else {
- using data_type = std::remove_pointer_t<decltype(Data)>;
- if constexpr(std::is_pointer_v<decltype(Data)>) {
- static_assert(Policy::template value<decltype(*Data)>, "Invalid return type for the given policy");
- } else {
- static_assert(Policy::template value<data_type>, "Invalid return type for the given policy");
- }
- base_type::data(
- internal::meta_data_node{
- id,
- name,
- ((!std::is_pointer_v<decltype(Data)> || std::is_const_v<data_type>) ? internal::meta_traits::is_const : internal::meta_traits::is_none) | internal::meta_traits::is_static,
- 1u,
- &internal::resolve<std::remove_const_t<std::remove_reference_t<data_type>>>,
- &meta_arg<type_list<std::remove_const_t<std::remove_reference_t<data_type>>>>,
- &meta_setter<Type, Data>,
- &meta_getter<Type, Data, Policy>});
- }
- return *this;
- }
- /**
- * @brief Assigns a meta data to a meta type by means of its setter and
- * getter.
- * @tparam Setter The actual function to use as a setter.
- * @tparam Getter The actual function to use as a getter.
- * @tparam Policy Optional policy (no policy set by default).
- * @param name A custom unique identifier as a **string literal**.
- * @return A meta factory for the given type.
- */
- template<auto Setter, auto Getter, typename Policy = as_value_t>
- meta_factory data(const char *name) noexcept {
- return data<Setter, Getter, Policy>(hashed_string::value(name), name);
- }
- /**
- * @brief Assigns a meta data to a meta type by means of its setter and
- * getter.
- *
- * Setters and getters can be either free functions, member functions or a
- * mix of them.<br/>
- * In case of free functions, setters and getters must accept a reference to
- * an instance of the parent type as their first argument. A setter has then
- * an extra argument of a type convertible to that of the parameter to
- * set.<br/>
- * In case of member functions, getters have no arguments at all, while
- * setters has an argument of a type convertible to that of the parameter to
- * set.
- *
- * @tparam Setter The actual function to use as a setter.
- * @tparam Getter The actual function to use as a getter.
- * @tparam Policy Optional policy (no policy set by default).
- * @param id Unique identifier.
- * @param name An optional name for the meta data as a **string literal**.
- * @return A meta factory for the parent type.
- */
- template<auto Setter, auto Getter, typename Policy = as_value_t>
- meta_factory data(const id_type id, const char *name = nullptr) noexcept {
- using descriptor = meta_function_helper_t<Type, decltype(Getter)>;
- static_assert(Policy::template value<typename descriptor::return_type>, "Invalid return type for the given policy");
- if constexpr(std::is_same_v<decltype(Setter), std::nullptr_t>) {
- base_type::data(
- internal::meta_data_node{
- id,
- name,
- /* this is never static */
- internal::meta_traits::is_const,
- 0u,
- &internal::resolve<std::remove_const_t<std::remove_reference_t<typename descriptor::return_type>>>,
- &meta_arg<type_list<>>,
- &meta_setter<Type, Setter>,
- &meta_getter<Type, Getter, Policy>});
- } else {
- using args_type = typename meta_function_helper_t<Type, decltype(Setter)>::args_type;
- base_type::data(
- internal::meta_data_node{
- id,
- name,
- /* this is never static nor const */
- internal::meta_traits::is_none,
- 1u,
- &internal::resolve<std::remove_const_t<std::remove_reference_t<typename descriptor::return_type>>>,
- &meta_arg<type_list<type_list_element_t<static_cast<std::size_t>(args_type::size != 1u), args_type>>>,
- &meta_setter<Type, Setter>,
- &meta_getter<Type, Getter, Policy>});
- }
- return *this;
- }
- /**
- * @brief Assigns a meta function to a meta type.
- * @tparam Candidate The actual function to attach to the meta function.
- * @tparam Policy Optional policy (no policy set by default).
- * @param name A custom unique identifier as a **string literal**.
- * @return A meta factory for the given type.
- */
- template<auto Candidate, typename Policy = as_value_t>
- meta_factory func(const char *name) noexcept {
- return func<Candidate, Policy>(hashed_string::value(name), name);
- }
- /**
- * @brief Assigns a meta function to a meta type.
- *
- * Both member functions and free functions can be assigned to a meta
- * type.<br/>
- * From a client's point of view, all the functions associated with the
- * reflected object will appear as if they were part of the type itself.
- *
- * @tparam Candidate The actual function to attach to the meta type.
- * @tparam Policy Optional policy (no policy set by default).
- * @param id Unique identifier.
- * @param name An optional name for the function as a **string literal**.
- * @return A meta factory for the parent type.
- */
- template<auto Candidate, typename Policy = as_value_t>
- meta_factory func(const id_type id, const char *name = nullptr) noexcept {
- using descriptor = meta_function_helper_t<Type, decltype(Candidate)>;
- static_assert(Policy::template value<typename descriptor::return_type>, "Invalid return type for the given policy");
- base_type::func(
- internal::meta_func_node{
- id,
- name,
- (descriptor::is_const ? internal::meta_traits::is_const : internal::meta_traits::is_none) | (descriptor::is_static ? internal::meta_traits::is_static : internal::meta_traits::is_none),
- descriptor::args_type::size,
- &internal::resolve<std::conditional_t<std::is_same_v<Policy, as_void_t>, void, std::remove_const_t<std::remove_reference_t<typename descriptor::return_type>>>>,
- &meta_arg<typename descriptor::args_type>,
- &meta_invoke<Type, Candidate, Policy>});
- return *this;
- }
- /**
- * @brief Sets traits on the last created meta object.
- *
- * The assigned value must be an enum and intended as a bitmask.
- *
- * @tparam Value Type of the traits value.
- * @param value Traits value.
- * @param unset True to unset the given traits, false otherwise.
- * @return A meta factory for the parent type.
- */
- template<typename Value>
- meta_factory traits(const Value value, const bool unset = false) {
- static_assert(std::is_enum_v<Value>, "Invalid enum type");
- base_type::traits(internal::user_to_meta_traits(value), unset);
- return *this;
- }
- /**
- * @brief Sets user defined data that will never be used by the library.
- * @tparam Value Type of user defined data to store.
- * @tparam Args Types of arguments to use to construct the user data.
- * @param args Parameters to use to initialize the user data.
- * @return A meta factory for the parent type.
- */
- template<typename Value, typename... Args>
- meta_factory custom(Args &&...args) {
- base_type::custom(internal::meta_custom_node{type_id<Value>().hash(), std::make_shared<Value>(std::forward<Args>(args)...)});
- return *this;
- }
- };
- /**
- * @brief Resets a type and all its parts.
- *
- * Resets a type and all its data members, member functions and properties, as
- * well as its constructors, destructors and conversion functions if any.<br/>
- * Base classes aren't reset but the link between the two types is removed.
- *
- * The type is also removed from the set of searchable types.
- *
- * @param id Unique identifier.
- * @param ctx The context from which to reset meta types.
- */
- inline void meta_reset(meta_ctx &ctx, const id_type id) noexcept {
- auto &context = internal::meta_context::from(ctx);
- for(auto it = context.value.begin(); it != context.value.end();) {
- if(it->second->id == id) {
- it = context.value.erase(it);
- } else {
- ++it;
- }
- }
- }
- /**
- * @brief Resets a type and all its parts.
- *
- * Resets a type and all its data members, member functions and properties, as
- * well as its constructors, destructors and conversion functions if any.<br/>
- * Base classes aren't reset but the link between the two types is removed.
- *
- * The type is also removed from the set of searchable types.
- *
- * @param id Unique identifier.
- */
- inline void meta_reset(const id_type id) noexcept {
- meta_reset(locator<meta_ctx>::value_or(), id);
- }
- /**
- * @brief Resets a type and all its parts.
- *
- * @sa meta_reset
- *
- * @tparam Type Type to reset.
- * @param ctx The context from which to reset meta types.
- */
- template<typename Type>
- void meta_reset(meta_ctx &ctx) noexcept {
- internal::meta_context::from(ctx).value.erase(type_id<Type>().hash());
- }
- /**
- * @brief Resets a type and all its parts.
- *
- * @sa meta_reset
- *
- * @tparam Type Type to reset.
- */
- template<typename Type>
- void meta_reset() noexcept {
- meta_reset<Type>(locator<meta_ctx>::value_or());
- }
- /**
- * @brief Resets all meta types.
- *
- * @sa meta_reset
- *
- * @param ctx The context from which to reset meta types.
- */
- inline void meta_reset(meta_ctx &ctx) noexcept {
- internal::meta_context::from(ctx).value.clear();
- }
- /**
- * @brief Resets all meta types.
- *
- * @sa meta_reset
- */
- inline void meta_reset() noexcept {
- meta_reset(locator<meta_ctx>::value_or());
- }
- } // namespace entt
- #endif
- // #include "meta/meta.hpp"
- #ifndef ENTT_META_META_HPP
- #define ENTT_META_META_HPP
- #include <array>
- #include <cstddef>
- #include <iterator>
- #include <memory>
- #include <type_traits>
- #include <utility>
- // #include "../config/config.h"
- // #include "../core/any.hpp"
- // #include "../core/fwd.hpp"
- // #include "../core/iterator.hpp"
- // #include "../core/type_info.hpp"
- // #include "../core/type_traits.hpp"
- // #include "../core/utility.hpp"
- // #include "../locator/locator.hpp"
- // #include "adl_pointer.hpp"
- // #include "context.hpp"
- // #include "fwd.hpp"
- // #include "node.hpp"
- // #include "range.hpp"
- // #include "type_traits.hpp"
- namespace entt {
- class meta_any;
- class meta_type;
- /*! @brief Proxy object for sequence containers. */
- class meta_sequence_container {
- class meta_iterator;
- public:
- /*! @brief Unsigned integer type. */
- using size_type = std::size_t;
- /*! @brief Meta iterator type. */
- using iterator = meta_iterator;
- /*! @brief Default constructor. */
- meta_sequence_container() = default;
- /**
- * @brief Context aware constructor.
- * @tparam Type Type of container to wrap.
- * @param area The context from which to search for meta types.
- * @param instance The container to wrap.
- */
- template<typename Type>
- meta_sequence_container(const meta_ctx &area, Type &instance) noexcept
- : ctx{&area},
- data{&instance},
- value_type_node{&internal::resolve<typename Type::value_type>},
- const_reference_node{&internal::resolve<std::remove_const_t<std::remove_reference_t<typename Type::const_reference>>>},
- size_fn{meta_sequence_container_traits<std::remove_const_t<Type>>::size},
- clear_fn{meta_sequence_container_traits<std::remove_const_t<Type>>::clear},
- reserve_fn{meta_sequence_container_traits<std::remove_const_t<Type>>::reserve},
- resize_fn{meta_sequence_container_traits<std::remove_const_t<Type>>::resize},
- begin_end_fn{meta_sequence_container_traits<std::remove_const_t<Type>>::iter},
- insert_fn{meta_sequence_container_traits<std::remove_const_t<Type>>::insert},
- erase_fn{meta_sequence_container_traits<std::remove_const_t<Type>>::erase},
- const_only{std::is_const_v<Type>} {}
- [[nodiscard]] inline meta_type value_type() const noexcept;
- [[nodiscard]] inline size_type size() const noexcept;
- inline bool resize(size_type);
- inline bool clear();
- inline bool reserve(size_type);
- [[nodiscard]] inline iterator begin();
- [[nodiscard]] inline iterator end();
- inline iterator insert(const iterator &, meta_any);
- inline iterator erase(const iterator &);
- [[nodiscard]] inline meta_any operator[](size_type);
- [[nodiscard]] inline explicit operator bool() const noexcept;
- private:
- const meta_ctx *ctx{};
- const void *data{};
- const internal::meta_type_node &(*value_type_node)(const internal::meta_context &){};
- const internal::meta_type_node &(*const_reference_node)(const internal::meta_context &){};
- size_type (*size_fn)(const void *){};
- bool (*clear_fn)(void *){};
- bool (*reserve_fn)(void *, const size_type){};
- bool (*resize_fn)(void *, const size_type){};
- iterator (*begin_end_fn)(const meta_ctx &, void *, const void *, const bool){};
- iterator (*insert_fn)(const meta_ctx &, void *, const void *, const void *, const iterator &){};
- iterator (*erase_fn)(const meta_ctx &, void *, const iterator &){};
- bool const_only{};
- };
- /*! @brief Proxy object for associative containers. */
- class meta_associative_container {
- class meta_iterator;
- public:
- /*! @brief Unsigned integer type. */
- using size_type = std::size_t;
- /*! @brief Meta iterator type. */
- using iterator = meta_iterator;
- /*! @brief Default constructor. */
- meta_associative_container() = default;
- /**
- * @brief Context aware constructor.
- * @tparam Type Type of container to wrap.
- * @param area The context from which to search for meta types.
- * @param instance The container to wrap.
- */
- template<typename Type>
- meta_associative_container(const meta_ctx &area, Type &instance) noexcept
- : ctx{&area},
- data{&instance},
- key_type_node{&internal::resolve<typename Type::key_type>},
- value_type_node{&internal::resolve<typename Type::value_type>},
- size_fn{&meta_associative_container_traits<std::remove_const_t<Type>>::size},
- clear_fn{&meta_associative_container_traits<std::remove_const_t<Type>>::clear},
- reserve_fn{&meta_associative_container_traits<std::remove_const_t<Type>>::reserve},
- begin_end_fn{&meta_associative_container_traits<std::remove_const_t<Type>>::iter},
- insert_fn{&meta_associative_container_traits<std::remove_const_t<Type>>::insert},
- erase_fn{&meta_associative_container_traits<std::remove_const_t<Type>>::erase},
- find_fn{&meta_associative_container_traits<std::remove_const_t<Type>>::find},
- const_only{std::is_const_v<Type>} {
- if constexpr(!meta_associative_container_traits<std::remove_const_t<Type>>::key_only) {
- mapped_type_node = &internal::resolve<typename Type::mapped_type>;
- }
- }
- [[nodiscard]] inline meta_type key_type() const noexcept;
- [[nodiscard]] inline meta_type mapped_type() const noexcept;
- [[nodiscard]] inline meta_type value_type() const noexcept;
- [[nodiscard]] inline size_type size() const noexcept;
- inline bool clear();
- inline bool reserve(size_type);
- [[nodiscard]] inline iterator begin();
- [[nodiscard]] inline iterator end();
- inline bool insert(meta_any, meta_any);
- inline size_type erase(meta_any);
- [[nodiscard]] inline iterator find(meta_any);
- [[nodiscard]] inline explicit operator bool() const noexcept;
- private:
- const meta_ctx *ctx{};
- const void *data{};
- const internal::meta_type_node &(*key_type_node)(const internal::meta_context &){};
- const internal::meta_type_node &(*mapped_type_node)(const internal::meta_context &){};
- const internal::meta_type_node &(*value_type_node)(const internal::meta_context &){};
- size_type (*size_fn)(const void *){};
- bool (*clear_fn)(void *){};
- bool (*reserve_fn)(void *, const size_type){};
- iterator (*begin_end_fn)(const meta_ctx &, void *, const void *, const bool){};
- bool (*insert_fn)(void *, const void *, const void *){};
- size_type (*erase_fn)(void *, const void *){};
- iterator (*find_fn)(const meta_ctx &, void *, const void *, const void *){};
- bool const_only{};
- };
- /*! @brief Opaque wrapper for values of any type. */
- class meta_any {
- using vtable_type = void(const internal::meta_traits, const meta_any &, const void *);
- template<typename Type>
- static void basic_vtable(const internal::meta_traits req, const meta_any &value, [[maybe_unused]] const void *other) {
- static_assert(std::is_same_v<std::remove_const_t<std::remove_reference_t<Type>>, Type>, "Invalid type");
- if(req == internal::meta_traits::is_none) {
- value.node = &internal::resolve<Type>(internal::meta_context::from(*value.ctx));
- }
- if constexpr(is_meta_pointer_like_v<Type>) {
- if(req == internal::meta_traits::is_pointer_like) {
- if constexpr(std::is_function_v<typename std::pointer_traits<Type>::element_type>) {
- const_cast<meta_any &>(value).emplace<Type>(*static_cast<const Type *>(other));
- } else if constexpr(!std::is_void_v<std::remove_const_t<typename std::pointer_traits<Type>::element_type>>) {
- using in_place_type = decltype(adl_meta_pointer_like<Type>::dereference(std::declval<const Type &>()));
- if constexpr(std::is_constructible_v<bool, Type>) {
- if(const auto &pointer_like = *static_cast<const Type *>(other); pointer_like) {
- const_cast<meta_any &>(value).emplace<in_place_type>(adl_meta_pointer_like<Type>::dereference(pointer_like));
- }
- } else {
- const_cast<meta_any &>(value).emplace<in_place_type>(adl_meta_pointer_like<Type>::dereference(*static_cast<const Type *>(other)));
- }
- }
- }
- }
- if constexpr(is_complete_v<meta_sequence_container_traits<Type>> || is_complete_v<meta_associative_container_traits<Type>>) {
- if(constexpr auto flag = (is_complete_v<meta_sequence_container_traits<Type>> ? internal::meta_traits::is_sequence_container : internal::meta_traits::is_associative_container); !!(req & flag)) {
- using container_type = std::conditional_t<is_complete_v<meta_sequence_container_traits<Type>>, meta_sequence_container, meta_associative_container>;
- if(!!(req & internal::meta_traits::is_const) || (value.storage.policy() == any_policy::cref)) {
- // NOLINTNEXTLINE(bugprone-casting-through-void)
- *static_cast<container_type *>(const_cast<void *>(other)) = container_type{*value.ctx, any_cast<const Type &>(value.storage)};
- } else {
- // NOLINTNEXTLINE(bugprone-casting-through-void)
- *static_cast<container_type *>(const_cast<void *>(other)) = container_type{*value.ctx, any_cast<Type &>(const_cast<meta_any &>(value).storage)};
- }
- }
- }
- }
- [[nodiscard]] const auto &fetch_node() const {
- if(node == nullptr) {
- ENTT_ASSERT(*this, "Invalid vtable function");
- vtable(internal::meta_traits::is_none, *this, nullptr);
- }
- ENTT_ASSERT(node != nullptr, "Invalid pointer to node");
- return *node;
- }
- meta_any(const meta_any &other, any elem)
- : storage{std::move(elem)},
- ctx{other.ctx},
- node{other.node},
- vtable{other.vtable} {}
- public:
- /*! Default constructor. */
- meta_any() = default;
- /**
- * @brief Context aware constructor.
- * @param area The context from which to search for meta types.
- */
- meta_any(meta_ctx_arg_t, const meta_ctx &area)
- : ctx{&area} {}
- /**
- * @brief Constructs a wrapper by directly initializing the new object.
- * @tparam Type Type of object to use to initialize the wrapper.
- * @tparam Args Types of arguments to use to construct the new instance.
- * @param args Parameters to use to construct the instance.
- */
- template<typename Type, typename... Args>
- explicit meta_any(std::in_place_type_t<Type>, Args &&...args)
- : meta_any{locator<meta_ctx>::value_or(), std::in_place_type<Type>, std::forward<Args>(args)...} {}
- /**
- * @brief Constructs a wrapper by directly initializing the new object.
- * @tparam Type Type of object to use to initialize the wrapper.
- * @tparam Args Types of arguments to use to construct the new instance.
- * @param area The context from which to search for meta types.
- * @param args Parameters to use to construct the instance.
- */
- template<typename Type, typename... Args>
- explicit meta_any(const meta_ctx &area, std::in_place_type_t<Type>, Args &&...args)
- : storage{std::in_place_type<Type>, std::forward<Args>(args)...},
- ctx{&area},
- vtable{&basic_vtable<std::remove_const_t<std::remove_reference_t<Type>>>} {}
- /**
- * @brief Constructs a wrapper taking ownership of the passed object.
- * @tparam Type Type of object to use to initialize the wrapper.
- * @param value A pointer to an object to take ownership of.
- */
- template<typename Type>
- explicit meta_any(std::in_place_t, Type *value)
- : meta_any{locator<meta_ctx>::value_or(), std::in_place, value} {}
- /**
- * @brief Constructs a wrapper taking ownership of the passed object.
- * @tparam Type Type of object to use to initialize the wrapper.
- * @param area The context from which to search for meta types.
- * @param value A pointer to an object to take ownership of.
- */
- template<typename Type>
- explicit meta_any(const meta_ctx &area, std::in_place_t, Type *value)
- : storage{std::in_place, value},
- ctx{&area},
- vtable{storage ? &basic_vtable<Type> : nullptr} {
- }
- /**
- * @brief Constructs a wrapper from a given value.
- * @tparam Type Type of object to use to initialize the wrapper.
- * @param value An instance of an object to use to initialize the wrapper.
- */
- template<typename Type, typename = std::enable_if_t<!std::is_same_v<std::decay_t<Type>, meta_any>>>
- meta_any(Type &&value)
- : meta_any{locator<meta_ctx>::value_or(), std::forward<Type>(value)} {}
- /**
- * @brief Constructs a wrapper from a given value.
- * @tparam Type Type of object to use to initialize the wrapper.
- * @param area The context from which to search for meta types.
- * @param value An instance of an object to use to initialize the wrapper.
- */
- template<typename Type, typename = std::enable_if_t<!std::is_same_v<std::decay_t<Type>, meta_any>>>
- meta_any(const meta_ctx &area, Type &&value)
- : meta_any{area, std::in_place_type<std::decay_t<Type>>, std::forward<Type>(value)} {}
- /**
- * @brief Context aware copy constructor.
- * @param area The context from which to search for meta types.
- * @param other The instance to copy from.
- */
- meta_any(const meta_ctx &area, const meta_any &other)
- : storage{other.storage},
- ctx{&area},
- node{(ctx == other.ctx) ? other.node : nullptr},
- vtable{other.vtable} {}
- /**
- * @brief Context aware move constructor.
- * @param area The context from which to search for meta types.
- * @param other The instance to move from.
- */
- meta_any(const meta_ctx &area, meta_any &&other)
- : storage{std::move(other.storage)},
- ctx{&area},
- node{(ctx == other.ctx) ? std::exchange(other.node, nullptr) : nullptr},
- vtable{std::exchange(other.vtable, nullptr)} {}
- /**
- * @brief Copy constructor.
- * @param other The instance to copy from.
- */
- meta_any(const meta_any &other) = default;
- /**
- * @brief Move constructor.
- * @param other The instance to move from.
- */
- meta_any(meta_any &&other) noexcept
- : storage{std::move(other.storage)},
- ctx{other.ctx},
- node{std::exchange(other.node, nullptr)},
- vtable{std::exchange(other.vtable, nullptr)} {}
- /*! @brief Default destructor. */
- ~meta_any() = default;
- /**
- * @brief Copy assignment operator.
- * @param other The instance to copy from.
- * @return This meta any object.
- */
- meta_any &operator=(const meta_any &other) {
- if(this != &other) {
- storage = other.storage;
- ctx = other.ctx;
- node = other.node;
- vtable = other.vtable;
- }
- return *this;
- }
- /**
- * @brief Move assignment operator.
- * @param other The instance to move from.
- * @return This meta any object.
- */
- meta_any &operator=(meta_any &&other) noexcept {
- storage = std::move(other.storage);
- ctx = other.ctx;
- node = std::exchange(other.node, nullptr);
- vtable = std::exchange(other.vtable, nullptr);
- return *this;
- }
- /**
- * @brief Value assignment operator.
- * @tparam Type Type of object to use to initialize the wrapper.
- * @param value An instance of an object to use to initialize the wrapper.
- * @return This meta any object.
- */
- template<typename Type, typename = std::enable_if_t<!std::is_same_v<std::decay_t<Type>, meta_any>>>
- meta_any &operator=(Type &&value) {
- emplace<std::decay_t<Type>>(std::forward<Type>(value));
- return *this;
- }
- /*! @copydoc any::info */
- [[nodiscard]] inline meta_type type() const noexcept;
- /**
- * @brief Invokes the underlying function, if possible.
- * @tparam Args Types of arguments to use to invoke the function.
- * @param id Unique identifier.
- * @param args Parameters to use to invoke the function.
- * @return A wrapper containing the returned value, if any.
- */
- template<typename... Args>
- meta_any invoke(id_type id, Args &&...args) const;
- /*! @copydoc invoke */
- template<typename... Args>
- meta_any invoke(id_type id, Args &&...args);
- /**
- * @brief Sets the value of a given variable.
- * @tparam Type Type of value to assign.
- * @param id Unique identifier.
- * @param value Parameter to use to set the underlying variable.
- * @return True in case of success, false otherwise.
- */
- template<typename Type>
- bool set(id_type id, Type &&value);
- /**
- * @brief Gets the value of a given variable.
- * @param id Unique identifier.
- * @return A wrapper containing the value of the underlying variable.
- */
- [[nodiscard]] meta_any get(id_type id) const;
- /*! @copydoc get */
- [[nodiscard]] meta_any get(id_type id);
- /**
- * @brief Tries to cast an instance to a given type.
- * @tparam Type Type to which to cast the instance.
- * @return A (possibly null) pointer to the contained instance.
- */
- template<typename Type>
- [[nodiscard]] const Type *try_cast() const {
- const auto *elem = any_cast<const Type>(&storage);
- return ((elem != nullptr) || !*this) ? elem : static_cast<const Type *>(internal::try_cast(internal::meta_context::from(*ctx), fetch_node(), type_hash<std::remove_const_t<Type>>::value(), storage.data()));
- }
- /*! @copydoc try_cast */
- template<typename Type>
- [[nodiscard]] Type *try_cast() {
- return ((storage.policy() == any_policy::cref) && !std::is_const_v<Type>) ? nullptr : const_cast<Type *>(std::as_const(*this).try_cast<std::remove_const_t<Type>>());
- }
- /**
- * @brief Tries to cast an instance to a given type.
- * @tparam Type Type to which to cast the instance.
- * @return A reference to the contained instance.
- */
- template<typename Type>
- [[nodiscard]] std::remove_const_t<Type> cast() const {
- auto *const instance = try_cast<std::remove_reference_t<Type>>();
- ENTT_ASSERT(instance, "Invalid instance");
- return static_cast<Type>(*instance);
- }
- /*! @copydoc cast */
- template<typename Type>
- [[nodiscard]] std::remove_const_t<Type> cast() {
- // forces const on non-reference types to make them work also with wrappers for const references
- auto *const instance = try_cast<std::remove_reference_t<const Type>>();
- ENTT_ASSERT(instance, "Invalid instance");
- return static_cast<Type>(*instance);
- }
- /**
- * @brief Converts an object in such a way that a given cast becomes viable.
- * @param type Meta type to which the cast is requested.
- * @return A valid meta object if convertible, an invalid one otherwise.
- */
- [[nodiscard]] meta_any allow_cast(const meta_type &type) const;
- /**
- * @brief Converts an object in such a way that a given cast becomes viable.
- * @param type Meta type to which the cast is requested.
- * @return True if convertible, false otherwise.
- */
- [[nodiscard]] bool allow_cast(const meta_type &type);
- /**
- * @brief Converts an object in such a way that a given cast becomes viable.
- * @tparam Type Type to which the cast is requested.
- * @return A valid meta object if convertible, an invalid one otherwise.
- */
- template<typename Type>
- [[nodiscard]] meta_any allow_cast() const {
- if constexpr(!std::is_reference_v<Type> || std::is_const_v<std::remove_reference_t<Type>>) {
- if(storage.has_value<std::remove_const_t<std::remove_reference_t<Type>>>()) {
- return as_ref();
- } else if(*this) {
- if constexpr(std::is_arithmetic_v<std::remove_const_t<std::remove_reference_t<Type>>> || std::is_enum_v<std::remove_const_t<std::remove_reference_t<Type>>>) {
- if(const auto &from = fetch_node(); from.conversion_helper) {
- return meta_any{*ctx, static_cast<Type>(from.conversion_helper(nullptr, storage.data()))};
- }
- }
- if(const auto &from = fetch_node(); from.details != nullptr) {
- if(const auto *elem = internal::find_member<&internal::meta_conv_node::type>(from.details->conv, entt::type_hash<std::remove_const_t<std::remove_reference_t<Type>>>::value()); elem != nullptr) {
- return elem->conv(*ctx, storage.data());
- }
- for(auto &&curr: from.details->base) {
- if(auto other = curr.resolve(internal::meta_context::from(*ctx)).from_void(*ctx, nullptr, curr.cast(storage.data())); curr.type == entt::type_hash<std::remove_const_t<std::remove_reference_t<Type>>>::value()) {
- return other;
- } else if(auto from_base = std::as_const(other).template allow_cast<Type>(); from_base) {
- return from_base;
- }
- }
- }
- }
- }
- return meta_any{meta_ctx_arg, *ctx};
- }
- /**
- * @brief Converts an object in such a way that a given cast becomes viable.
- * @tparam Type Type to which the cast is requested.
- * @return True if convertible, false otherwise.
- */
- template<typename Type>
- [[nodiscard]] bool allow_cast() {
- if constexpr(std::is_reference_v<Type> && !std::is_const_v<std::remove_reference_t<Type>>) {
- return allow_cast<const std::remove_reference_t<Type> &>() && (storage.policy() != any_policy::cref);
- } else {
- if(storage.has_value<std::remove_const_t<std::remove_reference_t<Type>>>()) {
- return true;
- } else if(auto other = std::as_const(*this).allow_cast<std::remove_const_t<std::remove_reference_t<Type>>>(); other) {
- if(other.storage.owner()) {
- std::swap(*this, other);
- }
- return true;
- }
- return false;
- }
- }
- /*! @copydoc any::emplace */
- template<typename Type, typename... Args>
- void emplace(Args &&...args) {
- storage.emplace<Type>(std::forward<Args>(args)...);
- auto *prev = std::exchange(vtable, &basic_vtable<std::remove_const_t<std::remove_reference_t<Type>>>);
- node = (prev == vtable) ? node : nullptr;
- }
- /*! @copydoc any::assign */
- bool assign(const meta_any &other);
- /*! @copydoc any::assign */
- bool assign(meta_any &&other);
- /*! @copydoc any::reset */
- void reset() {
- storage.reset();
- node = nullptr;
- vtable = nullptr;
- }
- /**
- * @brief Returns a sequence container proxy.
- * @return A sequence container proxy for the underlying object.
- */
- [[nodiscard]] meta_sequence_container as_sequence_container() noexcept {
- meta_sequence_container proxy{};
- if(*this) { vtable(internal::meta_traits::is_sequence_container, *this, &proxy); }
- return proxy;
- }
- /*! @copydoc as_sequence_container */
- [[nodiscard]] meta_sequence_container as_sequence_container() const noexcept {
- meta_sequence_container proxy{};
- if(*this) { vtable(internal::meta_traits::is_sequence_container | internal::meta_traits::is_const, *this, &proxy); }
- return proxy;
- }
- /**
- * @brief Returns an associative container proxy.
- * @return An associative container proxy for the underlying object.
- */
- [[nodiscard]] meta_associative_container as_associative_container() noexcept {
- meta_associative_container proxy{};
- if(*this) { vtable(internal::meta_traits::is_associative_container, *this, &proxy); }
- return proxy;
- }
- /*! @copydoc as_associative_container */
- [[nodiscard]] meta_associative_container as_associative_container() const noexcept {
- meta_associative_container proxy{};
- if(*this) { vtable(internal::meta_traits::is_associative_container | internal::meta_traits::is_const, *this, &proxy); }
- return proxy;
- }
- /**
- * @brief Indirection operator for dereferencing opaque objects.
- * @return A wrapper that shares a reference to an unmanaged object if the
- * wrapped element is dereferenceable, an invalid meta any otherwise.
- */
- [[nodiscard]] meta_any operator*() const noexcept {
- meta_any ret{meta_ctx_arg, *ctx};
- if(*this) { vtable(internal::meta_traits::is_pointer_like, ret, storage.data()); }
- return ret;
- }
- /*! @copydoc any::operator bool */
- [[nodiscard]] explicit operator bool() const noexcept {
- return !(vtable == nullptr);
- }
- /*! @copydoc any::operator== */
- [[nodiscard]] bool operator==(const meta_any &other) const noexcept {
- return (ctx == other.ctx) && (!*this == !other) && (storage == other.storage);
- }
- /*! @copydoc any::operator!= */
- [[nodiscard]] bool operator!=(const meta_any &other) const noexcept {
- return !(*this == other);
- }
- /*! @copydoc any::as_ref */
- [[nodiscard]] meta_any as_ref() noexcept {
- return meta_any{*this, storage.as_ref()};
- }
- /*! @copydoc any::as_ref */
- [[nodiscard]] meta_any as_ref() const noexcept {
- return meta_any{*this, storage.as_ref()};
- }
- /**
- * @brief Returns the underlying storage.
- * @return The underlyig storage.
- */
- [[nodiscard]] const any &base() const noexcept {
- return storage;
- }
- /**
- * @brief Returns the underlying meta context.
- * @return The underlying meta context.
- */
- [[nodiscard]] const meta_ctx &context() const noexcept {
- return *ctx;
- }
- private:
- any storage{};
- const meta_ctx *ctx{&locator<meta_ctx>::value_or()};
- mutable const internal::meta_type_node *node{};
- vtable_type *vtable{};
- };
- /**
- * @brief Forwards its argument and avoids copies for lvalue references.
- * @tparam Type Type of argument to use to construct the new instance.
- * @param value Parameter to use to construct the instance.
- * @param ctx The context from which to search for meta types.
- * @return A properly initialized and not necessarily owning wrapper.
- */
- template<typename Type>
- [[nodiscard]] meta_any forward_as_meta(const meta_ctx &ctx, Type &&value) {
- return meta_any{ctx, std::in_place_type<Type &&>, std::forward<Type>(value)};
- }
- /**
- * @brief Forwards its argument and avoids copies for lvalue references.
- * @tparam Type Type of argument to use to construct the new instance.
- * @param value Parameter to use to construct the instance.
- * @return A properly initialized and not necessarily owning wrapper.
- */
- template<typename Type>
- [[nodiscard]] meta_any forward_as_meta(Type &&value) {
- return forward_as_meta(locator<meta_ctx>::value_or(), std::forward<Type>(value));
- }
- /*! @brief Opaque pointers to instances of any type. */
- class meta_handle {
- template<typename Type, typename... Args, typename = std::enable_if_t<std::is_same_v<std::decay_t<Type>, meta_any>>>
- meta_handle(int, Type &value, Args &&...args)
- : any{std::forward<Args>(args)..., value.as_ref()} {}
- template<typename Type, typename... Args>
- meta_handle(char, Type &value, Args &&...args)
- : any{std::forward<Args>(args)..., std::in_place_type<Type &>, value} {}
- public:
- /*! Default constructor. */
- meta_handle() = default;
- /**
- * @brief Creates a handle that points to an unmanaged object.
- * @tparam Type Type of object to use to initialize the handle.
- * @param ctx The context from which to search for meta types.
- * @param value An instance of an object to use to initialize the handle.
- */
- template<typename Type, typename = std::enable_if_t<!std::is_same_v<std::decay_t<Type>, meta_handle>>>
- meta_handle(const meta_ctx &ctx, Type &value)
- : meta_handle{0, value, ctx} {}
- /**
- * @brief Creates a handle that points to an unmanaged object.
- * @tparam Type Type of object to use to initialize the handle.
- * @param value An instance of an object to use to initialize the handle.
- */
- template<typename Type, typename = std::enable_if_t<!std::is_same_v<std::decay_t<Type>, meta_handle>>>
- meta_handle(Type &value)
- : meta_handle{0, value} {}
- /**
- * @brief Context aware move constructor.
- * @param area The context from which to search for meta types.
- * @param other The instance to move from.
- */
- meta_handle(const meta_ctx &area, meta_handle &&other)
- : any{area, std::move(other.any)} {}
- /*! @brief Default copy constructor, deleted on purpose. */
- meta_handle(const meta_handle &) = delete;
- /*! @brief Default move constructor. */
- meta_handle(meta_handle &&) = default;
- /*! @brief Default destructor. */
- ~meta_handle() = default;
- /**
- * @brief Default copy assignment operator, deleted on purpose.
- * @return This meta handle.
- */
- meta_handle &operator=(const meta_handle &) = delete;
- /**
- * @brief Default move assignment operator.
- * @return This meta handle.
- */
- meta_handle &operator=(meta_handle &&) = default;
- /**
- * @brief Returns false if a handle is invalid, true otherwise.
- * @return False if the handle is invalid, true otherwise.
- */
- [[nodiscard]] explicit operator bool() const noexcept {
- return static_cast<bool>(any);
- }
- /**
- * @brief Access operator for accessing the contained opaque object.
- * @return A wrapper that shares a reference to an unmanaged object.
- */
- [[nodiscard]] meta_any *operator->() {
- return &any;
- }
- /*! @copydoc operator-> */
- [[deprecated("do not use const handles")]] [[nodiscard]] const meta_any *operator->() const {
- return &any;
- }
- private:
- meta_any any{};
- };
- /*! @brief Opaque wrapper for user defined data of any type. */
- struct meta_custom {
- /*! @brief Default constructor. */
- meta_custom() noexcept = default;
- /**
- * @brief Basic constructor for meta objects.
- * @param curr The underlying node with which to construct the instance.
- */
- meta_custom(const internal::meta_custom_node &curr) noexcept
- : node{&curr} {}
- /**
- * @brief Generic conversion operator.
- * @tparam Type Type to which conversion is requested.
- */
- template<typename Type>
- [[nodiscard]] operator Type *() const noexcept {
- return ((node != nullptr) && (type_hash<std::remove_const_t<Type>>::value() == node->type)) ? static_cast<Type *>(node->value.get()) : nullptr;
- }
- /**
- * @brief Generic conversion operator.
- * @tparam Type Type to which conversion is requested.
- */
- template<typename Type>
- [[nodiscard]] operator Type &() const noexcept {
- ENTT_ASSERT(static_cast<Type *>(*this) != nullptr, "Invalid type");
- return *static_cast<Type *>(node->value.get());
- }
- private:
- const internal::meta_custom_node *node{};
- };
- /*! @brief Opaque wrapper for data members. */
- class meta_data {
- [[nodiscard]] auto &node_or_assert() const noexcept {
- ENTT_ASSERT(node != nullptr, "Invalid pointer to node");
- return *node;
- }
- public:
- /*! @brief Unsigned integer type. */
- using size_type = typename internal::meta_data_node::size_type;
- /*! @brief Default constructor. */
- meta_data() noexcept = default;
- /**
- * @brief Context aware constructor for meta objects.
- * @param area The context from which to search for meta types.
- * @param curr The underlying node with which to construct the instance.
- */
- meta_data(const meta_ctx &area, const internal::meta_data_node &curr) noexcept
- : node{&curr},
- ctx{&area} {}
- /**
- * @brief Returns the name assigned to a data member, if any.
- * @return The name assigned to the data member, if any.
- */
- [[nodiscard]] const char *name() const noexcept {
- return node_or_assert().name;
- }
- /**
- * @brief Returns the number of setters available.
- * @return The number of setters available.
- */
- [[nodiscard]] size_type arity() const noexcept {
- return node_or_assert().arity;
- }
- /**
- * @brief Indicates whether a data member is constant or not.
- * @return True if the data member is constant, false otherwise.
- */
- [[nodiscard]] bool is_const() const noexcept {
- return !!(node_or_assert().traits & internal::meta_traits::is_const);
- }
- /**
- * @brief Indicates whether a data member is static or not.
- * @return True if the data member is static, false otherwise.
- */
- [[nodiscard]] bool is_static() const noexcept {
- return !!(node_or_assert().traits & internal::meta_traits::is_static);
- }
- /*! @copydoc meta_any::type */
- [[nodiscard]] inline meta_type type() const noexcept;
- /**
- * @brief Sets the value of a given variable.
- * @tparam Instance Type of instance to operate on.
- * @tparam Type Type of value to assign.
- * @param instance An instance that fits the underlying type.
- * @param value Parameter to use to set the underlying variable.
- * @return True in case of success, false otherwise.
- */
- template<typename Instance = meta_handle, typename Type>
- // NOLINTNEXTLINE(modernize-use-nodiscard)
- bool set(Instance &&instance, Type &&value) const {
- return node_or_assert().set(meta_handle{*ctx, std::forward<Instance>(instance)}, meta_any{*ctx, std::forward<Type>(value)});
- }
- /**
- * @brief Gets the value of a given variable.
- * @tparam Instance Type of instance to operate on.
- * @param instance An instance that fits the underlying type.
- * @return A wrapper containing the value of the underlying variable.
- */
- template<typename Instance = meta_handle>
- [[nodiscard]] meta_any get(Instance &&instance) const {
- return node_or_assert().get(meta_handle{*ctx, std::forward<Instance>(instance)});
- }
- /**
- * @brief Returns the type accepted by the i-th setter.
- * @param index Index of the setter of which to return the accepted type.
- * @return The type accepted by the i-th setter.
- */
- [[nodiscard]] inline meta_type arg(size_type index) const noexcept;
- /**
- * @brief Returns all meta traits for a given meta object.
- * @tparam Type The type to convert the meta traits to.
- * @return The registered meta traits, if any.
- */
- template<typename Type>
- [[nodiscard]] Type traits() const noexcept {
- return internal::meta_to_user_traits<Type>(node_or_assert().traits);
- }
- /**
- * @brief Returns user defined data for a given meta object.
- * @return User defined arbitrary data.
- */
- [[nodiscard]] meta_custom custom() const noexcept {
- return {node_or_assert().custom};
- }
- /**
- * @brief Returns true if an object is valid, false otherwise.
- * @return True if the object is valid, false otherwise.
- */
- [[nodiscard]] explicit operator bool() const noexcept {
- return (node != nullptr);
- }
- /**
- * @brief Checks if two objects refer to the same type.
- * @param other The object with which to compare.
- * @return True if the objects refer to the same type, false otherwise.
- */
- [[nodiscard]] bool operator==(const meta_data &other) const noexcept {
- return (ctx == other.ctx) && (node == other.node);
- }
- private:
- const internal::meta_data_node *node{};
- const meta_ctx *ctx{&locator<meta_ctx>::value_or()};
- };
- /**
- * @brief Checks if two objects refer to the same type.
- * @param lhs An object, either valid or not.
- * @param rhs An object, either valid or not.
- * @return False if the objects refer to the same node, true otherwise.
- */
- [[nodiscard]] inline bool operator!=(const meta_data &lhs, const meta_data &rhs) noexcept {
- return !(lhs == rhs);
- }
- /*! @brief Opaque wrapper for member functions. */
- class meta_func {
- [[nodiscard]] auto &node_or_assert() const noexcept {
- ENTT_ASSERT(node != nullptr, "Invalid pointer to node");
- return *node;
- }
- public:
- /*! @brief Unsigned integer type. */
- using size_type = typename internal::meta_func_node::size_type;
- /*! @brief Default constructor. */
- meta_func() noexcept = default;
- /**
- * @brief Context aware constructor for meta objects.
- * @param area The context from which to search for meta types.
- * @param curr The underlying node with which to construct the instance.
- */
- meta_func(const meta_ctx &area, const internal::meta_func_node &curr) noexcept
- : node{&curr},
- ctx{&area} {}
- /**
- * @brief Returns the name assigned to a member function, if any.
- * @return The name assigned to the member function, if any.
- */
- [[nodiscard]] const char *name() const noexcept {
- return node_or_assert().name;
- }
- /**
- * @brief Returns the number of arguments accepted by a member function.
- * @return The number of arguments accepted by the member function.
- */
- [[nodiscard]] size_type arity() const noexcept {
- return node_or_assert().arity;
- }
- /**
- * @brief Indicates whether a member function is constant or not.
- * @return True if the member function is constant, false otherwise.
- */
- [[nodiscard]] bool is_const() const noexcept {
- return !!(node_or_assert().traits & internal::meta_traits::is_const);
- }
- /**
- * @brief Indicates whether a member function is static or not.
- * @return True if the member function is static, false otherwise.
- */
- [[nodiscard]] bool is_static() const noexcept {
- return !!(node_or_assert().traits & internal::meta_traits::is_static);
- }
- /**
- * @brief Returns the return type of a member function.
- * @return The return type of the member function.
- */
- [[nodiscard]] inline meta_type ret() const noexcept;
- /**
- * @brief Returns the type of the i-th argument of a member function.
- * @param index Index of the argument of which to return the type.
- * @return The type of the i-th argument of a member function.
- */
- [[nodiscard]] inline meta_type arg(size_type index) const noexcept;
- /**
- * @brief Invokes the underlying function, if possible.
- * @tparam Instance Type of instance to operate on.
- * @param instance An instance that fits the underlying type.
- * @param args Parameters to use to invoke the function.
- * @param sz Number of parameters to use to invoke the function.
- * @return A wrapper containing the returned value, if any.
- */
- template<typename Instance = meta_handle>
- meta_any invoke(Instance &&instance, meta_any *const args, const size_type sz) const {
- return (sz == arity()) ? node_or_assert().invoke(meta_handle{*ctx, std::forward<Instance>(instance)}, args) : meta_any{meta_ctx_arg, *ctx};
- }
- /**
- * @copybrief invoke
- * @tparam Instance Type of instance to operate on.
- * @tparam Args Types of arguments to use to invoke the function.
- * @param instance An instance that fits the underlying type.
- * @param args Parameters to use to invoke the function.
- * @return A wrapper containing the returned value, if any.
- */
- template<typename Instance = meta_handle, typename... Args>
- // NOLINTNEXTLINE(modernize-use-nodiscard)
- meta_any invoke(Instance &&instance, Args &&...args) const {
- return invoke(std::forward<Instance>(instance), std::array<meta_any, sizeof...(Args)>{meta_any{*ctx, std::forward<Args>(args)}...}.data(), sizeof...(Args));
- }
- /*! @copydoc meta_data::traits */
- template<typename Type>
- [[nodiscard]] Type traits() const noexcept {
- return internal::meta_to_user_traits<Type>(node_or_assert().traits);
- }
- /*! @copydoc meta_data::custom */
- [[nodiscard]] meta_custom custom() const noexcept {
- return {node_or_assert().custom};
- }
- /**
- * @brief Returns the next overload of a given function, if any.
- * @return The next overload of the given function, if any.
- */
- [[nodiscard]] meta_func next() const {
- return (node_or_assert().next != nullptr) ? meta_func{*ctx, *node_or_assert().next} : meta_func{};
- }
- /*! @copydoc meta_data::operator bool */
- [[nodiscard]] explicit operator bool() const noexcept {
- return (node != nullptr);
- }
- /*! @copydoc meta_data::operator== */
- [[nodiscard]] bool operator==(const meta_func &other) const noexcept {
- return (ctx == other.ctx) && (node == other.node);
- }
- private:
- const internal::meta_func_node *node{};
- const meta_ctx *ctx{&locator<meta_ctx>::value_or()};
- };
- /*! @copydoc operator!=(const meta_data &, const meta_data &) */
- [[nodiscard]] inline bool operator!=(const meta_func &lhs, const meta_func &rhs) noexcept {
- return !(lhs == rhs);
- }
- /*! @brief Opaque wrapper for types. */
- class meta_type {
- [[nodiscard]] const auto &fetch_node() const {
- return (node == nullptr) ? internal::resolve<void>(internal::meta_context::from(*ctx)) : *node;
- }
- template<typename Func>
- [[nodiscard]] auto lookup(meta_any *const args, const typename internal::meta_type_node::size_type sz, [[maybe_unused]] bool constness, Func next) const {
- decltype(next()) candidate = nullptr;
- size_type same{};
- bool ambiguous{};
- for(auto curr = next(); curr; curr = next()) {
- if constexpr(std::is_same_v<std::decay_t<decltype(*curr)>, internal::meta_func_node>) {
- if(constness && !(curr->traits & internal::meta_traits::is_const)) {
- continue;
- }
- }
- if(curr->arity == sz) {
- size_type match{};
- size_type pos{};
- // NOLINTBEGIN(cppcoreguidelines-pro-bounds-pointer-arithmetic) - waiting for C++20 (and std::span)
- for(; pos < sz && args[pos]; ++pos) {
- const auto other = curr->arg(*ctx, pos);
- const auto type = args[pos].type();
- if(const auto &info = other.info(); info == type.info()) {
- ++match;
- } else if(!(type.fetch_node().conversion_helper && other.fetch_node().conversion_helper) && !(type.fetch_node().details && (internal::find_member<&internal::meta_base_node::type>(type.fetch_node().details->base, info.hash()) || internal::find_member<&internal::meta_conv_node::type>(type.fetch_node().details->conv, info.hash())))) {
- break;
- }
- }
- // NOLINTEND(cppcoreguidelines-pro-bounds-pointer-arithmetic)
- if(pos == sz) {
- if(!candidate || match > same) {
- candidate = curr;
- same = match;
- ambiguous = false;
- } else if(match == same) {
- if constexpr(std::is_same_v<std::decay_t<decltype(*curr)>, internal::meta_func_node>) {
- if(!!(curr->traits & internal::meta_traits::is_const) != !!(candidate->traits & internal::meta_traits::is_const)) {
- candidate = !!(candidate->traits & internal::meta_traits::is_const) ? curr : candidate;
- ambiguous = false;
- continue;
- }
- }
- ambiguous = true;
- }
- }
- }
- }
- return ambiguous ? nullptr : candidate;
- }
- public:
- /*! @brief Unsigned integer type. */
- using size_type = typename internal::meta_type_node::size_type;
- /*! @brief Default constructor. */
- meta_type() noexcept = default;
- /**
- * @brief Context aware constructor for meta objects.
- * @param area The context from which to search for meta types.
- * @param curr The underlying node with which to construct the instance.
- */
- meta_type(const meta_ctx &area, const internal::meta_type_node &curr) noexcept
- : node{&curr},
- ctx{&area} {}
- /**
- * @brief Context aware constructor for meta objects.
- * @param area The context from which to search for meta types.
- * @param curr The underlying node with which to construct the instance.
- */
- meta_type(const meta_ctx &area, const internal::meta_base_node &curr) noexcept
- : meta_type{area, curr.resolve(internal::meta_context::from(area))} {}
- /**
- * @brief Returns the type info object of the underlying type.
- * @return The type info object of the underlying type.
- */
- [[nodiscard]] const type_info &info() const noexcept {
- return *fetch_node().info;
- }
- /**
- * @brief Returns the identifier assigned to a type.
- * @return The identifier assigned to the type.
- */
- [[nodiscard]] id_type id() const noexcept {
- return fetch_node().id;
- }
- /**
- * @brief Returns the name assigned to a type, if any.
- * @return The name assigned to the type, if any.
- */
- [[nodiscard]] const char *name() const noexcept {
- return fetch_node().name;
- }
- /**
- * @brief Returns the size of the underlying type if known.
- * @return The size of the underlying type if known, 0 otherwise.
- */
- [[nodiscard]] size_type size_of() const noexcept {
- return fetch_node().size_of;
- }
- /**
- * @brief Checks whether a type refers to an arithmetic type or not.
- * @return True if the underlying type is an arithmetic type, false
- * otherwise.
- */
- [[nodiscard]] bool is_arithmetic() const noexcept {
- return !!(fetch_node().traits & internal::meta_traits::is_arithmetic);
- }
- /**
- * @brief Checks whether a type refers to an integral type or not.
- * @return True if the underlying type is an integral type, false otherwise.
- */
- [[nodiscard]] bool is_integral() const noexcept {
- return !!(fetch_node().traits & internal::meta_traits::is_integral);
- }
- /**
- * @brief Checks whether a type refers to a signed type or not.
- * @return True if the underlying type is a signed type, false otherwise.
- */
- [[nodiscard]] bool is_signed() const noexcept {
- return !!(fetch_node().traits & internal::meta_traits::is_signed);
- }
- /**
- * @brief Checks whether a type refers to an array type or not.
- * @return True if the underlying type is an array type, false otherwise.
- */
- [[nodiscard]] bool is_array() const noexcept {
- return !!(fetch_node().traits & internal::meta_traits::is_array);
- }
- /**
- * @brief Checks whether a type refers to an enum or not.
- * @return True if the underlying type is an enum, false otherwise.
- */
- [[nodiscard]] bool is_enum() const noexcept {
- return !!(fetch_node().traits & internal::meta_traits::is_enum);
- }
- /**
- * @brief Checks whether a type refers to a class or not.
- * @return True if the underlying type is a class, false otherwise.
- */
- [[nodiscard]] bool is_class() const noexcept {
- return !!(fetch_node().traits & internal::meta_traits::is_class);
- }
- /**
- * @brief Checks whether a type refers to a pointer or not.
- * @return True if the underlying type is a pointer, false otherwise.
- */
- [[nodiscard]] bool is_pointer() const noexcept {
- return !!(fetch_node().traits & internal::meta_traits::is_pointer);
- }
- /**
- * @brief Provides the type for which the pointer is defined.
- * @return The type for which the pointer is defined or this type if it
- * doesn't refer to a pointer type.
- */
- [[nodiscard]] meta_type remove_pointer() const noexcept {
- return meta_type{*ctx, fetch_node().remove_pointer(internal::meta_context::from(*ctx))};
- }
- /**
- * @brief Checks whether a type is a pointer-like type or not.
- * @return True if the underlying type is pointer-like, false otherwise.
- */
- [[nodiscard]] bool is_pointer_like() const noexcept {
- return !!(fetch_node().traits & internal::meta_traits::is_pointer_like);
- }
- /**
- * @brief Checks whether a type refers to a sequence container or not.
- * @return True if the type is a sequence container, false otherwise.
- */
- [[nodiscard]] bool is_sequence_container() const noexcept {
- return !!(fetch_node().traits & internal::meta_traits::is_sequence_container);
- }
- /**
- * @brief Checks whether a type refers to an associative container or not.
- * @return True if the type is an associative container, false otherwise.
- */
- [[nodiscard]] bool is_associative_container() const noexcept {
- return !!(fetch_node().traits & internal::meta_traits::is_associative_container);
- }
- /**
- * @brief Checks whether a type refers to a template specialization or not.
- * @return True if the type is a template specialization, false otherwise.
- */
- [[nodiscard]] bool is_template_specialization() const noexcept {
- return (fetch_node().templ.arity != 0u);
- }
- /**
- * @brief Returns the number of template arguments.
- * @return The number of template arguments.
- */
- [[nodiscard]] size_type template_arity() const noexcept {
- return fetch_node().templ.arity;
- }
- /**
- * @brief Returns a tag for the class template of the underlying type.
- * @return The tag for the class template of the underlying type.
- */
- [[nodiscard]] meta_type template_type() const noexcept {
- return (fetch_node().templ.resolve != nullptr) ? meta_type{*ctx, fetch_node().templ.resolve(internal::meta_context::from(*ctx))} : meta_type{};
- }
- /**
- * @brief Returns the type of the i-th template argument of a type.
- * @param index Index of the template argument of which to return the type.
- * @return The type of the i-th template argument of a type.
- */
- [[nodiscard]] meta_type template_arg(const size_type index) const noexcept {
- return index < template_arity() ? meta_type{*ctx, fetch_node().templ.arg(internal::meta_context::from(*ctx), index)} : meta_type{};
- }
- /**
- * @brief Checks if a type supports direct casting to another type.
- * @param other The meta type to test for.
- * @return True if direct casting is allowed, false otherwise.
- */
- [[nodiscard]] bool can_cast(const meta_type &other) const noexcept {
- // casting this is UB in all cases but we aren't going to use the resulting pointer, so...
- return other && ((*this == other) || (internal::try_cast(internal::meta_context::from(*ctx), fetch_node(), other.fetch_node().info->hash(), this) != nullptr));
- }
- /**
- * @brief Checks whether a type supports conversion to another type.
- * @param other The meta type to test for.
- * @return True if the conversion is allowed, false otherwise.
- */
- [[nodiscard]] bool can_convert(const meta_type &other) const noexcept {
- if(const auto &to = other.info().hash(); (info().hash() == to) || ((fetch_node().conversion_helper != nullptr) && (other.is_arithmetic() || other.is_enum()))) {
- return true;
- } else if(const auto &from = fetch_node(); from.details) {
- if(const auto *elem = internal::find_member<&internal::meta_conv_node::type>(from.details->conv, to); elem != nullptr) {
- return true;
- }
- for(auto &&curr: from.details->base) {
- if(curr.type == to || meta_type{*ctx, curr.resolve(internal::meta_context::from(*ctx))}.can_convert(other)) {
- return true;
- }
- }
- }
- return false;
- }
- /**
- * @brief Returns a range to visit registered top-level base meta types.
- * @return An iterable range to visit registered top-level base meta types.
- */
- [[nodiscard]] meta_range<meta_type, typename decltype(internal::meta_type_descriptor::base)::const_iterator> base() const noexcept {
- using range_type = meta_range<meta_type, typename decltype(internal::meta_type_descriptor::base)::const_iterator>;
- return fetch_node().details ? range_type{{*ctx, fetch_node().details->base.cbegin()}, {*ctx, fetch_node().details->base.cend()}} : range_type{};
- }
- /**
- * @brief Returns a range to visit registered top-level meta data.
- * @return An iterable range to visit registered top-level meta data.
- */
- [[nodiscard]] meta_range<meta_data, typename decltype(internal::meta_type_descriptor::data)::const_iterator> data() const noexcept {
- using range_type = meta_range<meta_data, typename decltype(internal::meta_type_descriptor::data)::const_iterator>;
- return fetch_node().details ? range_type{{*ctx, fetch_node().details->data.cbegin()}, {*ctx, fetch_node().details->data.cend()}} : range_type{};
- }
- /**
- * @brief Lookup utility for meta data (bases are also visited).
- * @param id Unique identifier.
- * @param recursive True for a search in the base classes, false otherwise.
- * @return The registered meta data for the given identifier, if any.
- */
- [[nodiscard]] meta_data data(const id_type id, const bool recursive = true) const {
- const auto *elem = internal::look_for<&internal::meta_type_descriptor::data>(internal::meta_context::from(*ctx), fetch_node(), id, recursive);
- return (elem != nullptr) ? meta_data{*ctx, *elem} : meta_data{};
- }
- /**
- * @brief Returns a range to visit registered top-level functions.
- * @return An iterable range to visit registered top-level functions.
- */
- [[nodiscard]] meta_range<meta_func, typename decltype(internal::meta_type_descriptor::func)::const_iterator> func() const noexcept {
- using return_type = meta_range<meta_func, typename decltype(internal::meta_type_descriptor::func)::const_iterator>;
- return fetch_node().details ? return_type{{*ctx, fetch_node().details->func.cbegin()}, {*ctx, fetch_node().details->func.cend()}} : return_type{};
- }
- /**
- * @brief Lookup utility for meta functions (bases are also visited).
- * @param id Unique identifier.
- * @param recursive True for a search in the base classes, false otherwise.
- * @return The registered meta function for the given identifier, if any.
- */
- [[nodiscard]] meta_func func(const id_type id, const bool recursive = true) const {
- const auto *elem = internal::look_for<&internal::meta_type_descriptor::func>(internal::meta_context::from(*ctx), fetch_node(), id, recursive);
- return (elem != nullptr) ? meta_func{*ctx, *elem} : meta_func{};
- }
- /**
- * @brief Creates an instance of the underlying type, if possible.
- * @param args Parameters to use to construct the instance.
- * @param sz Number of parameters to use to construct the instance.
- * @return A wrapper containing the new instance, if any.
- */
- [[nodiscard]] meta_any construct(meta_any *const args, const size_type sz) const {
- if(const auto &ref = fetch_node(); ref.details) {
- if(const auto *candidate = lookup(args, sz, false, [first = ref.details->ctor.cbegin(), last = ref.details->ctor.cend()]() mutable { return first == last ? nullptr : &*(first++); }); candidate) {
- return candidate->invoke(*ctx, args);
- }
- }
- if(const auto &ref = fetch_node(); (sz == 0u) && (ref.default_constructor != nullptr)) {
- return ref.default_constructor(*ctx);
- }
- return meta_any{meta_ctx_arg, *ctx};
- }
- /**
- * @copybrief construct
- * @tparam Args Types of arguments to use to construct the instance.
- * @param args Parameters to use to construct the instance.
- * @return A wrapper containing the new instance, if any.
- */
- template<typename... Args>
- [[nodiscard]] meta_any construct(Args &&...args) const {
- return construct(std::array<meta_any, sizeof...(Args)>{meta_any{*ctx, std::forward<Args>(args)}...}.data(), sizeof...(Args));
- // NOLINTNEXTLINE(clang-analyzer-cplusplus.NewDeleteLeaks)
- }
- /**
- * @brief Wraps an opaque element of the underlying type.
- * @param elem A valid pointer to an element of the underlying type.
- * @param transfer_ownership True to transfer ownership, false otherwise.
- * @return A wrapper that references the given instance.
- */
- [[nodiscard]] meta_any from_void(void *elem, bool transfer_ownership = false) const {
- return ((elem != nullptr) && (fetch_node().from_void != nullptr)) ? fetch_node().from_void(*ctx, elem, transfer_ownership ? elem : nullptr) : meta_any{meta_ctx_arg, *ctx};
- }
- /**
- * @brief Wraps an opaque element of the underlying type.
- * @param elem A valid pointer to an element of the underlying type.
- * @return A wrapper that references the given instance.
- */
- [[nodiscard]] meta_any from_void(const void *elem) const {
- return ((elem != nullptr) && (fetch_node().from_void != nullptr)) ? fetch_node().from_void(*ctx, nullptr, elem) : meta_any{meta_ctx_arg, *ctx};
- }
- /**
- * @brief Invokes a function given an identifier, if possible.
- * @tparam Instance Type of instance to operate on.
- * @param id Unique identifier.
- * @param instance An instance that fits the underlying type.
- * @param args Parameters to use to invoke the function.
- * @param sz Number of parameters to use to invoke the function.
- * @return A wrapper containing the returned value, if any.
- */
- template<typename Instance = meta_handle>
- // NOLINTNEXTLINE(modernize-use-nodiscard)
- meta_any invoke(const id_type id, Instance &&instance, meta_any *const args, const size_type sz) const {
- meta_handle wrapped{*ctx, std::forward<Instance>(instance)};
- if(const auto &ref = fetch_node(); ref.details) {
- if(auto *elem = internal::find_member<&internal::meta_func_node::id>(ref.details->func, id); elem != nullptr) {
- if(const auto *candidate = lookup(args, sz, (wrapped->base().policy() == any_policy::cref), [curr = elem]() mutable { return (curr != nullptr) ? std::exchange(curr, curr->next.get()) : nullptr; }); candidate) {
- return candidate->invoke(std::move(wrapped), args);
- }
- }
- }
- for(auto &&curr: base()) {
- if(auto elem = curr.second.invoke(id, *wrapped.operator->(), args, sz); elem) {
- return elem;
- }
- }
- return meta_any{meta_ctx_arg, *ctx};
- }
- /**
- * @copybrief invoke
- * @param id Unique identifier.
- * @tparam Instance Type of instance to operate on.
- * @tparam Args Types of arguments to use to invoke the function.
- * @param instance An instance that fits the underlying type.
- * @param args Parameters to use to invoke the function.
- * @return A wrapper containing the returned value, if any.
- */
- template<typename Instance = meta_handle, typename... Args>
- // NOLINTNEXTLINE(modernize-use-nodiscard)
- meta_any invoke(const id_type id, Instance &&instance, Args &&...args) const {
- return invoke(id, std::forward<Instance>(instance), std::array<meta_any, sizeof...(Args)>{meta_any{*ctx, std::forward<Args>(args)}...}.data(), sizeof...(Args));
- }
- /**
- * @brief Sets the value of a given variable.
- * @tparam Instance Type of instance to operate on.
- * @tparam Type Type of value to assign.
- * @param id Unique identifier.
- * @param instance An instance that fits the underlying type.
- * @param value Parameter to use to set the underlying variable.
- * @return True in case of success, false otherwise.
- */
- template<typename Instance = meta_handle, typename Type>
- // NOLINTNEXTLINE(modernize-use-nodiscard)
- bool set(const id_type id, Instance &&instance, Type &&value) const {
- const auto candidate = data(id);
- return candidate && candidate.set(std::forward<Instance>(instance), std::forward<Type>(value));
- }
- /**
- * @brief Gets the value of a given variable.
- * @tparam Instance Type of instance to operate on.
- * @param id Unique identifier.
- * @param instance An instance that fits the underlying type.
- * @return A wrapper containing the value of the underlying variable.
- */
- template<typename Instance = meta_handle>
- [[nodiscard]] meta_any get(const id_type id, Instance &&instance) const {
- const auto candidate = data(id);
- return candidate ? candidate.get(std::forward<Instance>(instance)) : meta_any{meta_ctx_arg, *ctx};
- }
- /*! @copydoc meta_data::traits */
- template<typename Type>
- [[nodiscard]] Type traits() const noexcept {
- return internal::meta_to_user_traits<Type>(fetch_node().traits);
- }
- /*! @copydoc meta_data::custom */
- [[nodiscard]] meta_custom custom() const noexcept {
- return fetch_node().custom;
- }
- /*! @copydoc meta_data::operator bool */
- [[nodiscard]] explicit operator bool() const noexcept {
- return (node != nullptr);
- }
- /*! @copydoc meta_data::operator== */
- [[nodiscard]] bool operator==(const meta_type &other) const noexcept {
- return (ctx == other.ctx) && (fetch_node().id == other.fetch_node().id);
- }
- private:
- mutable const internal::meta_type_node *node{};
- const meta_ctx *ctx{&locator<meta_ctx>::value_or()};
- };
- /*! @copydoc operator!=(const meta_data &, const meta_data &) */
- [[nodiscard]] inline bool operator!=(const meta_type &lhs, const meta_type &rhs) noexcept {
- return !(lhs == rhs);
- }
- [[nodiscard]] inline meta_type meta_any::type() const noexcept {
- return *this ? meta_type{*ctx, fetch_node()} : meta_type{};
- }
- template<typename... Args>
- // NOLINTNEXTLINE(modernize-use-nodiscard)
- meta_any meta_any::invoke(const id_type id, Args &&...args) const {
- return type().invoke(id, *this, std::forward<Args>(args)...);
- }
- template<typename... Args>
- meta_any meta_any::invoke(const id_type id, Args &&...args) {
- return type().invoke(id, *this, std::forward<Args>(args)...);
- }
- template<typename Type>
- bool meta_any::set(const id_type id, Type &&value) {
- return type().set(id, *this, std::forward<Type>(value));
- }
- [[nodiscard]] inline meta_any meta_any::get(const id_type id) const {
- return type().get(id, *this);
- }
- [[nodiscard]] inline meta_any meta_any::get(const id_type id) {
- return type().get(id, *this);
- }
- [[nodiscard]] inline meta_any meta_any::allow_cast(const meta_type &type) const {
- if(storage.has_value(type.info())) {
- return as_ref();
- } else if(*this) {
- if(const auto &from = fetch_node(); (from.conversion_helper != nullptr) && (type.is_arithmetic() || type.is_enum())) {
- auto other = type.construct();
- const auto value = from.conversion_helper(nullptr, storage.data());
- other.fetch_node().conversion_helper(other.storage.data(), &value);
- return other;
- }
- if(const auto &from = fetch_node(); from.details) {
- if(const auto *elem = internal::find_member<&internal::meta_conv_node::type>(from.details->conv, type.info().hash()); elem != nullptr) {
- return elem->conv(*ctx, storage.data());
- }
- for(auto &&curr: from.details->base) {
- if(auto other = curr.resolve(internal::meta_context::from(*ctx)).from_void(*ctx, nullptr, curr.cast(storage.data())); curr.type == type.info().hash()) {
- return other;
- } else if(auto from_base = std::as_const(other).allow_cast(type); from_base) {
- return from_base;
- }
- }
- }
- }
- return meta_any{meta_ctx_arg, *ctx};
- }
- [[nodiscard]] inline bool meta_any::allow_cast(const meta_type &type) {
- if(storage.has_value(type.info())) {
- return true;
- } else if(auto other = std::as_const(*this).allow_cast(type); other) {
- if(other.storage.owner()) {
- std::swap(*this, other);
- }
- return true;
- }
- return false;
- }
- inline bool meta_any::assign(const meta_any &other) {
- if(!storage.assign(other.storage)) {
- auto value = other.allow_cast(type());
- return storage.assign(value.storage);
- }
- return true;
- }
- inline bool meta_any::assign(meta_any &&other) {
- return storage.assign(std::move(other.storage)) || storage.assign(std::as_const(other).allow_cast(type()).storage);
- }
- [[nodiscard]] inline meta_type meta_data::type() const noexcept {
- return meta_type{*ctx, node_or_assert().type(internal::meta_context::from(*ctx))};
- }
- [[nodiscard]] inline meta_type meta_data::arg(const size_type index) const noexcept {
- return index < arity() ? node_or_assert().arg(*ctx, index) : meta_type{};
- }
- [[nodiscard]] inline meta_type meta_func::ret() const noexcept {
- return meta_type{*ctx, node_or_assert().ret(internal::meta_context::from(*ctx))};
- }
- [[nodiscard]] inline meta_type meta_func::arg(const size_type index) const noexcept {
- return index < arity() ? node_or_assert().arg(*ctx, index) : meta_type{};
- }
- /*! @cond TURN_OFF_DOXYGEN */
- class meta_sequence_container::meta_iterator final {
- using vtable_type = void(const void *, const std::ptrdiff_t, meta_any *);
- template<typename It>
- static void basic_vtable(const void *value, const std::ptrdiff_t offset, meta_any *other) {
- const auto &it = *static_cast<const It *>(value);
- other ? other->emplace<decltype(*it)>(*it) : std::advance(const_cast<It &>(it), offset);
- }
- public:
- using value_type = meta_any;
- using pointer = input_iterator_pointer<value_type>;
- using reference = value_type;
- using difference_type = std::ptrdiff_t;
- using iterator_category = std::input_iterator_tag;
- using iterator_concept = std::bidirectional_iterator_tag;
- meta_iterator() = default;
- template<typename It>
- meta_iterator(const meta_ctx &area, It iter) noexcept
- : ctx{&area},
- vtable{&basic_vtable<It>},
- handle{iter} {}
- meta_iterator &operator++() noexcept {
- return vtable(handle.data(), 1, nullptr), *this;
- }
- meta_iterator operator++(int value) noexcept {
- meta_iterator orig = *this;
- vtable(handle.data(), ++value, nullptr);
- return orig;
- }
- meta_iterator &operator--() noexcept {
- return vtable(handle.data(), -1, nullptr), *this;
- }
- meta_iterator operator--(int value) noexcept {
- meta_iterator orig = *this;
- vtable(handle.data(), --value, nullptr);
- return orig;
- }
- [[nodiscard]] reference operator*() const {
- reference other{meta_ctx_arg, *ctx};
- vtable(handle.data(), 0, &other);
- return other;
- }
- [[nodiscard]] pointer operator->() const {
- return operator*();
- }
- [[nodiscard]] explicit operator bool() const noexcept {
- return (vtable != nullptr);
- }
- [[nodiscard]] bool operator==(const meta_iterator &other) const noexcept {
- return handle == other.handle;
- }
- [[nodiscard]] const any &base() const noexcept {
- return handle;
- }
- private:
- const meta_ctx *ctx{};
- vtable_type *vtable{};
- any handle{};
- };
- [[nodiscard]] inline bool operator!=(const meta_sequence_container::iterator &lhs, const meta_sequence_container::iterator &rhs) noexcept {
- return !(lhs == rhs);
- }
- class meta_associative_container::meta_iterator final {
- using vtable_type = void(const void *, std::pair<meta_any, meta_any> *);
- template<bool KeyOnly, typename It>
- static void basic_vtable(const void *value, std::pair<meta_any, meta_any> *other) {
- if(const auto &it = *static_cast<const It *>(value); other) {
- if constexpr(KeyOnly) {
- other->first.emplace<decltype(*it)>(*it);
- } else {
- other->first.emplace<decltype((it->first))>(it->first);
- other->second.emplace<decltype((it->second))>(it->second);
- }
- } else {
- ++const_cast<It &>(it);
- }
- }
- public:
- using value_type = std::pair<meta_any, meta_any>;
- using pointer = input_iterator_pointer<value_type>;
- using reference = value_type;
- using difference_type = std::ptrdiff_t;
- using iterator_category = std::input_iterator_tag;
- using iterator_concept = std::forward_iterator_tag;
- meta_iterator() = default;
- template<bool KeyOnly, typename It>
- meta_iterator(const meta_ctx &area, std::bool_constant<KeyOnly>, It iter) noexcept
- : ctx{&area},
- vtable{&basic_vtable<KeyOnly, It>},
- handle{iter} {}
- meta_iterator &operator++() noexcept {
- return vtable(handle.data(), nullptr), *this;
- }
- meta_iterator operator++(int) noexcept {
- meta_iterator orig = *this;
- vtable(handle.data(), nullptr);
- return orig;
- }
- [[nodiscard]] reference operator*() const {
- reference other{{meta_ctx_arg, *ctx}, {meta_ctx_arg, *ctx}};
- vtable(handle.data(), &other);
- return other;
- }
- [[nodiscard]] pointer operator->() const {
- return operator*();
- }
- [[nodiscard]] explicit operator bool() const noexcept {
- return (vtable != nullptr);
- }
- [[nodiscard]] bool operator==(const meta_iterator &other) const noexcept {
- return handle == other.handle;
- }
- private:
- const meta_ctx *ctx{};
- vtable_type *vtable{};
- any handle{};
- };
- [[nodiscard]] inline bool operator!=(const meta_associative_container::iterator &lhs, const meta_associative_container::iterator &rhs) noexcept {
- return !(lhs == rhs);
- }
- /*! @endcond */
- /**
- * @brief Returns the meta value type of a container.
- * @return The meta value type of the container.
- */
- [[nodiscard]] inline meta_type meta_sequence_container::value_type() const noexcept {
- return (value_type_node != nullptr) ? meta_type{*ctx, value_type_node(internal::meta_context::from(*ctx))} : meta_type{};
- }
- /**
- * @brief Returns the size of a container.
- * @return The size of the container.
- */
- [[nodiscard]] inline meta_sequence_container::size_type meta_sequence_container::size() const noexcept {
- return size_fn(data);
- }
- /**
- * @brief Resizes a container to contain a given number of elements.
- * @param sz The new size of the container.
- * @return True in case of success, false otherwise.
- */
- inline bool meta_sequence_container::resize(const size_type sz) {
- return !const_only && resize_fn(const_cast<void *>(data), sz);
- }
- /**
- * @brief Clears the content of a container.
- * @return True in case of success, false otherwise.
- */
- inline bool meta_sequence_container::clear() {
- return !const_only && clear_fn(const_cast<void *>(data));
- }
- /**
- * @brief Reserves storage for at least the given number of elements.
- * @param sz The new capacity of the container.
- * @return True in case of success, false otherwise.
- */
- inline bool meta_sequence_container::reserve(const size_type sz) {
- return !const_only && reserve_fn(const_cast<void *>(data), sz);
- }
- /**
- * @brief Returns an iterator to the first element of a container.
- * @return An iterator to the first element of the container.
- */
- [[nodiscard]] inline meta_sequence_container::iterator meta_sequence_container::begin() {
- return begin_end_fn(*ctx, const_only ? nullptr : const_cast<void *>(data), data, false);
- }
- /**
- * @brief Returns an iterator that is past the last element of a container.
- * @return An iterator that is past the last element of the container.
- */
- [[nodiscard]] inline meta_sequence_container::iterator meta_sequence_container::end() {
- return begin_end_fn(*ctx, const_only ? nullptr : const_cast<void *>(data), data, true);
- }
- /**
- * @brief Inserts an element at a specified location of a container.
- * @param it Iterator before which the element will be inserted.
- * @param value Element value to insert.
- * @return A possibly invalid iterator to the inserted element.
- */
- inline meta_sequence_container::iterator meta_sequence_container::insert(const iterator &it, meta_any value) {
- // this abomination is necessary because only on macos value_type and const_reference are different types for std::vector<bool>
- if(const auto &vtype = value_type_node(internal::meta_context::from(*ctx)); !const_only && (value.allow_cast({*ctx, vtype}) || value.allow_cast({*ctx, const_reference_node(internal::meta_context::from(*ctx))}))) {
- const bool is_value_type = (value.type().info() == *vtype.info);
- return insert_fn(*ctx, const_cast<void *>(data), is_value_type ? value.base().data() : nullptr, is_value_type ? nullptr : value.base().data(), it);
- }
- return iterator{};
- }
- /**
- * @brief Removes a given element from a container.
- * @param it Iterator to the element to remove.
- * @return A possibly invalid iterator following the last removed element.
- */
- inline meta_sequence_container::iterator meta_sequence_container::erase(const iterator &it) {
- return const_only ? iterator{} : erase_fn(*ctx, const_cast<void *>(data), it);
- }
- /**
- * @brief Returns a reference to the element at a given location of a container.
- * @param pos The position of the element to return.
- * @return A reference to the requested element properly wrapped.
- */
- [[nodiscard]] inline meta_any meta_sequence_container::operator[](const size_type pos) {
- auto it = begin();
- it.operator++(static_cast<int>(pos) - 1);
- return *it;
- }
- /**
- * @brief Returns false if a proxy is invalid, true otherwise.
- * @return False if the proxy is invalid, true otherwise.
- */
- [[nodiscard]] inline meta_sequence_container::operator bool() const noexcept {
- return (data != nullptr);
- }
- /**
- * @brief Returns the meta key type of a container.
- * @return The meta key type of the a container.
- */
- [[nodiscard]] inline meta_type meta_associative_container::key_type() const noexcept {
- return (key_type_node != nullptr) ? meta_type{*ctx, key_type_node(internal::meta_context::from(*ctx))} : meta_type{};
- }
- /**
- * @brief Returns the meta mapped type of a container.
- * @return The meta mapped type of the a container.
- */
- [[nodiscard]] inline meta_type meta_associative_container::mapped_type() const noexcept {
- return (mapped_type_node != nullptr) ? meta_type{*ctx, mapped_type_node(internal::meta_context::from(*ctx))} : meta_type{};
- }
- /*! @copydoc meta_sequence_container::value_type */
- [[nodiscard]] inline meta_type meta_associative_container::value_type() const noexcept {
- return (value_type_node != nullptr) ? meta_type{*ctx, value_type_node(internal::meta_context::from(*ctx))} : meta_type{};
- }
- /*! @copydoc meta_sequence_container::size */
- [[nodiscard]] inline meta_associative_container::size_type meta_associative_container::size() const noexcept {
- return size_fn(data);
- }
- /*! @copydoc meta_sequence_container::clear */
- inline bool meta_associative_container::clear() {
- return !const_only && clear_fn(const_cast<void *>(data));
- }
- /*! @copydoc meta_sequence_container::reserve */
- inline bool meta_associative_container::reserve(const size_type sz) {
- return !const_only && reserve_fn(const_cast<void *>(data), sz);
- }
- /*! @copydoc meta_sequence_container::begin */
- [[nodiscard]] inline meta_associative_container::iterator meta_associative_container::begin() {
- return begin_end_fn(*ctx, const_only ? nullptr : const_cast<void *>(data), data, false);
- }
- /*! @copydoc meta_sequence_container::end */
- [[nodiscard]] inline meta_associative_container::iterator meta_associative_container::end() {
- return begin_end_fn(*ctx, const_only ? nullptr : const_cast<void *>(data), data, true);
- }
- /**
- * @brief Inserts a key-only or key/value element into a container.
- * @param key The key of the element to insert.
- * @param value The value of the element to insert, if needed.
- * @return A bool denoting whether the insertion took place.
- */
- inline bool meta_associative_container::insert(meta_any key, meta_any value = {}) {
- return !const_only && key.allow_cast(meta_type{*ctx, key_type_node(internal::meta_context::from(*ctx))})
- && ((mapped_type_node == nullptr) || value.allow_cast(meta_type{*ctx, mapped_type_node(internal::meta_context::from(*ctx))}))
- && insert_fn(const_cast<void *>(data), key.base().data(), value.base().data());
- }
- /**
- * @brief Removes the specified element from a container.
- * @param key The key of the element to remove.
- * @return A bool denoting whether the removal took place.
- */
- inline meta_associative_container::size_type meta_associative_container::erase(meta_any key) {
- return (!const_only && key.allow_cast(meta_type{*ctx, key_type_node(internal::meta_context::from(*ctx))})) ? erase_fn(const_cast<void *>(data), key.base().data()) : 0u;
- }
- /**
- * @brief Returns an iterator to the element with a given key, if any.
- * @param key The key of the element to search.
- * @return An iterator to the element with the given key, if any.
- */
- [[nodiscard]] inline meta_associative_container::iterator meta_associative_container::find(meta_any key) {
- return key.allow_cast(meta_type{*ctx, key_type_node(internal::meta_context::from(*ctx))}) ? find_fn(*ctx, const_only ? nullptr : const_cast<void *>(data), data, key.base().data()) : iterator{};
- }
- /**
- * @brief Returns false if a proxy is invalid, true otherwise.
- * @return False if the proxy is invalid, true otherwise.
- */
- [[nodiscard]] inline meta_associative_container::operator bool() const noexcept {
- return (data != nullptr);
- }
- } // namespace entt
- #endif
- // #include "meta/node.hpp"
- #ifndef ENTT_META_NODE_HPP
- #define ENTT_META_NODE_HPP
- #include <array>
- #include <cstddef>
- #include <memory>
- #include <type_traits>
- #include <utility>
- #include <vector>
- // #include "../config/config.h"
- // #include "../core/bit.hpp"
- // #include "../core/enum.hpp"
- // #include "../core/fwd.hpp"
- // #include "../core/type_info.hpp"
- // #include "../core/type_traits.hpp"
- // #include "../core/utility.hpp"
- // #include "context.hpp"
- // #include "type_traits.hpp"
- namespace entt {
- class meta_any;
- class meta_type;
- class meta_handle;
- /*! @cond TURN_OFF_DOXYGEN */
- namespace internal {
- enum class meta_traits : std::uint32_t {
- is_none = 0x0000,
- is_const = 0x0001,
- is_static = 0x0002,
- is_arithmetic = 0x0004,
- is_integral = 0x0008,
- is_signed = 0x0010,
- is_array = 0x0020,
- is_enum = 0x0040,
- is_class = 0x0080,
- is_pointer = 0x0100,
- is_pointer_like = 0x0200,
- is_sequence_container = 0x0400,
- is_associative_container = 0x0800,
- _user_defined_traits = 0xFFFF,
- _entt_enum_as_bitmask = 0xFFFF
- };
- template<typename Type>
- [[nodiscard]] auto meta_to_user_traits(const meta_traits traits) noexcept {
- static_assert(std::is_enum_v<Type>, "Invalid enum type");
- constexpr auto shift = popcount(static_cast<std::underlying_type_t<meta_traits>>(meta_traits::_user_defined_traits));
- return Type{static_cast<std::underlying_type_t<Type>>(static_cast<std::underlying_type_t<meta_traits>>(traits) >> shift)};
- }
- template<typename Type>
- [[nodiscard]] auto user_to_meta_traits(const Type value) noexcept {
- static_assert(std::is_enum_v<Type>, "Invalid enum type");
- constexpr auto shift = popcount(static_cast<std::underlying_type_t<meta_traits>>(meta_traits::_user_defined_traits));
- const auto traits = static_cast<std::underlying_type_t<internal::meta_traits>>(static_cast<std::underlying_type_t<Type>>(value));
- ENTT_ASSERT(traits < ((~static_cast<std::underlying_type_t<meta_traits>>(meta_traits::_user_defined_traits)) >> shift), "Invalid traits");
- return meta_traits{traits << shift};
- }
- struct meta_type_node;
- struct meta_custom_node {
- id_type type{};
- std::shared_ptr<void> value{};
- };
- struct meta_base_node {
- id_type type{};
- const meta_type_node &(*resolve)(const meta_context &) noexcept {};
- const void *(*cast)(const void *) noexcept {};
- };
- struct meta_conv_node {
- id_type type{};
- meta_any (*conv)(const meta_ctx &, const void *){};
- };
- struct meta_ctor_node {
- using size_type = std::size_t;
- id_type id{};
- size_type arity{0u};
- meta_type (*arg)(const meta_ctx &, const size_type) noexcept {};
- meta_any (*invoke)(const meta_ctx &, meta_any *const){};
- };
- struct meta_data_node {
- using size_type = std::size_t;
- id_type id{};
- const char *name{};
- meta_traits traits{meta_traits::is_none};
- size_type arity{0u};
- const meta_type_node &(*type)(const meta_context &) noexcept {};
- meta_type (*arg)(const meta_ctx &, const size_type) noexcept {};
- bool (*set)(meta_handle, meta_any){};
- meta_any (*get)(meta_handle){};
- meta_custom_node custom{};
- };
- struct meta_func_node {
- using size_type = std::size_t;
- id_type id{};
- const char *name{};
- meta_traits traits{meta_traits::is_none};
- size_type arity{0u};
- const meta_type_node &(*ret)(const meta_context &) noexcept {};
- meta_type (*arg)(const meta_ctx &, const size_type) noexcept {};
- meta_any (*invoke)(meta_handle, meta_any *const){};
- std::unique_ptr<meta_func_node> next;
- meta_custom_node custom{};
- };
- struct meta_template_node {
- using size_type = std::size_t;
- size_type arity{0u};
- const meta_type_node &(*resolve)(const meta_context &) noexcept {};
- const meta_type_node &(*arg)(const meta_context &, const size_type) noexcept {};
- };
- struct meta_type_descriptor {
- std::vector<meta_ctor_node> ctor{};
- std::vector<meta_base_node> base{};
- std::vector<meta_conv_node> conv{};
- std::vector<meta_data_node> data{};
- std::vector<meta_func_node> func{};
- };
- struct meta_type_node {
- using size_type = std::size_t;
- const type_info *info{};
- id_type id{};
- const char *name{};
- meta_traits traits{meta_traits::is_none};
- size_type size_of{0u};
- const meta_type_node &(*remove_pointer)(const meta_context &) noexcept {};
- meta_any (*default_constructor)(const meta_ctx &){};
- double (*conversion_helper)(void *, const void *){};
- meta_any (*from_void)(const meta_ctx &, void *, const void *){};
- meta_template_node templ{};
- meta_custom_node custom{};
- std::unique_ptr<meta_type_descriptor> details{};
- };
- template<auto Member, typename Type, typename Value>
- [[nodiscard]] auto *find_member(Type &from, const Value value) {
- for(auto &&elem: from) {
- if((elem.*Member) == value) {
- return &elem;
- }
- }
- return static_cast<typename Type::value_type *>(nullptr);
- }
- [[nodiscard]] inline auto *find_overload(meta_func_node *curr, std::remove_pointer_t<decltype(meta_func_node::invoke)> *const ref) {
- while((curr != nullptr) && (curr->invoke != ref)) { curr = curr->next.get(); }
- return curr;
- }
- template<auto Member>
- [[nodiscard]] auto *look_for(const meta_context &context, const meta_type_node &node, const id_type id, bool recursive) {
- using value_type = typename std::remove_reference_t<decltype((node.details.get()->*Member))>::value_type;
- if(node.details) {
- if(auto *member = find_member<&value_type::id>((node.details.get()->*Member), id); member != nullptr) {
- return member;
- }
- if(recursive) {
- for(auto &&curr: node.details->base) {
- if(auto *elem = look_for<Member>(context, curr.resolve(context), id, recursive); elem) {
- return elem;
- }
- }
- }
- }
- return static_cast<value_type *>(nullptr);
- }
- template<typename Type>
- const meta_type_node &resolve(const meta_context &) noexcept;
- template<typename... Args>
- [[nodiscard]] const meta_type_node &meta_arg_node(const meta_context &context, type_list<Args...>, const std::size_t index) noexcept {
- using resolve_type = const meta_type_node &(*)(const meta_context &) noexcept;
- constexpr std::array<resolve_type, sizeof...(Args)> list{&resolve<std::remove_const_t<std::remove_reference_t<Args>>>...};
- ENTT_ASSERT(index < sizeof...(Args), "Out of bounds");
- return list[index](context);
- }
- [[nodiscard]] inline const void *try_cast(const meta_context &context, const meta_type_node &from, const id_type to, const void *instance) noexcept {
- if(from.details) {
- for(auto &&curr: from.details->base) {
- if(const void *other = curr.cast(instance); curr.type == to) {
- return other;
- } else if(const void *elem = try_cast(context, curr.resolve(context), to, other); elem) {
- return elem;
- }
- }
- }
- return nullptr;
- }
- template<typename Type>
- auto setup_node_for() noexcept {
- meta_type_node node{
- &type_id<Type>(),
- type_id<Type>().hash(),
- nullptr,
- (std::is_arithmetic_v<Type> ? meta_traits::is_arithmetic : meta_traits::is_none)
- | (std::is_integral_v<Type> ? meta_traits::is_integral : meta_traits::is_none)
- | (std::is_signed_v<Type> ? meta_traits::is_signed : meta_traits::is_none)
- | (std::is_array_v<Type> ? meta_traits::is_array : meta_traits::is_none)
- | (std::is_enum_v<Type> ? meta_traits::is_enum : meta_traits::is_none)
- | (std::is_class_v<Type> ? meta_traits::is_class : meta_traits::is_none)
- | (std::is_pointer_v<Type> ? meta_traits::is_pointer : meta_traits::is_none)
- | (is_meta_pointer_like_v<Type> ? meta_traits::is_pointer_like : meta_traits::is_none)
- | (is_complete_v<meta_sequence_container_traits<Type>> ? meta_traits::is_sequence_container : meta_traits::is_none)
- | (is_complete_v<meta_associative_container_traits<Type>> ? meta_traits::is_associative_container : meta_traits::is_none),
- size_of_v<Type>,
- &resolve<std::remove_const_t<std::remove_pointer_t<Type>>>};
- if constexpr(std::is_default_constructible_v<Type>) {
- node.default_constructor = +[](const meta_ctx &ctx) {
- return meta_any{ctx, std::in_place_type<Type>};
- };
- }
- if constexpr(std::is_arithmetic_v<Type>) {
- node.conversion_helper = +[](void *lhs, const void *rhs) {
- return lhs ? static_cast<double>(*static_cast<Type *>(lhs) = static_cast<Type>(*static_cast<const double *>(rhs))) : static_cast<double>(*static_cast<const Type *>(rhs));
- };
- } else if constexpr(std::is_enum_v<Type>) {
- node.conversion_helper = +[](void *lhs, const void *rhs) {
- return lhs ? static_cast<double>(*static_cast<Type *>(lhs) = static_cast<Type>(static_cast<std::underlying_type_t<Type>>(*static_cast<const double *>(rhs)))) : static_cast<double>(*static_cast<const Type *>(rhs));
- };
- }
- if constexpr(!std::is_void_v<Type> && !std::is_function_v<Type>) {
- node.from_void = +[](const meta_ctx &ctx, void *elem, const void *celem) {
- if(elem && celem) { // ownership construction request
- return meta_any{ctx, std::in_place, static_cast<std::decay_t<Type> *>(elem)};
- }
- if(elem) { // non-const reference construction request
- return meta_any{ctx, std::in_place_type<std::decay_t<Type> &>, *static_cast<std::decay_t<Type> *>(elem)};
- }
- // const reference construction request
- return meta_any{ctx, std::in_place_type<const std::decay_t<Type> &>, *static_cast<const std::decay_t<Type> *>(celem)};
- };
- }
- if constexpr(is_complete_v<meta_template_traits<Type>>) {
- node.templ = meta_template_node{
- meta_template_traits<Type>::args_type::size,
- &resolve<typename meta_template_traits<Type>::class_type>,
- +[](const meta_context &area, const std::size_t index) noexcept -> decltype(auto) { return meta_arg_node(area, typename meta_template_traits<Type>::args_type{}, index); }};
- }
- return node;
- }
- [[nodiscard]] inline const meta_type_node *try_resolve(const meta_context &context, const type_info &info) noexcept {
- const auto it = context.value.find(info.hash());
- return (it != context.value.end()) ? it->second.get() : nullptr;
- }
- template<typename Type>
- [[nodiscard]] const meta_type_node &resolve(const meta_context &context) noexcept {
- static_assert(std::is_same_v<Type, std::remove_const_t<std::remove_reference_t<Type>>>, "Invalid type");
- static const meta_type_node node = setup_node_for<Type>();
- const auto *elem = try_resolve(context, *node.info);
- return (elem == nullptr) ? node : *elem;
- }
- } // namespace internal
- /*! @endcond */
- } // namespace entt
- #endif
- // #include "meta/pointer.hpp"
- // IWYU pragma: always_keep
- #ifndef ENTT_META_POINTER_HPP
- #define ENTT_META_POINTER_HPP
- #include <memory>
- #include <type_traits>
- // #include "type_traits.hpp"
- namespace entt {
- /**
- * @brief Makes plain pointers pointer-like types for the meta system.
- * @tparam Type Element type.
- */
- template<typename Type>
- struct is_meta_pointer_like<Type *>
- : std::true_type {};
- /**
- * @brief Partial specialization used to reject pointers to arrays.
- * @tparam Type Type of elements of the array.
- * @tparam N Number of elements of the array.
- */
- template<typename Type, std::size_t N>
- // NOLINTNEXTLINE(cppcoreguidelines-avoid-c-arrays, modernize-avoid-c-arrays)
- struct is_meta_pointer_like<Type (*)[N]>
- : std::false_type {};
- /**
- * @brief Makes `std::shared_ptr`s of any type pointer-like types for the meta
- * system.
- * @tparam Type Element type.
- */
- template<typename Type>
- struct is_meta_pointer_like<std::shared_ptr<Type>>
- : std::true_type {};
- /**
- * @brief Makes `std::unique_ptr`s of any type pointer-like types for the meta
- * system.
- * @tparam Type Element type.
- * @tparam Args Other arguments.
- */
- template<typename Type, typename... Args>
- struct is_meta_pointer_like<std::unique_ptr<Type, Args...>>
- : std::true_type {};
- /**
- * @brief Specialization for self-proclaimed meta pointer like types.
- * @tparam Type Element type.
- */
- template<typename Type>
- struct is_meta_pointer_like<Type, std::void_t<typename Type::is_meta_pointer_like>>
- : std::true_type {};
- } // namespace entt
- #endif
- // #include "meta/policy.hpp"
- #ifndef ENTT_META_POLICY_HPP
- #define ENTT_META_POLICY_HPP
- #include <type_traits>
- namespace entt {
- /*! @cond TURN_OFF_DOXYGEN */
- namespace internal {
- struct meta_policy {};
- } // namespace internal
- /*! @endcond */
- /*! @brief Empty class type used to request the _as-is_ policy. */
- struct as_value_t final: private internal::meta_policy {
- /*! @cond TURN_OFF_DOXYGEN */
- template<typename>
- static constexpr bool value = true;
- /*! @endcond */
- };
- /*! @brief Empty class type used to request the _as void_ policy. */
- struct as_void_t final: private internal::meta_policy {
- /*! @cond TURN_OFF_DOXYGEN */
- template<typename>
- static constexpr bool value = true;
- /*! @endcond */
- };
- /*! @brief Empty class type used to request the _as ref_ policy. */
- struct as_ref_t final: private internal::meta_policy {
- /*! @cond TURN_OFF_DOXYGEN */
- template<typename Type>
- static constexpr bool value = std::is_reference_v<Type> && !std::is_const_v<std::remove_reference_t<Type>>;
- /*! @endcond */
- };
- /*! @brief Empty class type used to request the _as cref_ policy. */
- struct as_cref_t final: private internal::meta_policy {
- /*! @cond TURN_OFF_DOXYGEN */
- template<typename Type>
- static constexpr bool value = std::is_reference_v<Type>;
- /*! @endcond */
- };
- /*! @brief Empty class type used to request the _as auto_ policy. */
- struct as_is_t final: private internal::meta_policy {
- /*! @cond TURN_OFF_DOXYGEN */
- template<typename>
- static constexpr bool value = true;
- /*! @endcond */
- };
- /**
- * @brief Provides the member constant `value` to true if a type also is a meta
- * policy, false otherwise.
- * @tparam Type Type to check.
- */
- template<typename Type>
- struct is_meta_policy
- : std::bool_constant<std::is_base_of_v<internal::meta_policy, Type>> {};
- /**
- * @brief Helper variable template.
- * @tparam Type Type to check.
- */
- template<typename Type>
- inline constexpr bool is_meta_policy_v = is_meta_policy<Type>::value;
- } // namespace entt
- #endif
- // #include "meta/range.hpp"
- #ifndef ENTT_META_RANGE_HPP
- #define ENTT_META_RANGE_HPP
- #include <cstddef>
- #include <iterator>
- #include <utility>
- // #include "../core/fwd.hpp"
- // #include "../core/iterator.hpp"
- // #include "context.hpp"
- namespace entt {
- /*! @cond TURN_OFF_DOXYGEN */
- namespace internal {
- struct meta_base_node;
- template<typename Type, typename It>
- struct meta_range_iterator final {
- using value_type = std::pair<id_type, Type>;
- using pointer = input_iterator_pointer<value_type>;
- using reference = value_type;
- using difference_type = std::ptrdiff_t;
- using iterator_category = std::input_iterator_tag;
- using iterator_concept = std::random_access_iterator_tag;
- constexpr meta_range_iterator() noexcept
- : it{},
- ctx{} {}
- constexpr meta_range_iterator(const meta_ctx &area, const It iter) noexcept
- : it{iter},
- ctx{&area} {}
- constexpr meta_range_iterator &operator++() noexcept {
- return ++it, *this;
- }
- constexpr meta_range_iterator operator++(int) noexcept {
- const meta_range_iterator orig = *this;
- return ++(*this), orig;
- }
- constexpr meta_range_iterator &operator--() noexcept {
- return --it, *this;
- }
- constexpr meta_range_iterator operator--(int) noexcept {
- const meta_range_iterator orig = *this;
- return operator--(), orig;
- }
- constexpr meta_range_iterator &operator+=(const difference_type value) noexcept {
- it += value;
- return *this;
- }
- constexpr meta_range_iterator operator+(const difference_type value) const noexcept {
- meta_range_iterator copy = *this;
- return (copy += value);
- }
- constexpr meta_range_iterator &operator-=(const difference_type value) noexcept {
- return (*this += -value);
- }
- constexpr meta_range_iterator operator-(const difference_type value) const noexcept {
- return (*this + -value);
- }
- [[nodiscard]] constexpr reference operator[](const difference_type value) const noexcept {
- if constexpr(std::is_same_v<It, typename decltype(meta_context::value)::const_iterator>) {
- return {it[value].first, Type{*ctx, *it[value].second}};
- } else if constexpr(std::is_same_v<typename std::iterator_traits<It>::value_type, meta_base_node>) {
- return {it[value].type, Type{*ctx, it[value]}};
- } else {
- return {it[value].id, Type{*ctx, it[value]}};
- }
- }
- [[nodiscard]] constexpr pointer operator->() const noexcept {
- return operator*();
- }
- [[nodiscard]] constexpr reference operator*() const noexcept {
- return operator[](0);
- }
- template<typename... Args>
- friend constexpr std::ptrdiff_t operator-(const meta_range_iterator<Args...> &, const meta_range_iterator<Args...> &) noexcept;
- template<typename... Args>
- friend constexpr bool operator==(const meta_range_iterator<Args...> &, const meta_range_iterator<Args...> &) noexcept;
- template<typename... Args>
- friend constexpr bool operator<(const meta_range_iterator<Args...> &, const meta_range_iterator<Args...> &) noexcept;
- private:
- It it;
- const meta_ctx *ctx;
- };
- template<typename... Args>
- [[nodiscard]] constexpr std::ptrdiff_t operator-(const meta_range_iterator<Args...> &lhs, const meta_range_iterator<Args...> &rhs) noexcept {
- return lhs.it - rhs.it;
- }
- template<typename... Args>
- [[nodiscard]] constexpr bool operator==(const meta_range_iterator<Args...> &lhs, const meta_range_iterator<Args...> &rhs) noexcept {
- return lhs.it == rhs.it;
- }
- template<typename... Args>
- [[nodiscard]] constexpr bool operator!=(const meta_range_iterator<Args...> &lhs, const meta_range_iterator<Args...> &rhs) noexcept {
- return !(lhs == rhs);
- }
- template<typename... Args>
- [[nodiscard]] constexpr bool operator<(const meta_range_iterator<Args...> &lhs, const meta_range_iterator<Args...> &rhs) noexcept {
- return lhs.it < rhs.it;
- }
- template<typename... Args>
- [[nodiscard]] constexpr bool operator>(const meta_range_iterator<Args...> &lhs, const meta_range_iterator<Args...> &rhs) noexcept {
- return rhs < lhs;
- }
- template<typename... Args>
- [[nodiscard]] constexpr bool operator<=(const meta_range_iterator<Args...> &lhs, const meta_range_iterator<Args...> &rhs) noexcept {
- return !(lhs > rhs);
- }
- template<typename... Args>
- [[nodiscard]] constexpr bool operator>=(const meta_range_iterator<Args...> &lhs, const meta_range_iterator<Args...> &rhs) noexcept {
- return !(lhs < rhs);
- }
- } // namespace internal
- /*! @endcond */
- /**
- * @brief Iterable range to use to iterate all types of meta objects.
- * @tparam Type Type of meta objects returned.
- * @tparam It Type of forward iterator.
- */
- template<typename Type, typename It>
- using meta_range = iterable_adaptor<internal::meta_range_iterator<Type, It>>;
- } // namespace entt
- #endif
- // #include "meta/resolve.hpp"
- #ifndef ENTT_META_RESOLVE_HPP
- #define ENTT_META_RESOLVE_HPP
- #include <type_traits>
- // #include "../core/type_info.hpp"
- // #include "../locator/locator.hpp"
- // #include "context.hpp"
- // #include "meta.hpp"
- // #include "node.hpp"
- // #include "range.hpp"
- namespace entt {
- /**
- * @brief Returns the meta type associated with a given type.
- * @tparam Type Type to use to search for a meta type.
- * @param ctx The context from which to search for meta types.
- * @return The meta type associated with the given type, if any.
- */
- template<typename Type>
- [[nodiscard]] meta_type resolve(const meta_ctx &ctx) noexcept {
- const auto &context = internal::meta_context::from(ctx);
- return {ctx, internal::resolve<std::remove_const_t<std::remove_reference_t<Type>>>(context)};
- }
- /**
- * @brief Returns the meta type associated with a given type.
- * @tparam Type Type to use to search for a meta type.
- * @return The meta type associated with the given type, if any.
- */
- template<typename Type>
- [[nodiscard]] meta_type resolve() noexcept {
- return resolve<Type>(locator<meta_ctx>::value_or());
- }
- /**
- * @brief Returns a range to use to visit all meta types.
- * @param ctx The context from which to search for meta types.
- * @return An iterable range to use to visit all meta types.
- */
- [[nodiscard]] inline meta_range<meta_type, typename decltype(internal::meta_context::value)::const_iterator> resolve(const meta_ctx &ctx) noexcept {
- const auto &context = internal::meta_context::from(ctx);
- return {{ctx, context.value.cbegin()}, {ctx, context.value.cend()}};
- }
- /**
- * @brief Returns a range to use to visit all meta types.
- * @return An iterable range to use to visit all meta types.
- */
- [[nodiscard]] inline meta_range<meta_type, typename decltype(internal::meta_context::value)::const_iterator> resolve() noexcept {
- return resolve(locator<meta_ctx>::value_or());
- }
- /**
- * @brief Returns the meta type associated with a given identifier, if any.
- * @param ctx The context from which to search for meta types.
- * @param id Unique identifier.
- * @return The meta type associated with the given identifier, if any.
- */
- [[nodiscard]] inline meta_type resolve(const meta_ctx &ctx, const id_type id) noexcept {
- for(auto &&curr: resolve(ctx)) {
- if(curr.second.id() == id) {
- return curr.second;
- }
- }
- return meta_type{};
- }
- /**
- * @brief Returns the meta type associated with a given identifier, if any.
- * @param id Unique identifier.
- * @return The meta type associated with the given identifier, if any.
- */
- [[nodiscard]] inline meta_type resolve(const id_type id) noexcept {
- return resolve(locator<meta_ctx>::value_or(), id);
- }
- /**
- * @brief Returns the meta type associated with a given type info object.
- * @param ctx The context from which to search for meta types.
- * @param info The type info object of the requested type.
- * @return The meta type associated with the given type info object, if any.
- */
- [[nodiscard]] inline meta_type resolve(const meta_ctx &ctx, const type_info &info) noexcept {
- const auto &context = internal::meta_context::from(ctx);
- const auto *elem = internal::try_resolve(context, info);
- return (elem != nullptr) ? meta_type{ctx, *elem} : meta_type{};
- }
- /**
- * @brief Returns the meta type associated with a given type info object.
- * @param info The type info object of the requested type.
- * @return The meta type associated with the given type info object, if any.
- */
- [[nodiscard]] inline meta_type resolve(const type_info &info) noexcept {
- return resolve(locator<meta_ctx>::value_or(), info);
- }
- } // namespace entt
- #endif
- // #include "meta/template.hpp"
- // IWYU pragma: always_keep
- #ifndef ENTT_META_TEMPLATE_HPP
- #define ENTT_META_TEMPLATE_HPP
- // #include "../core/type_traits.hpp"
- namespace entt {
- /*! @brief Utility class to disambiguate class templates. */
- template<template<typename...> class>
- struct meta_class_template_tag {};
- /**
- * @brief General purpose traits class for generating meta template information.
- * @tparam Clazz Type of class template.
- * @tparam Args Types of template arguments.
- */
- template<template<typename...> class Clazz, typename... Args>
- struct meta_template_traits<Clazz<Args...>> {
- /*! @brief Wrapped class template. */
- using class_type = meta_class_template_tag<Clazz>;
- /*! @brief List of template arguments. */
- using args_type = type_list<Args...>;
- };
- } // namespace entt
- #endif
- // #include "meta/type_traits.hpp"
- #ifndef ENTT_META_TYPE_TRAITS_HPP
- #define ENTT_META_TYPE_TRAITS_HPP
- #include <type_traits>
- #include <utility>
- namespace entt {
- /**
- * @brief Traits class template to be specialized to enable support for meta
- * template information.
- */
- template<typename>
- struct meta_template_traits;
- /**
- * @brief Traits class template to be specialized to enable support for meta
- * sequence containers.
- */
- template<typename>
- struct meta_sequence_container_traits;
- /**
- * @brief Traits class template to be specialized to enable support for meta
- * associative containers.
- */
- template<typename>
- struct meta_associative_container_traits;
- /**
- * @brief Provides the member constant `value` to true if a given type is a
- * pointer-like type from the point of view of the meta system, false otherwise.
- */
- template<typename, typename = void>
- struct is_meta_pointer_like: std::false_type {};
- /**
- * @brief Partial specialization to ensure that const pointer-like types are
- * also accepted.
- * @tparam Type Potentially pointer-like type.
- */
- template<typename Type>
- struct is_meta_pointer_like<const Type>: is_meta_pointer_like<Type> {};
- /**
- * @brief Helper variable template.
- * @tparam Type Potentially pointer-like type.
- */
- template<typename Type>
- inline constexpr auto is_meta_pointer_like_v = is_meta_pointer_like<Type>::value;
- } // namespace entt
- #endif
- // #include "meta/utility.hpp"
- #ifndef ENTT_META_UTILITY_HPP
- #define ENTT_META_UTILITY_HPP
- #include <cstddef>
- #include <functional>
- #include <type_traits>
- #include <utility>
- // #include "../core/type_traits.hpp"
- // #include "../locator/locator.hpp"
- // #include "meta.hpp"
- // #include "node.hpp"
- // #include "policy.hpp"
- namespace entt {
- /**
- * @brief Meta function descriptor traits.
- * @tparam Ret Function return type.
- * @tparam Args Function arguments.
- * @tparam Static Function staticness.
- * @tparam Const Function constness.
- */
- template<typename Ret, typename Args, bool Static, bool Const>
- struct meta_function_descriptor_traits {
- /*! @brief Meta function return type. */
- using return_type = Ret;
- /*! @brief Meta function arguments. */
- using args_type = Args;
- /*! @brief True if the meta function is static, false otherwise. */
- static constexpr bool is_static = Static;
- /*! @brief True if the meta function is const, false otherwise. */
- static constexpr bool is_const = Const;
- };
- /*! @brief Primary template isn't defined on purpose. */
- template<typename, typename>
- struct meta_function_descriptor;
- /**
- * @brief Meta function descriptor.
- * @tparam Type Reflected type to which the meta function is associated.
- * @tparam Ret Function return type.
- * @tparam Class Actual owner of the member function.
- * @tparam Args Function arguments.
- */
- template<typename Type, typename Ret, typename Class, typename... Args>
- struct meta_function_descriptor<Type, Ret (Class::*)(Args...) const>
- : meta_function_descriptor_traits<
- Ret,
- std::conditional_t<std::is_base_of_v<Class, Type>, type_list<Args...>, type_list<const Class &, Args...>>,
- !std::is_base_of_v<Class, Type>,
- true> {};
- /**
- * @brief Meta function descriptor.
- * @tparam Type Reflected type to which the meta function is associated.
- * @tparam Ret Function return type.
- * @tparam Class Actual owner of the member function.
- * @tparam Args Function arguments.
- */
- template<typename Type, typename Ret, typename Class, typename... Args>
- struct meta_function_descriptor<Type, Ret (Class::*)(Args...)>
- : meta_function_descriptor_traits<
- Ret,
- std::conditional_t<std::is_base_of_v<Class, Type>, type_list<Args...>, type_list<Class &, Args...>>,
- !std::is_base_of_v<Class, Type>,
- false> {};
- /**
- * @brief Meta function descriptor.
- * @tparam Type Reflected type to which the meta data is associated.
- * @tparam Class Actual owner of the data member.
- * @tparam Ret Data member type.
- */
- template<typename Type, typename Ret, typename Class>
- struct meta_function_descriptor<Type, Ret Class::*>
- : meta_function_descriptor_traits<
- Ret &,
- std::conditional_t<std::is_base_of_v<Class, Type>, type_list<>, type_list<Class &>>,
- !std::is_base_of_v<Class, Type>,
- false> {};
- /**
- * @brief Meta function descriptor.
- * @tparam Type Reflected type to which the meta function is associated.
- * @tparam Ret Function return type.
- * @tparam MaybeType First function argument.
- * @tparam Args Other function arguments.
- */
- template<typename Type, typename Ret, typename MaybeType, typename... Args>
- struct meta_function_descriptor<Type, Ret (*)(MaybeType, Args...)>
- : meta_function_descriptor_traits<
- Ret,
- std::conditional_t<
- std::is_same_v<std::remove_const_t<std::remove_reference_t<MaybeType>>, Type> || std::is_base_of_v<std::remove_const_t<std::remove_reference_t<MaybeType>>, Type>,
- type_list<Args...>,
- type_list<MaybeType, Args...>>,
- !(std::is_same_v<std::remove_const_t<std::remove_reference_t<MaybeType>>, Type> || std::is_base_of_v<std::remove_const_t<std::remove_reference_t<MaybeType>>, Type>),
- std::is_const_v<std::remove_reference_t<MaybeType>> && (std::is_same_v<std::remove_const_t<std::remove_reference_t<MaybeType>>, Type> || std::is_base_of_v<std::remove_const_t<std::remove_reference_t<MaybeType>>, Type>)> {};
- /**
- * @brief Meta function descriptor.
- * @tparam Type Reflected type to which the meta function is associated.
- * @tparam Ret Function return type.
- */
- template<typename Type, typename Ret>
- struct meta_function_descriptor<Type, Ret (*)()>
- : meta_function_descriptor_traits<
- Ret,
- type_list<>,
- true,
- false> {};
- /**
- * @brief Meta function helper.
- *
- * Converts a function type to be associated with a reflected type into its meta
- * function descriptor.
- *
- * @tparam Type Reflected type to which the meta function is associated.
- * @tparam Candidate The actual function to associate with the reflected type.
- */
- template<typename Type, typename Candidate>
- class meta_function_helper {
- template<typename Ret, typename... Args, typename Class>
- static constexpr meta_function_descriptor<Type, Ret (Class::*)(Args...) const> get_rid_of_noexcept(Ret (Class::*)(Args...) const);
- template<typename Ret, typename... Args, typename Class>
- static constexpr meta_function_descriptor<Type, Ret (Class::*)(Args...)> get_rid_of_noexcept(Ret (Class::*)(Args...));
- template<typename Ret, typename Class, typename = std::enable_if_t<std::is_member_object_pointer_v<Ret Class::*>>>
- static constexpr meta_function_descriptor<Type, Ret Class::*> get_rid_of_noexcept(Ret Class::*);
- template<typename Ret, typename... Args>
- static constexpr meta_function_descriptor<Type, Ret (*)(Args...)> get_rid_of_noexcept(Ret (*)(Args...));
- template<typename Class>
- static constexpr meta_function_descriptor<Class, decltype(&Class::operator())> get_rid_of_noexcept(Class);
- public:
- /*! @brief The meta function descriptor of the given function. */
- using type = decltype(get_rid_of_noexcept(std::declval<Candidate>()));
- };
- /**
- * @brief Helper type.
- * @tparam Type Reflected type to which the meta function is associated.
- * @tparam Candidate The actual function to associate with the reflected type.
- */
- template<typename Type, typename Candidate>
- using meta_function_helper_t = typename meta_function_helper<Type, Candidate>::type;
- /**
- * @brief Wraps a value depending on the given policy.
- *
- * This function always returns a wrapped value in the requested context.<br/>
- * Therefore, if the passed value is itself a wrapped object with a different
- * context, it undergoes a rebinding to the requested context.
- *
- * @tparam Policy Optional policy (no policy set by default).
- * @tparam Type Type of value to wrap.
- * @param ctx The context from which to search for meta types.
- * @param value Value to wrap.
- * @return A meta any containing the returned value, if any.
- */
- template<typename Policy = as_value_t, typename Type>
- [[nodiscard]] std::enable_if_t<is_meta_policy_v<Policy>, meta_any> meta_dispatch(const meta_ctx &ctx, [[maybe_unused]] Type &&value) {
- if constexpr(std::is_same_v<Policy, as_cref_t>) {
- static_assert(std::is_lvalue_reference_v<Type>, "Invalid type");
- return meta_any{ctx, std::in_place_type<const std::remove_reference_t<Type> &>, std::as_const(value)};
- } else if constexpr(std::is_same_v<Policy, as_ref_t> || (std::is_same_v<Policy, as_is_t> && std::is_lvalue_reference_v<Type>)) {
- return meta_any{ctx, std::in_place_type<Type>, value};
- } else if constexpr(std::is_same_v<Policy, as_void_t>) {
- return meta_any{ctx, std::in_place_type<void>};
- } else {
- return meta_any{ctx, std::forward<Type>(value)};
- }
- }
- /**
- * @brief Wraps a value depending on the given policy.
- * @tparam Policy Optional policy (no policy set by default).
- * @tparam Type Type of value to wrap.
- * @param value Value to wrap.
- * @return A meta any containing the returned value, if any.
- */
- template<typename Policy = as_value_t, typename Type>
- [[nodiscard]] std::enable_if_t<is_meta_policy_v<Policy>, meta_any> meta_dispatch(Type &&value) {
- return meta_dispatch<Policy, Type>(locator<meta_ctx>::value_or(), std::forward<Type>(value));
- }
- /*! @cond TURN_OFF_DOXYGEN */
- namespace internal {
- template<typename Policy, typename Candidate, typename... Args>
- [[nodiscard]] meta_any meta_invoke_with_args(const meta_ctx &ctx, Candidate &&candidate, Args &&...args) {
- if constexpr(std::is_void_v<decltype(std::invoke(std::forward<Candidate>(candidate), args...))>) {
- std::invoke(std::forward<Candidate>(candidate), args...);
- return meta_any{ctx, std::in_place_type<void>};
- } else {
- return meta_dispatch<Policy>(ctx, std::invoke(std::forward<Candidate>(candidate), args...));
- }
- }
- template<typename Type, typename Policy, typename Candidate, std::size_t... Index>
- [[nodiscard]] meta_any meta_invoke(meta_any &instance, Candidate &&candidate, [[maybe_unused]] meta_any *const args, std::index_sequence<Index...>) {
- using descriptor = meta_function_helper_t<Type, std::remove_reference_t<Candidate>>;
- // NOLINTBEGIN(cppcoreguidelines-pro-bounds-pointer-arithmetic) - waiting for C++20 (and std::span)
- if constexpr(std::is_invocable_v<std::remove_reference_t<Candidate>, const Type &, type_list_element_t<Index, typename descriptor::args_type>...>) {
- if(const auto *const clazz = instance.try_cast<const Type>(); clazz && ((args + Index)->allow_cast<type_list_element_t<Index, typename descriptor::args_type>>() && ...)) {
- return meta_invoke_with_args<Policy>(instance.context(), std::forward<Candidate>(candidate), *clazz, (args + Index)->cast<type_list_element_t<Index, typename descriptor::args_type>>()...);
- }
- } else if constexpr(std::is_invocable_v<std::remove_reference_t<Candidate>, Type &, type_list_element_t<Index, typename descriptor::args_type>...>) {
- if(auto *const clazz = instance.try_cast<Type>(); clazz && ((args + Index)->allow_cast<type_list_element_t<Index, typename descriptor::args_type>>() && ...)) {
- return meta_invoke_with_args<Policy>(instance.context(), std::forward<Candidate>(candidate), *clazz, (args + Index)->cast<type_list_element_t<Index, typename descriptor::args_type>>()...);
- }
- } else {
- if(((args + Index)->allow_cast<type_list_element_t<Index, typename descriptor::args_type>>() && ...)) {
- return meta_invoke_with_args<Policy>(instance.context(), std::forward<Candidate>(candidate), (args + Index)->cast<type_list_element_t<Index, typename descriptor::args_type>>()...);
- }
- }
- // NOLINTEND(cppcoreguidelines-pro-bounds-pointer-arithmetic)
- return meta_any{meta_ctx_arg, instance.context()};
- }
- template<typename Type, typename... Args, std::size_t... Index>
- [[nodiscard]] meta_any meta_construct(const meta_ctx &ctx, meta_any *const args, std::index_sequence<Index...>) {
- // NOLINTBEGIN(cppcoreguidelines-pro-bounds-pointer-arithmetic) - waiting for C++20 (and std::span)
- if(((args + Index)->allow_cast<Args>() && ...)) {
- return meta_any{ctx, std::in_place_type<Type>, (args + Index)->cast<Args>()...};
- }
- // NOLINTEND(cppcoreguidelines-pro-bounds-pointer-arithmetic)
- return meta_any{meta_ctx_arg, ctx};
- }
- } // namespace internal
- /*! @endcond */
- /**
- * @brief Returns the meta type of the i-th element of a list of arguments.
- * @tparam Type Type list of the actual types of arguments.
- * @param ctx The context from which to search for meta types.
- * @param index The index of the element for which to return the meta type.
- * @return The meta type of the i-th element of the list of arguments.
- */
- template<typename Type>
- [[nodiscard]] meta_type meta_arg(const meta_ctx &ctx, const std::size_t index) noexcept {
- const auto &context = internal::meta_context::from(ctx);
- return {ctx, internal::meta_arg_node(context, Type{}, index)};
- }
- /**
- * @brief Returns the meta type of the i-th element of a list of arguments.
- * @tparam Type Type list of the actual types of arguments.
- * @param index The index of the element for which to return the meta type.
- * @return The meta type of the i-th element of the list of arguments.
- */
- template<typename Type>
- [[nodiscard]] meta_type meta_arg(const std::size_t index) noexcept {
- return meta_arg<Type>(locator<meta_ctx>::value_or(), index);
- }
- /**
- * @brief Sets the value of a given variable.
- * @tparam Type Reflected type to which the variable is associated.
- * @tparam Data The actual variable to set.
- * @param instance An opaque instance of the underlying type, if required.
- * @param value Parameter to use to set the variable.
- * @return True in case of success, false otherwise.
- */
- template<typename Type, auto Data>
- [[nodiscard]] bool meta_setter([[maybe_unused]] meta_handle instance, [[maybe_unused]] meta_any value) {
- if constexpr(std::is_member_function_pointer_v<decltype(Data)> || std::is_function_v<std::remove_reference_t<std::remove_pointer_t<decltype(Data)>>>) {
- using descriptor = meta_function_helper_t<Type, decltype(Data)>;
- using data_type = type_list_element_t<descriptor::is_static, typename descriptor::args_type>;
- if(auto *const clazz = instance->try_cast<Type>(); clazz && value.allow_cast<data_type>()) {
- std::invoke(Data, *clazz, value.cast<data_type>());
- return true;
- }
- } else if constexpr(std::is_member_object_pointer_v<decltype(Data)>) {
- using data_type = std::remove_reference_t<typename meta_function_helper_t<Type, decltype(Data)>::return_type>;
- if constexpr(!std::is_array_v<data_type> && !std::is_const_v<data_type>) {
- if(auto *const clazz = instance->try_cast<Type>(); clazz && value.allow_cast<data_type>()) {
- std::invoke(Data, *clazz) = value.cast<data_type>();
- return true;
- }
- }
- } else if constexpr(std::is_pointer_v<decltype(Data)>) {
- using data_type = std::remove_reference_t<decltype(*Data)>;
- if constexpr(!std::is_array_v<data_type> && !std::is_const_v<data_type>) {
- if(value.allow_cast<data_type>()) {
- *Data = value.cast<data_type>();
- return true;
- }
- }
- }
- return false;
- }
- /**
- * @brief Gets the value of a given variable.
- * @tparam Type Reflected type to which the variable is associated.
- * @tparam Data The actual variable to get.
- * @tparam Policy Optional policy (no policy set by default).
- * @param instance An opaque instance of the underlying type, if required.
- * @return A meta any containing the value of the underlying variable.
- */
- template<typename Type, auto Data, typename Policy = as_value_t>
- [[nodiscard]] std::enable_if_t<is_meta_policy_v<Policy>, meta_any> meta_getter(meta_handle instance) {
- if constexpr(std::is_member_pointer_v<decltype(Data)> || std::is_function_v<std::remove_reference_t<std::remove_pointer_t<decltype(Data)>>>) {
- if constexpr(!std::is_array_v<std::remove_const_t<std::remove_reference_t<std::invoke_result_t<decltype(Data), Type &>>>>) {
- if constexpr(std::is_invocable_v<decltype(Data), Type &>) {
- if(auto *clazz = instance->try_cast<Type>(); clazz) {
- return meta_dispatch<Policy>(instance->context(), std::invoke(Data, *clazz));
- }
- }
- if constexpr(std::is_invocable_v<decltype(Data), const Type &>) {
- if(auto *fallback = instance->try_cast<const Type>(); fallback) {
- return meta_dispatch<Policy>(instance->context(), std::invoke(Data, *fallback));
- }
- }
- }
- return meta_any{meta_ctx_arg, instance->context()};
- } else if constexpr(std::is_pointer_v<decltype(Data)>) {
- if constexpr(std::is_array_v<std::remove_pointer_t<decltype(Data)>>) {
- return meta_any{meta_ctx_arg, instance->context()};
- } else {
- return meta_dispatch<Policy>(instance->context(), *Data);
- }
- } else {
- return meta_dispatch<Policy>(instance->context(), Data);
- }
- }
- /**
- * @brief Tries to _invoke_ an object given a list of erased parameters.
- * @tparam Type Reflected type to which the object to _invoke_ is associated.
- * @tparam Policy Optional policy (no policy set by default).
- * @tparam Candidate The type of the actual object to _invoke_.
- * @param instance An opaque instance of the underlying type, if required.
- * @param candidate The actual object to _invoke_.
- * @param args Parameters to use to _invoke_ the object.
- * @return A meta any containing the returned value, if any.
- */
- template<typename Type, typename Policy = as_value_t, typename Candidate>
- [[nodiscard]] std::enable_if_t<is_meta_policy_v<Policy>, meta_any> meta_invoke(meta_handle instance, Candidate &&candidate, meta_any *const args) {
- return internal::meta_invoke<Type, Policy>(*instance.operator->(), std::forward<Candidate>(candidate), args, std::make_index_sequence<meta_function_helper_t<Type, std::remove_reference_t<Candidate>>::args_type::size>{});
- }
- /**
- * @brief Tries to invoke a function given a list of erased parameters.
- * @tparam Type Reflected type to which the function is associated.
- * @tparam Candidate The actual function to invoke.
- * @tparam Policy Optional policy (no policy set by default).
- * @param instance An opaque instance of the underlying type, if required.
- * @param args Parameters to use to invoke the function.
- * @return A meta any containing the returned value, if any.
- */
- template<typename Type, auto Candidate, typename Policy = as_value_t>
- [[nodiscard]] std::enable_if_t<is_meta_policy_v<Policy>, meta_any> meta_invoke(meta_handle instance, meta_any *const args) {
- return internal::meta_invoke<Type, Policy>(*instance.operator->(), Candidate, args, std::make_index_sequence<meta_function_helper_t<Type, std::remove_reference_t<decltype(Candidate)>>::args_type::size>{});
- }
- /**
- * @brief Tries to construct an instance given a list of erased parameters.
- *
- * @warning
- * The context provided is used only for the return type.<br/>
- * It's up to the caller to bind the arguments to the right context(s).
- *
- * @tparam Type Actual type of the instance to construct.
- * @tparam Args Types of arguments expected.
- * @param ctx The context from which to search for meta types.
- * @param args Parameters to use to construct the instance.
- * @return A meta any containing the new instance, if any.
- */
- template<typename Type, typename... Args>
- [[nodiscard]] meta_any meta_construct(const meta_ctx &ctx, meta_any *const args) {
- return internal::meta_construct<Type, Args...>(ctx, args, std::index_sequence_for<Args...>{});
- }
- /**
- * @brief Tries to construct an instance given a list of erased parameters.
- * @tparam Type Actual type of the instance to construct.
- * @tparam Args Types of arguments expected.
- * @param args Parameters to use to construct the instance.
- * @return A meta any containing the new instance, if any.
- */
- template<typename Type, typename... Args>
- [[nodiscard]] meta_any meta_construct(meta_any *const args) {
- return meta_construct<Type, Args...>(locator<meta_ctx>::value_or(), args);
- }
- /**
- * @brief Tries to construct an instance given a list of erased parameters.
- *
- * @warning
- * The context provided is used only for the return type.<br/>
- * It's up to the caller to bind the arguments to the right context(s).
- *
- * @tparam Type Reflected type to which the object to _invoke_ is associated.
- * @tparam Policy Optional policy (no policy set by default).
- * @tparam Candidate The type of the actual object to _invoke_.
- * @param ctx The context from which to search for meta types.
- * @param candidate The actual object to _invoke_.
- * @param args Parameters to use to _invoke_ the object.
- * @return A meta any containing the returned value, if any.
- */
- template<typename Type, typename Policy = as_value_t, typename Candidate>
- [[nodiscard]] meta_any meta_construct(const meta_ctx &ctx, Candidate &&candidate, meta_any *const args) {
- if constexpr(meta_function_helper_t<Type, Candidate>::is_static || std::is_class_v<std::remove_const_t<std::remove_reference_t<Candidate>>>) {
- meta_any placeholder{meta_ctx_arg, ctx};
- return internal::meta_invoke<Type, Policy>(placeholder, std::forward<Candidate>(candidate), args, std::make_index_sequence<meta_function_helper_t<Type, std::remove_reference_t<Candidate>>::args_type::size>{});
- } else {
- // NOLINTNEXTLINE(cppcoreguidelines-pro-bounds-pointer-arithmetic) - waiting for C++20 (and std::span)
- return internal::meta_invoke<Type, Policy>(*args, std::forward<Candidate>(candidate), args + 1u, std::make_index_sequence<meta_function_helper_t<Type, std::remove_reference_t<Candidate>>::args_type::size>{});
- }
- }
- /**
- * @brief Tries to construct an instance given a list of erased parameters.
- * @tparam Type Reflected type to which the object to _invoke_ is associated.
- * @tparam Policy Optional policy (no policy set by default).
- * @tparam Candidate The type of the actual object to _invoke_.
- * @param candidate The actual object to _invoke_.
- * @param args Parameters to use to _invoke_ the object.
- * @return A meta any containing the returned value, if any.
- */
- template<typename Type, typename Policy = as_value_t, typename Candidate>
- [[nodiscard]] std::enable_if_t<is_meta_policy_v<Policy>, meta_any> meta_construct(Candidate &&candidate, meta_any *const args) {
- return meta_construct<Type, Policy>(locator<meta_ctx>::value_or(), std::forward<Candidate>(candidate), args);
- }
- /**
- * @brief Tries to construct an instance given a list of erased parameters.
- *
- * @warning
- * The context provided is used only for the return type.<br/>
- * It's up to the caller to bind the arguments to the right context(s).
- *
- * @tparam Type Reflected type to which the function is associated.
- * @tparam Candidate The actual function to invoke.
- * @tparam Policy Optional policy (no policy set by default).
- * @param ctx The context from which to search for meta types.
- * @param args Parameters to use to invoke the function.
- * @return A meta any containing the returned value, if any.
- */
- template<typename Type, auto Candidate, typename Policy = as_value_t>
- [[nodiscard]] std::enable_if_t<is_meta_policy_v<Policy>, meta_any> meta_construct(const meta_ctx &ctx, meta_any *const args) {
- return meta_construct<Type, Policy>(ctx, Candidate, args);
- }
- /**
- * @brief Tries to construct an instance given a list of erased parameters.
- * @tparam Type Reflected type to which the function is associated.
- * @tparam Candidate The actual function to invoke.
- * @tparam Policy Optional policy (no policy set by default).
- * @param args Parameters to use to invoke the function.
- * @return A meta any containing the returned value, if any.
- */
- template<typename Type, auto Candidate, typename Policy = as_value_t>
- [[nodiscard]] std::enable_if_t<is_meta_policy_v<Policy>, meta_any> meta_construct(meta_any *const args) {
- return meta_construct<Type, Candidate, Policy>(locator<meta_ctx>::value_or(), args);
- }
- } // namespace entt
- #endif
- // #include "poly/poly.hpp"
- #ifndef ENTT_POLY_POLY_HPP
- #define ENTT_POLY_POLY_HPP
- #include <cstddef>
- #include <functional>
- #include <tuple>
- #include <type_traits>
- #include <utility>
- // #include "../core/any.hpp"
- #ifndef ENTT_CORE_ANY_HPP
- #define ENTT_CORE_ANY_HPP
- #include <cstddef>
- #include <memory>
- #include <type_traits>
- #include <utility>
- // #include "../config/config.h"
- #ifndef ENTT_CONFIG_CONFIG_H
- #define ENTT_CONFIG_CONFIG_H
- // #include "version.h"
- #ifndef ENTT_CONFIG_VERSION_H
- #define ENTT_CONFIG_VERSION_H
- // #include "macro.h"
- #ifndef ENTT_CONFIG_MACRO_H
- #define ENTT_CONFIG_MACRO_H
- // NOLINTBEGIN(cppcoreguidelines-macro-usage)
- #define ENTT_STR(arg) #arg
- #define ENTT_XSTR(arg) ENTT_STR(arg)
- // NOLINTEND(cppcoreguidelines-macro-usage)
- #endif
- // NOLINTBEGIN(cppcoreguidelines-macro-*,modernize-macro-*)
- #define ENTT_VERSION_MAJOR 3
- #define ENTT_VERSION_MINOR 16
- #define ENTT_VERSION_PATCH 0
- #define ENTT_VERSION \
- ENTT_XSTR(ENTT_VERSION_MAJOR) \
- "." ENTT_XSTR(ENTT_VERSION_MINOR) "." ENTT_XSTR(ENTT_VERSION_PATCH)
- // NOLINTEND(cppcoreguidelines-macro-*,modernize-macro-*)
- #endif
- // NOLINTBEGIN(cppcoreguidelines-macro-usage)
- #if defined(__cpp_exceptions) && !defined(ENTT_NOEXCEPTION)
- # define ENTT_CONSTEXPR
- # define ENTT_THROW throw
- # define ENTT_TRY try
- # define ENTT_CATCH catch(...)
- #else
- # define ENTT_CONSTEXPR constexpr // use only with throwing functions (waiting for C++20)
- # define ENTT_THROW
- # define ENTT_TRY if(true)
- # define ENTT_CATCH if(false)
- #endif
- #if __has_include(<version>)
- # include <version>
- #
- # if defined(__cpp_consteval)
- # define ENTT_CONSTEVAL consteval
- # endif
- #endif
- #ifndef ENTT_CONSTEVAL
- # define ENTT_CONSTEVAL constexpr
- #endif
- #ifdef ENTT_USE_ATOMIC
- # include <atomic>
- # define ENTT_MAYBE_ATOMIC(Type) std::atomic<Type>
- #else
- # define ENTT_MAYBE_ATOMIC(Type) Type
- #endif
- #ifndef ENTT_ID_TYPE
- # include <cstdint>
- # define ENTT_ID_TYPE std::uint32_t
- #else
- # include <cstdint> // provides coverage for types in the std namespace
- #endif
- #ifndef ENTT_SPARSE_PAGE
- # define ENTT_SPARSE_PAGE 4096
- #endif
- #ifndef ENTT_PACKED_PAGE
- # define ENTT_PACKED_PAGE 1024
- #endif
- #ifdef ENTT_DISABLE_ASSERT
- # undef ENTT_ASSERT
- # define ENTT_ASSERT(condition, msg) (void(0))
- #elif !defined ENTT_ASSERT
- # include <cassert>
- # define ENTT_ASSERT(condition, msg) assert(((condition) && (msg)))
- #endif
- #ifdef ENTT_DISABLE_ASSERT
- # undef ENTT_ASSERT_CONSTEXPR
- # define ENTT_ASSERT_CONSTEXPR(condition, msg) (void(0))
- #elif !defined ENTT_ASSERT_CONSTEXPR
- # define ENTT_ASSERT_CONSTEXPR(condition, msg) ENTT_ASSERT(condition, msg)
- #endif
- #define ENTT_FAIL(msg) ENTT_ASSERT(false, msg);
- #ifdef ENTT_NO_ETO
- # define ENTT_ETO_TYPE(Type) void
- #else
- # define ENTT_ETO_TYPE(Type) Type
- #endif
- #ifdef ENTT_NO_MIXIN
- # define ENTT_STORAGE(Mixin, ...) __VA_ARGS__
- #else
- # define ENTT_STORAGE(Mixin, ...) Mixin<__VA_ARGS__>
- #endif
- #ifdef ENTT_STANDARD_CPP
- # define ENTT_NONSTD false
- #else
- # define ENTT_NONSTD true
- # if defined __clang__ || defined __GNUC__
- # define ENTT_PRETTY_FUNCTION __PRETTY_FUNCTION__
- # define ENTT_PRETTY_FUNCTION_PREFIX '='
- # define ENTT_PRETTY_FUNCTION_SUFFIX ']'
- # elif defined _MSC_VER
- # define ENTT_PRETTY_FUNCTION __FUNCSIG__
- # define ENTT_PRETTY_FUNCTION_PREFIX '<'
- # define ENTT_PRETTY_FUNCTION_SUFFIX '>'
- # endif
- #endif
- #ifndef ENTT_EXPORT
- # if defined _WIN32 || defined __CYGWIN__ || defined _MSC_VER
- # define ENTT_EXPORT __declspec(dllexport)
- # define ENTT_IMPORT __declspec(dllimport)
- # define ENTT_HIDDEN
- # elif defined __GNUC__ && __GNUC__ >= 4
- # define ENTT_EXPORT __attribute__((visibility("default")))
- # define ENTT_IMPORT __attribute__((visibility("default")))
- # define ENTT_HIDDEN __attribute__((visibility("hidden")))
- # else /* Unsupported compiler */
- # define ENTT_EXPORT
- # define ENTT_IMPORT
- # define ENTT_HIDDEN
- # endif
- #endif
- #ifndef ENTT_API
- # if defined ENTT_API_EXPORT
- # define ENTT_API ENTT_EXPORT
- # elif defined ENTT_API_IMPORT
- # define ENTT_API ENTT_IMPORT
- # else /* No API */
- # define ENTT_API
- # endif
- #endif
- #if defined _MSC_VER
- # pragma detect_mismatch("entt.version", ENTT_VERSION)
- # pragma detect_mismatch("entt.noexcept", ENTT_XSTR(ENTT_TRY))
- # pragma detect_mismatch("entt.id", ENTT_XSTR(ENTT_ID_TYPE))
- # pragma detect_mismatch("entt.nonstd", ENTT_XSTR(ENTT_NONSTD))
- #endif
- // NOLINTEND(cppcoreguidelines-macro-usage)
- #endif
- // #include "fwd.hpp"
- #ifndef ENTT_CORE_FWD_HPP
- #define ENTT_CORE_FWD_HPP
- #include <cstddef>
- #include <cstdint>
- // #include "../config/config.h"
- namespace entt {
- /*! @brief Possible modes of an any object. */
- enum class any_policy : std::uint8_t {
- /*! @brief Default mode, no element available. */
- empty,
- /*! @brief Owning mode, dynamically allocated element. */
- dynamic,
- /*! @brief Owning mode, embedded element. */
- embedded,
- /*! @brief Aliasing mode, non-const reference. */
- ref,
- /*! @brief Const aliasing mode, const reference. */
- cref
- };
- // NOLINTNEXTLINE(cppcoreguidelines-avoid-c-arrays, modernize-avoid-c-arrays)
- template<std::size_t Len = sizeof(double[2]), std::size_t = alignof(double[2])>
- class basic_any;
- /*! @brief Alias declaration for type identifiers. */
- using id_type = ENTT_ID_TYPE;
- /*! @brief Alias declaration for the most common use case. */
- using any = basic_any<>;
- template<typename, typename>
- class compressed_pair;
- template<typename>
- class basic_hashed_string;
- /*! @brief Aliases for common character types. */
- using hashed_string = basic_hashed_string<char>;
- /*! @brief Aliases for common character types. */
- using hashed_wstring = basic_hashed_string<wchar_t>;
- // NOLINTNEXTLINE(bugprone-forward-declaration-namespace)
- struct type_info;
- } // namespace entt
- #endif
- // #include "type_info.hpp"
- #ifndef ENTT_CORE_TYPE_INFO_HPP
- #define ENTT_CORE_TYPE_INFO_HPP
- #include <string_view>
- #include <type_traits>
- #include <utility>
- // #include "../config/config.h"
- // #include "fwd.hpp"
- // #include "hashed_string.hpp"
- #ifndef ENTT_CORE_HASHED_STRING_HPP
- #define ENTT_CORE_HASHED_STRING_HPP
- #include <cstddef>
- #include <cstdint>
- // #include "fwd.hpp"
- namespace entt {
- /*! @cond TURN_OFF_DOXYGEN */
- namespace internal {
- template<typename = id_type>
- struct fnv_1a_params;
- template<>
- struct fnv_1a_params<std::uint32_t> {
- static constexpr auto offset = 2166136261;
- static constexpr auto prime = 16777619;
- };
- template<>
- struct fnv_1a_params<std::uint64_t> {
- static constexpr auto offset = 14695981039346656037ull;
- static constexpr auto prime = 1099511628211ull;
- };
- template<typename Char>
- struct basic_hashed_string {
- using value_type = Char;
- using size_type = std::size_t;
- using hash_type = id_type;
- const value_type *repr{};
- hash_type hash{fnv_1a_params<>::offset};
- size_type length{};
- };
- } // namespace internal
- /*! @endcond */
- /**
- * @brief Zero overhead unique identifier.
- *
- * A hashed string is a compile-time tool that allows users to use
- * human-readable identifiers in the codebase while using their numeric
- * counterparts at runtime.<br/>
- * Because of that, a hashed string can also be used in constant expressions if
- * required.
- *
- * @warning
- * This class doesn't take ownership of user-supplied strings nor does it make a
- * copy of them.
- *
- * @tparam Char Character type.
- */
- template<typename Char>
- class basic_hashed_string: internal::basic_hashed_string<Char> {
- using base_type = internal::basic_hashed_string<Char>;
- using params = internal::fnv_1a_params<>;
- struct const_wrapper {
- // non-explicit constructor on purpose
- constexpr const_wrapper(const typename base_type::value_type *str) noexcept
- : repr{str} {}
- const typename base_type::value_type *repr;
- };
- public:
- /*! @brief Character type. */
- using value_type = typename base_type::value_type;
- /*! @brief Unsigned integer type. */
- using size_type = typename base_type::size_type;
- /*! @brief Unsigned integer type. */
- using hash_type = typename base_type::hash_type;
- /**
- * @brief Returns directly the numeric representation of a string view.
- * @param str Human-readable identifier.
- * @param len Length of the string to hash.
- * @return The numeric representation of the string.
- */
- [[nodiscard]] static constexpr hash_type value(const value_type *str, const size_type len) noexcept {
- return basic_hashed_string{str, len};
- }
- /**
- * @brief Returns directly the numeric representation of a string.
- * @tparam N Number of characters of the identifier.
- * @param str Human-readable identifier.
- * @return The numeric representation of the string.
- */
- template<std::size_t N>
- // NOLINTNEXTLINE(cppcoreguidelines-avoid-c-arrays, modernize-avoid-c-arrays)
- [[nodiscard]] static ENTT_CONSTEVAL hash_type value(const value_type (&str)[N]) noexcept {
- return basic_hashed_string{str};
- }
- /**
- * @brief Returns directly the numeric representation of a string.
- * @param wrapper Helps achieving the purpose by relying on overloading.
- * @return The numeric representation of the string.
- */
- [[nodiscard]] static constexpr hash_type value(const_wrapper wrapper) noexcept {
- return basic_hashed_string{wrapper};
- }
- /*! @brief Constructs an empty hashed string. */
- constexpr basic_hashed_string() noexcept
- : basic_hashed_string{nullptr, 0u} {}
- /**
- * @brief Constructs a hashed string from a string view.
- * @param str Human-readable identifier.
- * @param len Length of the string to hash.
- */
- constexpr basic_hashed_string(const value_type *str, const size_type len) noexcept
- // NOLINTNEXTLINE(cppcoreguidelines-pro-bounds-array-to-pointer-decay)
- : base_type{str} {
- // NOLINTBEGIN(cppcoreguidelines-pro-bounds-pointer-arithmetic)
- for(; base_type::length < len; ++base_type::length) {
- base_type::hash = (base_type::hash ^ static_cast<id_type>(str[base_type::length])) * params::prime;
- }
- // NOLINTEND(cppcoreguidelines-pro-bounds-pointer-arithmetic)
- }
- /**
- * @brief Constructs a hashed string from an array of const characters.
- * @tparam N Number of characters of the identifier.
- * @param str Human-readable identifier.
- */
- template<std::size_t N>
- // NOLINTNEXTLINE(cppcoreguidelines-avoid-c-arrays, modernize-avoid-c-arrays)
- ENTT_CONSTEVAL basic_hashed_string(const value_type (&str)[N]) noexcept
- // NOLINTNEXTLINE(cppcoreguidelines-pro-bounds-array-to-pointer-decay)
- : base_type{str} {
- for(; str[base_type::length]; ++base_type::length) {
- base_type::hash = (base_type::hash ^ static_cast<id_type>(str[base_type::length])) * params::prime;
- }
- }
- /**
- * @brief Explicit constructor on purpose to avoid constructing a hashed
- * string directly from a `const value_type *`.
- *
- * @warning
- * The lifetime of the string is not extended nor is it copied.
- *
- * @param wrapper Helps achieving the purpose by relying on overloading.
- */
- explicit constexpr basic_hashed_string(const_wrapper wrapper) noexcept
- : base_type{wrapper.repr} {
- // NOLINTBEGIN(cppcoreguidelines-pro-bounds-pointer-arithmetic)
- for(; wrapper.repr[base_type::length]; ++base_type::length) {
- base_type::hash = (base_type::hash ^ static_cast<id_type>(wrapper.repr[base_type::length])) * params::prime;
- }
- // NOLINTEND(cppcoreguidelines-pro-bounds-pointer-arithmetic)
- }
- /**
- * @brief Returns the size of a hashed string.
- * @return The size of the hashed string.
- */
- [[nodiscard]] constexpr size_type size() const noexcept {
- return base_type::length;
- }
- /**
- * @brief Returns the human-readable representation of a hashed string.
- * @return The string used to initialize the hashed string.
- */
- [[nodiscard]] constexpr const value_type *data() const noexcept {
- return base_type::repr;
- }
- /**
- * @brief Returns the numeric representation of a hashed string.
- * @return The numeric representation of the hashed string.
- */
- [[nodiscard]] constexpr hash_type value() const noexcept {
- return base_type::hash;
- }
- /*! @copydoc data */
- [[nodiscard]] explicit constexpr operator const value_type *() const noexcept {
- return data();
- }
- /**
- * @brief Returns the numeric representation of a hashed string.
- * @return The numeric representation of the hashed string.
- */
- [[nodiscard]] constexpr operator hash_type() const noexcept {
- return value();
- }
- };
- /**
- * @brief Deduction guide.
- * @tparam Char Character type.
- * @param str Human-readable identifier.
- * @param len Length of the string to hash.
- */
- template<typename Char>
- basic_hashed_string(const Char *str, std::size_t len) -> basic_hashed_string<Char>;
- /**
- * @brief Deduction guide.
- * @tparam Char Character type.
- * @tparam N Number of characters of the identifier.
- * @param str Human-readable identifier.
- */
- template<typename Char, std::size_t N>
- // NOLINTNEXTLINE(cppcoreguidelines-avoid-c-arrays, modernize-avoid-c-arrays)
- basic_hashed_string(const Char (&str)[N]) -> basic_hashed_string<Char>;
- /**
- * @brief Compares two hashed strings.
- * @tparam Char Character type.
- * @param lhs A valid hashed string.
- * @param rhs A valid hashed string.
- * @return True if the two hashed strings are identical, false otherwise.
- */
- template<typename Char>
- [[nodiscard]] constexpr bool operator==(const basic_hashed_string<Char> &lhs, const basic_hashed_string<Char> &rhs) noexcept {
- return lhs.value() == rhs.value();
- }
- /**
- * @brief Compares two hashed strings.
- * @tparam Char Character type.
- * @param lhs A valid hashed string.
- * @param rhs A valid hashed string.
- * @return True if the two hashed strings differ, false otherwise.
- */
- template<typename Char>
- [[nodiscard]] constexpr bool operator!=(const basic_hashed_string<Char> &lhs, const basic_hashed_string<Char> &rhs) noexcept {
- return !(lhs == rhs);
- }
- /**
- * @brief Compares two hashed strings.
- * @tparam Char Character type.
- * @param lhs A valid hashed string.
- * @param rhs A valid hashed string.
- * @return True if the first element is less than the second, false otherwise.
- */
- template<typename Char>
- [[nodiscard]] constexpr bool operator<(const basic_hashed_string<Char> &lhs, const basic_hashed_string<Char> &rhs) noexcept {
- return lhs.value() < rhs.value();
- }
- /**
- * @brief Compares two hashed strings.
- * @tparam Char Character type.
- * @param lhs A valid hashed string.
- * @param rhs A valid hashed string.
- * @return True if the first element is less than or equal to the second, false
- * otherwise.
- */
- template<typename Char>
- [[nodiscard]] constexpr bool operator<=(const basic_hashed_string<Char> &lhs, const basic_hashed_string<Char> &rhs) noexcept {
- return !(rhs < lhs);
- }
- /**
- * @brief Compares two hashed strings.
- * @tparam Char Character type.
- * @param lhs A valid hashed string.
- * @param rhs A valid hashed string.
- * @return True if the first element is greater than the second, false
- * otherwise.
- */
- template<typename Char>
- [[nodiscard]] constexpr bool operator>(const basic_hashed_string<Char> &lhs, const basic_hashed_string<Char> &rhs) noexcept {
- return rhs < lhs;
- }
- /**
- * @brief Compares two hashed strings.
- * @tparam Char Character type.
- * @param lhs A valid hashed string.
- * @param rhs A valid hashed string.
- * @return True if the first element is greater than or equal to the second,
- * false otherwise.
- */
- template<typename Char>
- [[nodiscard]] constexpr bool operator>=(const basic_hashed_string<Char> &lhs, const basic_hashed_string<Char> &rhs) noexcept {
- return !(lhs < rhs);
- }
- inline namespace literals {
- /**
- * @brief User defined literal for hashed strings.
- * @param str The literal without its suffix.
- * @return A properly initialized hashed string.
- */
- [[nodiscard]] ENTT_CONSTEVAL hashed_string operator""_hs(const char *str, std::size_t) noexcept {
- return hashed_string{str};
- }
- /**
- * @brief User defined literal for hashed wstrings.
- * @param str The literal without its suffix.
- * @return A properly initialized hashed wstring.
- */
- [[nodiscard]] ENTT_CONSTEVAL hashed_wstring operator""_hws(const wchar_t *str, std::size_t) noexcept {
- return hashed_wstring{str};
- }
- } // namespace literals
- } // namespace entt
- #endif
- namespace entt {
- /*! @cond TURN_OFF_DOXYGEN */
- namespace internal {
- struct ENTT_API type_index final {
- [[nodiscard]] static id_type next() noexcept {
- static ENTT_MAYBE_ATOMIC(id_type) value{};
- return value++;
- }
- };
- template<typename Type>
- [[nodiscard]] constexpr const char *pretty_function() noexcept {
- #if defined ENTT_PRETTY_FUNCTION
- return static_cast<const char *>(ENTT_PRETTY_FUNCTION);
- #else
- return "";
- #endif
- }
- template<typename Type>
- [[nodiscard]] constexpr auto stripped_type_name() noexcept {
- #if defined ENTT_PRETTY_FUNCTION
- const std::string_view full_name{pretty_function<Type>()};
- auto first = full_name.find_first_not_of(' ', full_name.find_first_of(ENTT_PRETTY_FUNCTION_PREFIX) + 1);
- auto value = full_name.substr(first, full_name.find_last_of(ENTT_PRETTY_FUNCTION_SUFFIX) - first);
- return value;
- #else
- return std::string_view{};
- #endif
- }
- template<typename Type, auto = stripped_type_name<Type>().find_first_of('.')>
- [[nodiscard]] constexpr std::string_view type_name(int) noexcept {
- constexpr auto value = stripped_type_name<Type>();
- return value;
- }
- template<typename Type>
- [[nodiscard]] std::string_view type_name(char) noexcept {
- static const auto value = stripped_type_name<Type>();
- return value;
- }
- template<typename Type, auto = stripped_type_name<Type>().find_first_of('.')>
- [[nodiscard]] constexpr id_type type_hash(int) noexcept {
- constexpr auto stripped = stripped_type_name<Type>();
- constexpr auto value = hashed_string::value(stripped.data(), stripped.size());
- return value;
- }
- template<typename Type>
- [[nodiscard]] id_type type_hash(char) noexcept {
- static const auto value = [](const auto stripped) {
- return hashed_string::value(stripped.data(), stripped.size());
- }(stripped_type_name<Type>());
- return value;
- }
- } // namespace internal
- /*! @endcond */
- /**
- * @brief Type sequential identifier.
- * @tparam Type Type for which to generate a sequential identifier.
- */
- template<typename Type, typename = void>
- struct ENTT_API type_index final {
- /**
- * @brief Returns the sequential identifier of a given type.
- * @return The sequential identifier of a given type.
- */
- [[nodiscard]] static id_type value() noexcept {
- static const id_type value = internal::type_index::next();
- return value;
- }
- /*! @copydoc value */
- [[nodiscard]] constexpr operator id_type() const noexcept {
- return value();
- }
- };
- /**
- * @brief Type hash.
- * @tparam Type Type for which to generate a hash value.
- */
- template<typename Type, typename = void>
- struct type_hash final {
- /**
- * @brief Returns the numeric representation of a given type.
- * @return The numeric representation of the given type.
- */
- #if defined ENTT_PRETTY_FUNCTION
- [[nodiscard]] static constexpr id_type value() noexcept {
- return internal::type_hash<Type>(0);
- #else
- [[nodiscard]] static constexpr id_type value() noexcept {
- return type_index<Type>::value();
- #endif
- }
- /*! @copydoc value */
- [[nodiscard]] constexpr operator id_type() const noexcept {
- return value();
- }
- };
- /**
- * @brief Type name.
- * @tparam Type Type for which to generate a name.
- */
- template<typename Type, typename = void>
- struct type_name final {
- /**
- * @brief Returns the name of a given type.
- * @return The name of the given type.
- */
- [[nodiscard]] static constexpr std::string_view value() noexcept {
- return internal::type_name<Type>(0);
- }
- /*! @copydoc value */
- [[nodiscard]] constexpr operator std::string_view() const noexcept {
- return value();
- }
- };
- /*! @brief Implementation specific information about a type. */
- struct type_info final {
- /**
- * @brief Constructs a type info object for a given type.
- * @tparam Type Type for which to construct a type info object.
- */
- template<typename Type>
- // NOLINTBEGIN(modernize-use-transparent-functors)
- constexpr type_info(std::in_place_type_t<Type>) noexcept
- : seq{type_index<std::remove_const_t<std::remove_reference_t<Type>>>::value()},
- identifier{type_hash<std::remove_const_t<std::remove_reference_t<Type>>>::value()},
- alias{type_name<std::remove_const_t<std::remove_reference_t<Type>>>::value()} {}
- // NOLINTEND(modernize-use-transparent-functors)
- /**
- * @brief Type index.
- * @return Type index.
- */
- [[nodiscard]] constexpr id_type index() const noexcept {
- return seq;
- }
- /**
- * @brief Type hash.
- * @return Type hash.
- */
- [[nodiscard]] constexpr id_type hash() const noexcept {
- return identifier;
- }
- /**
- * @brief Type name.
- * @return Type name.
- */
- [[nodiscard]] constexpr std::string_view name() const noexcept {
- return alias;
- }
- private:
- id_type seq;
- id_type identifier;
- std::string_view alias;
- };
- /**
- * @brief Compares the contents of two type info objects.
- * @param lhs A type info object.
- * @param rhs A type info object.
- * @return True if the two type info objects are identical, false otherwise.
- */
- [[nodiscard]] constexpr bool operator==(const type_info &lhs, const type_info &rhs) noexcept {
- return lhs.hash() == rhs.hash();
- }
- /**
- * @brief Compares the contents of two type info objects.
- * @param lhs A type info object.
- * @param rhs A type info object.
- * @return True if the two type info objects differ, false otherwise.
- */
- [[nodiscard]] constexpr bool operator!=(const type_info &lhs, const type_info &rhs) noexcept {
- return !(lhs == rhs);
- }
- /**
- * @brief Compares two type info objects.
- * @param lhs A valid type info object.
- * @param rhs A valid type info object.
- * @return True if the first element is less than the second, false otherwise.
- */
- [[nodiscard]] constexpr bool operator<(const type_info &lhs, const type_info &rhs) noexcept {
- return lhs.index() < rhs.index();
- }
- /**
- * @brief Compares two type info objects.
- * @param lhs A valid type info object.
- * @param rhs A valid type info object.
- * @return True if the first element is less than or equal to the second, false
- * otherwise.
- */
- [[nodiscard]] constexpr bool operator<=(const type_info &lhs, const type_info &rhs) noexcept {
- return !(rhs < lhs);
- }
- /**
- * @brief Compares two type info objects.
- * @param lhs A valid type info object.
- * @param rhs A valid type info object.
- * @return True if the first element is greater than the second, false
- * otherwise.
- */
- [[nodiscard]] constexpr bool operator>(const type_info &lhs, const type_info &rhs) noexcept {
- return rhs < lhs;
- }
- /**
- * @brief Compares two type info objects.
- * @param lhs A valid type info object.
- * @param rhs A valid type info object.
- * @return True if the first element is greater than or equal to the second,
- * false otherwise.
- */
- [[nodiscard]] constexpr bool operator>=(const type_info &lhs, const type_info &rhs) noexcept {
- return !(lhs < rhs);
- }
- /**
- * @brief Returns the type info object associated to a given type.
- *
- * The returned element refers to an object with static storage duration.<br/>
- * The type doesn't need to be a complete type. If the type is a reference, the
- * result refers to the referenced type. In all cases, top-level cv-qualifiers
- * are ignored.
- *
- * @tparam Type Type for which to generate a type info object.
- * @return A reference to a properly initialized type info object.
- */
- template<typename Type>
- [[nodiscard]] const type_info &type_id() noexcept {
- if constexpr(std::is_same_v<Type, std::remove_const_t<std::remove_reference_t<Type>>>) {
- static const type_info instance{std::in_place_type<Type>};
- return instance;
- } else {
- return type_id<std::remove_const_t<std::remove_reference_t<Type>>>();
- }
- }
- /*! @copydoc type_id */
- template<typename Type>
- // NOLINTNEXTLINE(cppcoreguidelines-missing-std-forward)
- [[nodiscard]] const type_info &type_id(Type &&) noexcept {
- return type_id<std::remove_const_t<std::remove_reference_t<Type>>>();
- }
- } // namespace entt
- #endif
- // #include "type_traits.hpp"
- #ifndef ENTT_CORE_TYPE_TRAITS_HPP
- #define ENTT_CORE_TYPE_TRAITS_HPP
- #include <cstddef>
- #include <iterator>
- #include <tuple>
- #include <type_traits>
- #include <utility>
- // #include "../config/config.h"
- // #include "fwd.hpp"
- namespace entt {
- /**
- * @brief Utility class to disambiguate overloaded functions.
- * @tparam N Number of choices available.
- */
- template<std::size_t N>
- struct choice_t
- // unfortunately, doxygen cannot parse such a construct
- : /*! @cond TURN_OFF_DOXYGEN */ choice_t<N - 1> /*! @endcond */
- {};
- /*! @copybrief choice_t */
- template<>
- struct choice_t<0> {};
- /**
- * @brief Variable template for the choice trick.
- * @tparam N Number of choices available.
- */
- template<std::size_t N>
- inline constexpr choice_t<N> choice{};
- /**
- * @brief Identity type trait.
- *
- * Useful to establish non-deduced contexts in template argument deduction
- * (waiting for C++20) or to provide types through function arguments.
- *
- * @tparam Type A type.
- */
- template<typename Type>
- struct type_identity {
- /*! @brief Identity type. */
- using type = Type;
- };
- /**
- * @brief Helper type.
- * @tparam Type A type.
- */
- template<typename Type>
- using type_identity_t = typename type_identity<Type>::type;
- /**
- * @brief A type-only `sizeof` wrapper that returns 0 where `sizeof` complains.
- * @tparam Type The type of which to return the size.
- */
- template<typename Type, typename = void>
- struct size_of: std::integral_constant<std::size_t, 0u> {};
- /*! @copydoc size_of */
- template<typename Type>
- struct size_of<Type, std::void_t<decltype(sizeof(Type))>>
- // NOLINTNEXTLINE(bugprone-sizeof-expression)
- : std::integral_constant<std::size_t, sizeof(Type)> {};
- /**
- * @brief Helper variable template.
- * @tparam Type The type of which to return the size.
- */
- template<typename Type>
- inline constexpr std::size_t size_of_v = size_of<Type>::value;
- /**
- * @brief Using declaration to be used to _repeat_ the same type a number of
- * times equal to the size of a given parameter pack.
- * @tparam Type A type to repeat.
- */
- template<typename Type, typename>
- using unpack_as_type = Type;
- /**
- * @brief Helper variable template to be used to _repeat_ the same value a
- * number of times equal to the size of a given parameter pack.
- * @tparam Value A value to repeat.
- */
- template<auto Value, typename>
- inline constexpr auto unpack_as_value = Value;
- /**
- * @brief Wraps a static constant.
- * @tparam Value A static constant.
- */
- template<auto Value>
- using integral_constant = std::integral_constant<decltype(Value), Value>;
- /**
- * @brief Alias template to facilitate the creation of named values.
- * @tparam Value A constant value at least convertible to `id_type`.
- */
- template<id_type Value>
- using tag = integral_constant<Value>;
- /**
- * @brief A class to use to push around lists of types, nothing more.
- * @tparam Type Types provided by the type list.
- */
- template<typename... Type>
- struct type_list {
- /*! @brief Type list type. */
- using type = type_list;
- /*! @brief Compile-time number of elements in the type list. */
- static constexpr auto size = sizeof...(Type);
- };
- /*! @brief Primary template isn't defined on purpose. */
- template<std::size_t, typename>
- struct type_list_element;
- /**
- * @brief Provides compile-time indexed access to the types of a type list.
- * @tparam Index Index of the type to return.
- * @tparam First First type provided by the type list.
- * @tparam Other Other types provided by the type list.
- */
- template<std::size_t Index, typename First, typename... Other>
- struct type_list_element<Index, type_list<First, Other...>>
- : type_list_element<Index - 1u, type_list<Other...>> {};
- /**
- * @brief Provides compile-time indexed access to the types of a type list.
- * @tparam First First type provided by the type list.
- * @tparam Other Other types provided by the type list.
- */
- template<typename First, typename... Other>
- struct type_list_element<0u, type_list<First, Other...>> {
- /*! @brief Searched type. */
- using type = First;
- };
- /**
- * @brief Helper type.
- * @tparam Index Index of the type to return.
- * @tparam List Type list to search into.
- */
- template<std::size_t Index, typename List>
- using type_list_element_t = typename type_list_element<Index, List>::type;
- /*! @brief Primary template isn't defined on purpose. */
- template<typename, typename>
- struct type_list_index;
- /**
- * @brief Provides compile-time type access to the types of a type list.
- * @tparam Type Type to look for and for which to return the index.
- * @tparam First First type provided by the type list.
- * @tparam Other Other types provided by the type list.
- */
- template<typename Type, typename First, typename... Other>
- struct type_list_index<Type, type_list<First, Other...>> {
- /*! @brief Unsigned integer type. */
- using value_type = std::size_t;
- /*! @brief Compile-time position of the given type in the sublist. */
- static constexpr value_type value = 1u + type_list_index<Type, type_list<Other...>>::value;
- };
- /**
- * @brief Provides compile-time type access to the types of a type list.
- * @tparam Type Type to look for and for which to return the index.
- * @tparam Other Other types provided by the type list.
- */
- template<typename Type, typename... Other>
- struct type_list_index<Type, type_list<Type, Other...>> {
- static_assert(type_list_index<Type, type_list<Other...>>::value == sizeof...(Other), "Non-unique type");
- /*! @brief Unsigned integer type. */
- using value_type = std::size_t;
- /*! @brief Compile-time position of the given type in the sublist. */
- static constexpr value_type value = 0u;
- };
- /**
- * @brief Provides compile-time type access to the types of a type list.
- * @tparam Type Type to look for and for which to return the index.
- */
- template<typename Type>
- struct type_list_index<Type, type_list<>> {
- /*! @brief Unsigned integer type. */
- using value_type = std::size_t;
- /*! @brief Compile-time position of the given type in the sublist. */
- static constexpr value_type value = 0u;
- };
- /**
- * @brief Helper variable template.
- * @tparam List Type list.
- * @tparam Type Type to look for and for which to return the index.
- */
- template<typename Type, typename List>
- inline constexpr std::size_t type_list_index_v = type_list_index<Type, List>::value;
- /**
- * @brief Concatenates multiple type lists.
- * @tparam Type Types provided by the first type list.
- * @tparam Other Types provided by the second type list.
- * @return A type list composed by the types of both the type lists.
- */
- template<typename... Type, typename... Other>
- constexpr type_list<Type..., Other...> operator+(type_list<Type...>, type_list<Other...>) {
- return {};
- }
- /*! @brief Primary template isn't defined on purpose. */
- template<typename...>
- struct type_list_cat;
- /*! @brief Concatenates multiple type lists. */
- template<>
- struct type_list_cat<> {
- /*! @brief A type list composed by the types of all the type lists. */
- using type = type_list<>;
- };
- /**
- * @brief Concatenates multiple type lists.
- * @tparam Type Types provided by the first type list.
- * @tparam Other Types provided by the second type list.
- * @tparam List Other type lists, if any.
- */
- template<typename... Type, typename... Other, typename... List>
- struct type_list_cat<type_list<Type...>, type_list<Other...>, List...> {
- /*! @brief A type list composed by the types of all the type lists. */
- using type = typename type_list_cat<type_list<Type..., Other...>, List...>::type;
- };
- /**
- * @brief Concatenates multiple type lists.
- * @tparam Type Types provided by the type list.
- */
- template<typename... Type>
- struct type_list_cat<type_list<Type...>> {
- /*! @brief A type list composed by the types of all the type lists. */
- using type = type_list<Type...>;
- };
- /**
- * @brief Helper type.
- * @tparam List Type lists to concatenate.
- */
- template<typename... List>
- using type_list_cat_t = typename type_list_cat<List...>::type;
- /*! @cond TURN_OFF_DOXYGEN */
- namespace internal {
- template<typename...>
- struct type_list_unique;
- template<typename First, typename... Other, typename... Type>
- struct type_list_unique<type_list<First, Other...>, Type...>
- : std::conditional_t<(std::is_same_v<First, Type> || ...), type_list_unique<type_list<Other...>, Type...>, type_list_unique<type_list<Other...>, Type..., First>> {};
- template<typename... Type>
- struct type_list_unique<type_list<>, Type...> {
- using type = type_list<Type...>;
- };
- } // namespace internal
- /*! @endcond */
- /**
- * @brief Removes duplicates types from a type list.
- * @tparam List Type list.
- */
- template<typename List>
- struct type_list_unique {
- /*! @brief A type list without duplicate types. */
- using type = typename internal::type_list_unique<List>::type;
- };
- /**
- * @brief Helper type.
- * @tparam List Type list.
- */
- template<typename List>
- using type_list_unique_t = typename type_list_unique<List>::type;
- /**
- * @brief Provides the member constant `value` to true if a type list contains a
- * given type, false otherwise.
- * @tparam List Type list.
- * @tparam Type Type to look for.
- */
- template<typename List, typename Type>
- struct type_list_contains;
- /**
- * @copybrief type_list_contains
- * @tparam Type Types provided by the type list.
- * @tparam Other Type to look for.
- */
- template<typename... Type, typename Other>
- struct type_list_contains<type_list<Type...>, Other>
- : std::bool_constant<(std::is_same_v<Type, Other> || ...)> {};
- /**
- * @brief Helper variable template.
- * @tparam List Type list.
- * @tparam Type Type to look for.
- */
- template<typename List, typename Type>
- inline constexpr bool type_list_contains_v = type_list_contains<List, Type>::value;
- /*! @brief Primary template isn't defined on purpose. */
- template<typename...>
- struct type_list_diff;
- /**
- * @brief Computes the difference between two type lists.
- * @tparam Type Types provided by the first type list.
- * @tparam Other Types provided by the second type list.
- */
- template<typename... Type, typename... Other>
- struct type_list_diff<type_list<Type...>, type_list<Other...>> {
- /*! @brief A type list that is the difference between the two type lists. */
- using type = type_list_cat_t<std::conditional_t<type_list_contains_v<type_list<Other...>, Type>, type_list<>, type_list<Type>>...>;
- };
- /**
- * @brief Helper type.
- * @tparam List Type lists between which to compute the difference.
- */
- template<typename... List>
- using type_list_diff_t = typename type_list_diff<List...>::type;
- /*! @brief Primary template isn't defined on purpose. */
- template<typename, template<typename...> class>
- struct type_list_transform;
- /**
- * @brief Applies a given _function_ to a type list and generate a new list.
- * @tparam Type Types provided by the type list.
- * @tparam Op Unary operation as template class with a type member named `type`.
- */
- template<typename... Type, template<typename...> class Op>
- struct type_list_transform<type_list<Type...>, Op> {
- /*! @brief Resulting type list after applying the transform function. */
- // NOLINTNEXTLINE(modernize-type-traits)
- using type = type_list<typename Op<Type>::type...>;
- };
- /**
- * @brief Helper type.
- * @tparam List Type list.
- * @tparam Op Unary operation as template class with a type member named `type`.
- */
- template<typename List, template<typename...> class Op>
- using type_list_transform_t = typename type_list_transform<List, Op>::type;
- /**
- * @brief A class to use to push around lists of constant values, nothing more.
- * @tparam Value Values provided by the value list.
- */
- template<auto... Value>
- struct value_list {
- /*! @brief Value list type. */
- using type = value_list;
- /*! @brief Compile-time number of elements in the value list. */
- static constexpr auto size = sizeof...(Value);
- };
- /*! @brief Primary template isn't defined on purpose. */
- template<std::size_t, typename>
- struct value_list_element;
- /**
- * @brief Provides compile-time indexed access to the values of a value list.
- * @tparam Index Index of the value to return.
- * @tparam Value First value provided by the value list.
- * @tparam Other Other values provided by the value list.
- */
- template<std::size_t Index, auto Value, auto... Other>
- struct value_list_element<Index, value_list<Value, Other...>>
- : value_list_element<Index - 1u, value_list<Other...>> {};
- /**
- * @brief Provides compile-time indexed access to the types of a type list.
- * @tparam Value First value provided by the value list.
- * @tparam Other Other values provided by the value list.
- */
- template<auto Value, auto... Other>
- struct value_list_element<0u, value_list<Value, Other...>> {
- /*! @brief Searched type. */
- using type = decltype(Value);
- /*! @brief Searched value. */
- static constexpr auto value = Value;
- };
- /**
- * @brief Helper type.
- * @tparam Index Index of the type to return.
- * @tparam List Value list to search into.
- */
- template<std::size_t Index, typename List>
- using value_list_element_t = typename value_list_element<Index, List>::type;
- /**
- * @brief Helper type.
- * @tparam Index Index of the value to return.
- * @tparam List Value list to search into.
- */
- template<std::size_t Index, typename List>
- inline constexpr auto value_list_element_v = value_list_element<Index, List>::value;
- /*! @brief Primary template isn't defined on purpose. */
- template<auto, typename>
- struct value_list_index;
- /**
- * @brief Provides compile-time type access to the values of a value list.
- * @tparam Value Value to look for and for which to return the index.
- * @tparam First First value provided by the value list.
- * @tparam Other Other values provided by the value list.
- */
- template<auto Value, auto First, auto... Other>
- struct value_list_index<Value, value_list<First, Other...>> {
- /*! @brief Unsigned integer type. */
- using value_type = std::size_t;
- /*! @brief Compile-time position of the given value in the sublist. */
- static constexpr value_type value = 1u + value_list_index<Value, value_list<Other...>>::value;
- };
- /**
- * @brief Provides compile-time type access to the values of a value list.
- * @tparam Value Value to look for and for which to return the index.
- * @tparam Other Other values provided by the value list.
- */
- template<auto Value, auto... Other>
- struct value_list_index<Value, value_list<Value, Other...>> {
- static_assert(value_list_index<Value, value_list<Other...>>::value == sizeof...(Other), "Non-unique type");
- /*! @brief Unsigned integer type. */
- using value_type = std::size_t;
- /*! @brief Compile-time position of the given value in the sublist. */
- static constexpr value_type value = 0u;
- };
- /**
- * @brief Provides compile-time type access to the values of a value list.
- * @tparam Value Value to look for and for which to return the index.
- */
- template<auto Value>
- struct value_list_index<Value, value_list<>> {
- /*! @brief Unsigned integer type. */
- using value_type = std::size_t;
- /*! @brief Compile-time position of the given type in the sublist. */
- static constexpr value_type value = 0u;
- };
- /**
- * @brief Helper variable template.
- * @tparam List Value list.
- * @tparam Value Value to look for and for which to return the index.
- */
- template<auto Value, typename List>
- inline constexpr std::size_t value_list_index_v = value_list_index<Value, List>::value;
- /**
- * @brief Concatenates multiple value lists.
- * @tparam Value Values provided by the first value list.
- * @tparam Other Values provided by the second value list.
- * @return A value list composed by the values of both the value lists.
- */
- template<auto... Value, auto... Other>
- constexpr value_list<Value..., Other...> operator+(value_list<Value...>, value_list<Other...>) {
- return {};
- }
- /*! @brief Primary template isn't defined on purpose. */
- template<typename...>
- struct value_list_cat;
- /*! @brief Concatenates multiple value lists. */
- template<>
- struct value_list_cat<> {
- /*! @brief A value list composed by the values of all the value lists. */
- using type = value_list<>;
- };
- /**
- * @brief Concatenates multiple value lists.
- * @tparam Value Values provided by the first value list.
- * @tparam Other Values provided by the second value list.
- * @tparam List Other value lists, if any.
- */
- template<auto... Value, auto... Other, typename... List>
- struct value_list_cat<value_list<Value...>, value_list<Other...>, List...> {
- /*! @brief A value list composed by the values of all the value lists. */
- using type = typename value_list_cat<value_list<Value..., Other...>, List...>::type;
- };
- /**
- * @brief Concatenates multiple value lists.
- * @tparam Value Values provided by the value list.
- */
- template<auto... Value>
- struct value_list_cat<value_list<Value...>> {
- /*! @brief A value list composed by the values of all the value lists. */
- using type = value_list<Value...>;
- };
- /**
- * @brief Helper type.
- * @tparam List Value lists to concatenate.
- */
- template<typename... List>
- using value_list_cat_t = typename value_list_cat<List...>::type;
- /*! @brief Primary template isn't defined on purpose. */
- template<typename>
- struct value_list_unique;
- /**
- * @brief Removes duplicates values from a value list.
- * @tparam Value One of the values provided by the given value list.
- * @tparam Other The other values provided by the given value list.
- */
- template<auto Value, auto... Other>
- struct value_list_unique<value_list<Value, Other...>> {
- /*! @brief A value list without duplicate types. */
- using type = std::conditional_t<
- ((Value == Other) || ...),
- typename value_list_unique<value_list<Other...>>::type,
- value_list_cat_t<value_list<Value>, typename value_list_unique<value_list<Other...>>::type>>;
- };
- /*! @brief Removes duplicates values from a value list. */
- template<>
- struct value_list_unique<value_list<>> {
- /*! @brief A value list without duplicate types. */
- using type = value_list<>;
- };
- /**
- * @brief Helper type.
- * @tparam Type A value list.
- */
- template<typename Type>
- using value_list_unique_t = typename value_list_unique<Type>::type;
- /**
- * @brief Provides the member constant `value` to true if a value list contains
- * a given value, false otherwise.
- * @tparam List Value list.
- * @tparam Value Value to look for.
- */
- template<typename List, auto Value>
- struct value_list_contains;
- /**
- * @copybrief value_list_contains
- * @tparam Value Values provided by the value list.
- * @tparam Other Value to look for.
- */
- template<auto... Value, auto Other>
- struct value_list_contains<value_list<Value...>, Other>
- : std::bool_constant<((Value == Other) || ...)> {};
- /**
- * @brief Helper variable template.
- * @tparam List Value list.
- * @tparam Value Value to look for.
- */
- template<typename List, auto Value>
- inline constexpr bool value_list_contains_v = value_list_contains<List, Value>::value;
- /*! @brief Primary template isn't defined on purpose. */
- template<typename...>
- struct value_list_diff;
- /**
- * @brief Computes the difference between two value lists.
- * @tparam Value Values provided by the first value list.
- * @tparam Other Values provided by the second value list.
- */
- template<auto... Value, auto... Other>
- struct value_list_diff<value_list<Value...>, value_list<Other...>> {
- /*! @brief A value list that is the difference between the two value lists. */
- using type = value_list_cat_t<std::conditional_t<value_list_contains_v<value_list<Other...>, Value>, value_list<>, value_list<Value>>...>;
- };
- /**
- * @brief Helper type.
- * @tparam List Value lists between which to compute the difference.
- */
- template<typename... List>
- using value_list_diff_t = typename value_list_diff<List...>::type;
- /*! @brief Same as std::is_invocable, but with tuples. */
- template<typename, typename>
- struct is_applicable: std::false_type {};
- /**
- * @copybrief is_applicable
- * @tparam Func A valid function type.
- * @tparam Tuple Tuple-like type.
- * @tparam Args The list of arguments to use to probe the function type.
- */
- template<typename Func, template<typename...> class Tuple, typename... Args>
- struct is_applicable<Func, Tuple<Args...>>: std::is_invocable<Func, Args...> {};
- /**
- * @copybrief is_applicable
- * @tparam Func A valid function type.
- * @tparam Tuple Tuple-like type.
- * @tparam Args The list of arguments to use to probe the function type.
- */
- template<typename Func, template<typename...> class Tuple, typename... Args>
- struct is_applicable<Func, const Tuple<Args...>>: std::is_invocable<Func, Args...> {};
- /**
- * @brief Helper variable template.
- * @tparam Func A valid function type.
- * @tparam Args The list of arguments to use to probe the function type.
- */
- template<typename Func, typename Args>
- inline constexpr bool is_applicable_v = is_applicable<Func, Args>::value;
- /*! @brief Same as std::is_invocable_r, but with tuples for arguments. */
- template<typename, typename, typename>
- struct is_applicable_r: std::false_type {};
- /**
- * @copybrief is_applicable_r
- * @tparam Ret The type to which the return type of the function should be
- * convertible.
- * @tparam Func A valid function type.
- * @tparam Args The list of arguments to use to probe the function type.
- */
- template<typename Ret, typename Func, typename... Args>
- struct is_applicable_r<Ret, Func, std::tuple<Args...>>: std::is_invocable_r<Ret, Func, Args...> {};
- /**
- * @brief Helper variable template.
- * @tparam Ret The type to which the return type of the function should be
- * convertible.
- * @tparam Func A valid function type.
- * @tparam Args The list of arguments to use to probe the function type.
- */
- template<typename Ret, typename Func, typename Args>
- inline constexpr bool is_applicable_r_v = is_applicable_r<Ret, Func, Args>::value;
- /**
- * @brief Provides the member constant `value` to true if a given type is
- * complete, false otherwise.
- * @tparam Type The type to test.
- */
- template<typename Type, typename = void>
- struct is_complete: std::false_type {};
- /*! @copydoc is_complete */
- template<typename Type>
- struct is_complete<Type, std::void_t<decltype(sizeof(Type))>>: std::true_type {};
- /**
- * @brief Helper variable template.
- * @tparam Type The type to test.
- */
- template<typename Type>
- inline constexpr bool is_complete_v = is_complete<Type>::value;
- /**
- * @brief Provides the member constant `value` to true if a given type is an
- * iterator, false otherwise.
- * @tparam Type The type to test.
- */
- template<typename Type, typename = void>
- struct is_iterator: std::false_type {};
- /*! @cond TURN_OFF_DOXYGEN */
- namespace internal {
- template<typename, typename = void>
- struct has_iterator_category: std::false_type {};
- template<typename Type>
- struct has_iterator_category<Type, std::void_t<typename std::iterator_traits<Type>::iterator_category>>: std::true_type {};
- } // namespace internal
- /*! @endcond */
- /*! @copydoc is_iterator */
- template<typename Type>
- struct is_iterator<Type, std::enable_if_t<!std::is_void_v<std::remove_const_t<std::remove_pointer_t<Type>>>>>
- : internal::has_iterator_category<Type> {};
- /**
- * @brief Helper variable template.
- * @tparam Type The type to test.
- */
- template<typename Type>
- inline constexpr bool is_iterator_v = is_iterator<Type>::value;
- /**
- * @brief Provides the member constant `value` to true if a given type is both
- * an empty and non-final class, false otherwise.
- * @tparam Type The type to test
- */
- template<typename Type>
- struct is_ebco_eligible
- : std::bool_constant<std::is_empty_v<Type> && !std::is_final_v<Type>> {};
- /**
- * @brief Helper variable template.
- * @tparam Type The type to test.
- */
- template<typename Type>
- inline constexpr bool is_ebco_eligible_v = is_ebco_eligible<Type>::value;
- /**
- * @brief Provides the member constant `value` to true if `Type::is_transparent`
- * is valid and denotes a type, false otherwise.
- * @tparam Type The type to test.
- */
- template<typename Type, typename = void>
- struct is_transparent: std::false_type {};
- /*! @copydoc is_transparent */
- template<typename Type>
- struct is_transparent<Type, std::void_t<typename Type::is_transparent>>: std::true_type {};
- /**
- * @brief Helper variable template.
- * @tparam Type The type to test.
- */
- template<typename Type>
- inline constexpr bool is_transparent_v = is_transparent<Type>::value;
- /*! @cond TURN_OFF_DOXYGEN */
- namespace internal {
- template<typename, typename = void>
- struct has_tuple_size_value: std::false_type {};
- template<typename Type>
- struct has_tuple_size_value<Type, std::void_t<decltype(std::tuple_size<const Type>::value)>>: std::true_type {};
- template<typename, typename = void>
- struct has_value_type: std::false_type {};
- template<typename Type>
- struct has_value_type<Type, std::void_t<typename Type::value_type>>: std::true_type {};
- template<typename>
- [[nodiscard]] constexpr bool dispatch_is_equality_comparable();
- template<typename Type, std::size_t... Index>
- [[nodiscard]] constexpr bool unpack_maybe_equality_comparable(std::index_sequence<Index...>) {
- return (dispatch_is_equality_comparable<std::tuple_element_t<Index, Type>>() && ...);
- }
- template<typename>
- [[nodiscard]] constexpr bool maybe_equality_comparable(char) {
- return false;
- }
- template<typename Type>
- [[nodiscard]] constexpr auto maybe_equality_comparable(int) -> decltype(std::declval<Type>() == std::declval<Type>()) {
- return true;
- }
- template<typename Type>
- [[nodiscard]] constexpr bool dispatch_is_equality_comparable() {
- // NOLINTBEGIN(modernize-use-transparent-functors)
- if constexpr(std::is_array_v<Type>) {
- return false;
- } else if constexpr(is_complete_v<std::tuple_size<std::remove_const_t<Type>>>) {
- if constexpr(has_tuple_size_value<Type>::value) {
- return maybe_equality_comparable<Type>(0) && unpack_maybe_equality_comparable<Type>(std::make_index_sequence<std::tuple_size<Type>::value>{});
- } else {
- return maybe_equality_comparable<Type>(0);
- }
- } else if constexpr(has_value_type<Type>::value) {
- if constexpr(is_iterator_v<Type> || std::is_same_v<typename Type::value_type, Type> || dispatch_is_equality_comparable<typename Type::value_type>()) {
- return maybe_equality_comparable<Type>(0);
- } else {
- return false;
- }
- } else {
- return maybe_equality_comparable<Type>(0);
- }
- // NOLINTEND(modernize-use-transparent-functors)
- }
- } // namespace internal
- /*! @endcond */
- /**
- * @brief Provides the member constant `value` to true if a given type is
- * equality comparable, false otherwise.
- * @tparam Type The type to test.
- */
- template<typename Type>
- struct is_equality_comparable: std::bool_constant<internal::dispatch_is_equality_comparable<Type>()> {};
- /*! @copydoc is_equality_comparable */
- template<typename Type>
- struct is_equality_comparable<const Type>: is_equality_comparable<Type> {};
- /**
- * @brief Helper variable template.
- * @tparam Type The type to test.
- */
- template<typename Type>
- inline constexpr bool is_equality_comparable_v = is_equality_comparable<Type>::value;
- /**
- * @brief Transcribes the constness of a type to another type.
- * @tparam To The type to which to transcribe the constness.
- * @tparam From The type from which to transcribe the constness.
- */
- template<typename To, typename From>
- struct constness_as {
- /*! @brief The type resulting from the transcription of the constness. */
- using type = std::remove_const_t<To>;
- };
- /*! @copydoc constness_as */
- template<typename To, typename From>
- struct constness_as<To, const From> {
- /*! @brief The type resulting from the transcription of the constness. */
- using type = const To;
- };
- /**
- * @brief Alias template to facilitate the transcription of the constness.
- * @tparam To The type to which to transcribe the constness.
- * @tparam From The type from which to transcribe the constness.
- */
- template<typename To, typename From>
- using constness_as_t = typename constness_as<To, From>::type;
- /**
- * @brief Extracts the class of a non-static member object or function.
- * @tparam Member A pointer to a non-static member object or function.
- */
- template<typename Member>
- class member_class {
- static_assert(std::is_member_pointer_v<Member>, "Invalid pointer type to non-static member object or function");
- template<typename Class, typename Ret, typename... Args>
- static Class *clazz(Ret (Class::*)(Args...));
- template<typename Class, typename Ret, typename... Args>
- static Class *clazz(Ret (Class::*)(Args...) const);
- template<typename Class, typename Type>
- static Class *clazz(Type Class::*);
- public:
- /*! @brief The class of the given non-static member object or function. */
- using type = std::remove_pointer_t<decltype(clazz(std::declval<Member>()))>;
- };
- /**
- * @brief Helper type.
- * @tparam Member A pointer to a non-static member object or function.
- */
- template<typename Member>
- using member_class_t = typename member_class<Member>::type;
- /**
- * @brief Extracts the n-th argument of a _callable_ type.
- * @tparam Index The index of the argument to extract.
- * @tparam Candidate A valid _callable_ type.
- */
- template<std::size_t Index, typename Candidate>
- class nth_argument {
- template<typename Ret, typename... Args>
- static constexpr type_list<Args...> pick_up(Ret (*)(Args...));
- template<typename Ret, typename Class, typename... Args>
- static constexpr type_list<Args...> pick_up(Ret (Class ::*)(Args...));
- template<typename Ret, typename Class, typename... Args>
- static constexpr type_list<Args...> pick_up(Ret (Class ::*)(Args...) const);
- template<typename Type, typename Class>
- static constexpr type_list<Type> pick_up(Type Class ::*);
- template<typename Type>
- static constexpr decltype(pick_up(&Type::operator())) pick_up(Type &&);
- public:
- /*! @brief N-th argument of the _callable_ type. */
- using type = type_list_element_t<Index, decltype(pick_up(std::declval<Candidate>()))>;
- };
- /**
- * @brief Helper type.
- * @tparam Index The index of the argument to extract.
- * @tparam Candidate A valid function, member function or data member type.
- */
- template<std::size_t Index, typename Candidate>
- using nth_argument_t = typename nth_argument<Index, Candidate>::type;
- } // namespace entt
- template<typename... Type>
- struct std::tuple_size<entt::type_list<Type...>>: std::integral_constant<std::size_t, entt::type_list<Type...>::size> {};
- template<std::size_t Index, typename... Type>
- struct std::tuple_element<Index, entt::type_list<Type...>>: entt::type_list_element<Index, entt::type_list<Type...>> {};
- template<auto... Value>
- struct std::tuple_size<entt::value_list<Value...>>: std::integral_constant<std::size_t, entt::value_list<Value...>::size> {};
- template<std::size_t Index, auto... Value>
- struct std::tuple_element<Index, entt::value_list<Value...>>: entt::value_list_element<Index, entt::value_list<Value...>> {};
- #endif
- // #include "utility.hpp"
- #ifndef ENTT_CORE_UTILITY_HPP
- #define ENTT_CORE_UTILITY_HPP
- #include <type_traits>
- #include <utility>
- namespace entt {
- /*! @brief Identity function object (waiting for C++20). */
- struct identity {
- /*! @brief Indicates that this is a transparent function object. */
- using is_transparent = void;
- /**
- * @brief Returns its argument unchanged.
- * @tparam Type Type of the argument.
- * @param value The actual argument.
- * @return The submitted value as-is.
- */
- template<typename Type>
- [[nodiscard]] constexpr Type &&operator()(Type &&value) const noexcept {
- return std::forward<Type>(value);
- }
- };
- /**
- * @brief Constant utility to disambiguate overloaded members of a class.
- * @tparam Type Type of the desired overload.
- * @tparam Class Type of class to which the member belongs.
- * @param member A valid pointer to a member.
- * @return Pointer to the member.
- */
- template<typename Type, typename Class>
- [[nodiscard]] constexpr auto overload(Type Class::*member) noexcept {
- return member;
- }
- /**
- * @brief Constant utility to disambiguate overloaded functions.
- * @tparam Func Function type of the desired overload.
- * @param func A valid pointer to a function.
- * @return Pointer to the function.
- */
- template<typename Func>
- [[nodiscard]] constexpr auto overload(Func *func) noexcept {
- return func;
- }
- /**
- * @brief Helper type for visitors.
- * @tparam Func Types of function objects.
- */
- template<typename... Func>
- struct overloaded: Func... {
- using Func::operator()...;
- };
- /**
- * @brief Deduction guide.
- * @tparam Func Types of function objects.
- */
- template<typename... Func>
- overloaded(Func...) -> overloaded<Func...>;
- /**
- * @brief Basic implementation of a y-combinator.
- * @tparam Func Type of a potentially recursive function.
- */
- template<typename Func>
- struct y_combinator {
- /**
- * @brief Constructs a y-combinator from a given function.
- * @param recursive A potentially recursive function.
- */
- constexpr y_combinator(Func recursive) noexcept(std::is_nothrow_move_constructible_v<Func>)
- : func{std::move(recursive)} {}
- /**
- * @brief Invokes a y-combinator and therefore its underlying function.
- * @tparam Args Types of arguments to use to invoke the underlying function.
- * @param args Parameters to use to invoke the underlying function.
- * @return Return value of the underlying function, if any.
- */
- template<typename... Args>
- constexpr decltype(auto) operator()(Args &&...args) const noexcept(std::is_nothrow_invocable_v<Func, const y_combinator &, Args...>) {
- return func(*this, std::forward<Args>(args)...);
- }
- /*! @copydoc operator()() */
- template<typename... Args>
- constexpr decltype(auto) operator()(Args &&...args) noexcept(std::is_nothrow_invocable_v<Func, y_combinator &, Args...>) {
- return func(*this, std::forward<Args>(args)...);
- }
- private:
- Func func;
- };
- } // namespace entt
- #endif
- namespace entt {
- /*! @cond TURN_OFF_DOXYGEN */
- namespace internal {
- enum class any_request : std::uint8_t {
- info,
- transfer,
- assign,
- compare,
- copy,
- move
- };
- template<std::size_t Len, std::size_t Align>
- struct basic_any_storage {
- static constexpr bool has_buffer = true;
- union {
- const void *instance{};
- // NOLINTNEXTLINE(cppcoreguidelines-avoid-c-arrays, modernize-avoid-c-arrays)
- alignas(Align) std::byte buffer[Len];
- };
- };
- template<std::size_t Align>
- struct basic_any_storage<0u, Align> {
- static constexpr bool has_buffer = false;
- const void *instance{};
- };
- template<typename Type, std::size_t Len, std::size_t Align>
- // NOLINTNEXTLINE(bugprone-sizeof-expression)
- struct in_situ: std::bool_constant<(Len != 0u) && alignof(Type) <= Align && sizeof(Type) <= Len && std::is_nothrow_move_constructible_v<Type>> {};
- template<std::size_t Len, std::size_t Align>
- struct in_situ<void, Len, Align>: std::false_type {};
- } // namespace internal
- /*! @endcond */
- /**
- * @brief A SBO friendly, type-safe container for single values of any type.
- * @tparam Len Size of the buffer reserved for the small buffer optimization.
- * @tparam Align Optional alignment requirement.
- */
- template<std::size_t Len, std::size_t Align>
- class basic_any: private internal::basic_any_storage<Len, Align> {
- using request = internal::any_request;
- using base_type = internal::basic_any_storage<Len, Align>;
- using vtable_type = const void *(const request, const basic_any &, const void *);
- using deleter_type = void(const basic_any &);
- template<typename Type>
- static constexpr bool in_situ_v = internal::in_situ<Type, Len, Align>::value;
- template<typename Type>
- static const void *basic_vtable(const request req, const basic_any &value, const void *other) {
- static_assert(std::is_same_v<std::remove_const_t<std::remove_reference_t<Type>>, Type>, "Invalid type");
- switch(const auto *elem = static_cast<const Type *>(value.data()); req) {
- case request::info:
- return &type_id<Type>();
- case request::transfer:
- if constexpr(std::is_move_assignable_v<Type>) {
- // NOLINTNEXTLINE(bugprone-casting-through-void)
- *const_cast<Type *>(elem) = std::move(*static_cast<Type *>(const_cast<void *>(other)));
- return other;
- }
- [[fallthrough]];
- case request::assign:
- if constexpr(std::is_copy_assignable_v<Type>) {
- *const_cast<Type *>(elem) = *static_cast<const Type *>(other);
- return other;
- }
- break;
- case request::compare:
- if constexpr(!std::is_function_v<Type> && !std::is_array_v<Type> && is_equality_comparable_v<Type>) {
- return (*elem == *static_cast<const Type *>(other)) ? other : nullptr;
- } else {
- return (elem == other) ? other : nullptr;
- }
- case request::copy:
- if constexpr(std::is_copy_constructible_v<Type>) {
- // NOLINTNEXTLINE(bugprone-casting-through-void)
- static_cast<basic_any *>(const_cast<void *>(other))->initialize<Type>(*elem);
- }
- break;
- case request::move:
- ENTT_ASSERT(value.mode == any_policy::embedded, "Unexpected policy");
- if constexpr(in_situ_v<Type>) {
- // NOLINTNEXTLINE(bugprone-casting-through-void, bugprone-multi-level-implicit-pointer-conversion)
- return ::new(&static_cast<basic_any *>(const_cast<void *>(other))->buffer) Type{std::move(*const_cast<Type *>(elem))};
- }
- }
- return nullptr;
- }
- template<typename Type>
- static void basic_deleter(const basic_any &value) {
- static_assert(std::is_same_v<std::remove_const_t<std::remove_reference_t<Type>>, Type>, "Invalid type");
- ENTT_ASSERT((value.mode == any_policy::dynamic) || ((value.mode == any_policy::embedded) && !std::is_trivially_destructible_v<Type>), "Unexpected policy");
- const auto *elem = static_cast<const Type *>(value.data());
- if constexpr(in_situ_v<Type>) {
- (value.mode == any_policy::embedded) ? elem->~Type() : (delete elem);
- } else if constexpr(std::is_array_v<Type>) {
- delete[] elem;
- } else {
- delete elem;
- }
- }
- template<typename Type, typename... Args>
- void initialize([[maybe_unused]] Args &&...args) {
- using plain_type = std::remove_const_t<std::remove_reference_t<Type>>;
- vtable = basic_vtable<plain_type>;
- underlying_type = type_hash<plain_type>::value();
- if constexpr(std::is_void_v<Type>) {
- deleter = nullptr;
- mode = any_policy::empty;
- this->instance = nullptr;
- } else if constexpr(std::is_lvalue_reference_v<Type>) {
- deleter = nullptr;
- mode = std::is_const_v<std::remove_reference_t<Type>> ? any_policy::cref : any_policy::ref;
- static_assert((std::is_lvalue_reference_v<Args> && ...) && (sizeof...(Args) == 1u), "Invalid arguments");
- // NOLINTNEXTLINE(bugprone-multi-level-implicit-pointer-conversion)
- this->instance = (std::addressof(args), ...);
- } else if constexpr(in_situ_v<plain_type>) {
- if constexpr(std::is_trivially_destructible_v<plain_type>) {
- deleter = nullptr;
- } else {
- deleter = &basic_deleter<plain_type>;
- }
- mode = any_policy::embedded;
- if constexpr(std::is_aggregate_v<plain_type> && (sizeof...(Args) != 0u || !std::is_default_constructible_v<plain_type>)) {
- ::new(&this->buffer) plain_type{std::forward<Args>(args)...};
- } else {
- // NOLINTNEXTLINE(cppcoreguidelines-pro-bounds-array-to-pointer-decay)
- ::new(&this->buffer) plain_type(std::forward<Args>(args)...);
- }
- } else {
- deleter = &basic_deleter<plain_type>;
- mode = any_policy::dynamic;
- if constexpr(std::is_aggregate_v<plain_type> && (sizeof...(Args) != 0u || !std::is_default_constructible_v<plain_type>)) {
- this->instance = new plain_type{std::forward<Args>(args)...};
- } else if constexpr(std::is_array_v<plain_type>) {
- static_assert(sizeof...(Args) == 0u, "Invalid arguments");
- this->instance = new plain_type[std::extent_v<plain_type>]();
- } else {
- this->instance = new plain_type(std::forward<Args>(args)...);
- }
- }
- }
- void invoke_deleter_if_exists() {
- if(deleter != nullptr) {
- deleter(*this);
- }
- }
- public:
- /*! @brief Size of the internal buffer. */
- static constexpr auto length = Len;
- /*! @brief Alignment requirement. */
- static constexpr auto alignment = Align;
- /*! @brief Default constructor. */
- constexpr basic_any() noexcept
- : basic_any{std::in_place_type<void>} {}
- /**
- * @brief Constructs a wrapper by directly initializing the new object.
- * @tparam Type Type of object to use to initialize the wrapper.
- * @tparam Args Types of arguments to use to construct the new instance.
- * @param args Parameters to use to construct the instance.
- */
- template<typename Type, typename... Args>
- explicit basic_any(std::in_place_type_t<Type>, Args &&...args)
- : base_type{} {
- initialize<Type>(std::forward<Args>(args)...);
- }
- /**
- * @brief Constructs a wrapper taking ownership of the passed object.
- * @tparam Type Type of object to use to initialize the wrapper.
- * @param value A pointer to an object to take ownership of.
- */
- template<typename Type>
- explicit basic_any(std::in_place_t, Type *value)
- : base_type{} {
- static_assert(!std::is_const_v<Type> && !std::is_void_v<Type>, "Non-const non-void pointer required");
- if(value == nullptr) {
- initialize<void>();
- } else {
- initialize<Type &>(*value);
- deleter = &basic_deleter<Type>;
- mode = any_policy::dynamic;
- }
- }
- /**
- * @brief Constructs a wrapper from a given value.
- * @tparam Type Type of object to use to initialize the wrapper.
- * @param value An instance of an object to use to initialize the wrapper.
- */
- template<typename Type, typename = std::enable_if_t<!std::is_same_v<std::decay_t<Type>, basic_any>>>
- basic_any(Type &&value)
- : basic_any{std::in_place_type<std::decay_t<Type>>, std::forward<Type>(value)} {}
- /**
- * @brief Copy constructor.
- * @param other The instance to copy from.
- */
- basic_any(const basic_any &other)
- : basic_any{} {
- other.vtable(request::copy, other, this);
- }
- /**
- * @brief Move constructor.
- * @param other The instance to move from.
- */
- basic_any(basic_any &&other) noexcept
- : base_type{},
- vtable{other.vtable},
- deleter{other.deleter},
- underlying_type{other.underlying_type},
- mode{other.mode} {
- if(other.mode == any_policy::embedded) {
- other.vtable(request::move, other, this);
- } else if(other.mode != any_policy::empty) {
- this->instance = std::exchange(other.instance, nullptr);
- }
- }
- /*! @brief Frees the internal buffer, whatever it means. */
- ~basic_any() {
- invoke_deleter_if_exists();
- }
- /**
- * @brief Copy assignment operator.
- * @param other The instance to copy from.
- * @return This any object.
- */
- basic_any &operator=(const basic_any &other) {
- if(this != &other) {
- invoke_deleter_if_exists();
- if(other) {
- other.vtable(request::copy, other, this);
- } else {
- initialize<void>();
- }
- }
- return *this;
- }
- /**
- * @brief Move assignment operator.
- * @param other The instance to move from.
- * @return This any object.
- */
- basic_any &operator=(basic_any &&other) noexcept {
- if(this != &other) {
- invoke_deleter_if_exists();
- if(other.mode == any_policy::embedded) {
- other.vtable(request::move, other, this);
- } else if(other.mode != any_policy::empty) {
- this->instance = std::exchange(other.instance, nullptr);
- }
- vtable = other.vtable;
- deleter = other.deleter;
- underlying_type = other.underlying_type;
- mode = other.mode;
- }
- return *this;
- }
- /**
- * @brief Value assignment operator.
- * @tparam Type Type of object to use to initialize the wrapper.
- * @param value An instance of an object to use to initialize the wrapper.
- * @return This any object.
- */
- template<typename Type, typename = std::enable_if_t<!std::is_same_v<std::decay_t<Type>, basic_any>>>
- basic_any &operator=(Type &&value) {
- emplace<std::decay_t<Type>>(std::forward<Type>(value));
- return *this;
- }
- /**
- * @brief Returns false if a wrapper is empty, true otherwise.
- * @return False if the wrapper is empty, true otherwise.
- */
- [[nodiscard]] bool has_value() const noexcept {
- return (mode != any_policy::empty);
- }
- /**
- * @brief Returns false if the wrapper does not contain the expected type,
- * true otherwise.
- * @param req Expected type.
- * @return False if the wrapper does not contain the expected type, true
- * otherwise.
- */
- [[nodiscard]] bool has_value(const type_info &req) const noexcept {
- return (underlying_type == req.hash());
- }
- /**
- * @brief Returns false if the wrapper does not contain the expected type,
- * true otherwise.
- * @tparam Type Expected type.
- * @return False if the wrapper does not contain the expected type, true
- * otherwise.
- */
- template<typename Type>
- [[nodiscard]] bool has_value() const noexcept {
- static_assert(std::is_same_v<std::remove_const_t<Type>, Type>, "Invalid type");
- return (underlying_type == type_hash<Type>::value());
- }
- /**
- * @brief Returns the object type info if any, `type_id<void>()` otherwise.
- * @return The object type info if any, `type_id<void>()` otherwise.
- */
- [[nodiscard]] const type_info &info() const noexcept {
- return *static_cast<const type_info *>(vtable(request::info, *this, nullptr));
- }
- /*! @copydoc info */
- [[deprecated("use ::info instead")]] [[nodiscard]] const type_info &type() const noexcept {
- return info();
- }
- /**
- * @brief Returns an opaque pointer to the contained instance.
- * @return An opaque pointer the contained instance, if any.
- */
- [[nodiscard]] const void *data() const noexcept {
- if constexpr(base_type::has_buffer) {
- return (mode == any_policy::embedded) ? &this->buffer : this->instance;
- } else {
- return this->instance;
- }
- }
- /**
- * @brief Returns an opaque pointer to the contained instance.
- * @param req Expected type.
- * @return An opaque pointer the contained instance, if any.
- */
- [[nodiscard]] const void *data(const type_info &req) const noexcept {
- return has_value(req) ? data() : nullptr;
- }
- /**
- * @brief Returns an opaque pointer to the contained instance.
- * @tparam Type Expected type.
- * @return An opaque pointer the contained instance, if any.
- */
- template<typename Type>
- [[nodiscard]] const Type *data() const noexcept {
- return has_value<std::remove_const_t<Type>>() ? static_cast<const Type *>(data()) : nullptr;
- }
- /**
- * @brief Returns an opaque pointer to the contained instance.
- * @return An opaque pointer the contained instance, if any.
- */
- [[nodiscard]] void *data() noexcept {
- return (mode == any_policy::cref) ? nullptr : const_cast<void *>(std::as_const(*this).data());
- }
- /**
- * @brief Returns an opaque pointer to the contained instance.
- * @param req Expected type.
- * @return An opaque pointer the contained instance, if any.
- */
- [[nodiscard]] void *data(const type_info &req) noexcept {
- return (mode == any_policy::cref) ? nullptr : const_cast<void *>(std::as_const(*this).data(req));
- }
- /**
- * @brief Returns an opaque pointer to the contained instance.
- * @tparam Type Expected type.
- * @return An opaque pointer the contained instance, if any.
- */
- template<typename Type>
- [[nodiscard]] Type *data() noexcept {
- if constexpr(std::is_const_v<Type>) {
- return std::as_const(*this).template data<std::remove_const_t<Type>>();
- } else {
- return (mode == any_policy::cref) ? nullptr : const_cast<Type *>(std::as_const(*this).template data<std::remove_const_t<Type>>());
- }
- }
- /**
- * @brief Replaces the contained object by creating a new instance directly.
- * @tparam Type Type of object to use to initialize the wrapper.
- * @tparam Args Types of arguments to use to construct the new instance.
- * @param args Parameters to use to construct the instance.
- */
- template<typename Type, typename... Args>
- void emplace(Args &&...args) {
- invoke_deleter_if_exists();
- initialize<Type>(std::forward<Args>(args)...);
- }
- /**
- * @brief Assigns a value to the contained object without replacing it.
- * @param other The value to assign to the contained object.
- * @return True in case of success, false otherwise.
- */
- bool assign(const basic_any &other) {
- if(other && (mode != any_policy::cref) && (underlying_type == other.underlying_type)) {
- return (vtable(request::assign, *this, other.data()) != nullptr);
- }
- return false;
- }
- /*! @copydoc assign */
- // NOLINTNEXTLINE(cppcoreguidelines-rvalue-reference-param-not-moved)
- bool assign(basic_any &&other) {
- if(other && (mode != any_policy::cref) && (underlying_type == other.underlying_type)) {
- return (other.mode == any_policy::cref) ? (vtable(request::assign, *this, std::as_const(other).data()) != nullptr) : (vtable(request::transfer, *this, other.data()) != nullptr);
- }
- return false;
- }
- /*! @brief Destroys contained object */
- void reset() {
- invoke_deleter_if_exists();
- initialize<void>();
- }
- /**
- * @brief Returns false if a wrapper is empty, true otherwise.
- * @return False if the wrapper is empty, true otherwise.
- */
- [[nodiscard]] explicit operator bool() const noexcept {
- return has_value();
- }
- /**
- * @brief Checks if two wrappers differ in their content.
- * @param other Wrapper with which to compare.
- * @return False if the two objects differ in their content, true otherwise.
- */
- [[nodiscard]] bool operator==(const basic_any &other) const noexcept {
- if(other && (underlying_type == other.underlying_type)) {
- return (vtable(request::compare, *this, other.data()) != nullptr);
- }
- return (!*this && !other);
- }
- /**
- * @brief Checks if two wrappers differ in their content.
- * @param other Wrapper with which to compare.
- * @return True if the two objects differ in their content, false otherwise.
- */
- [[nodiscard]] bool operator!=(const basic_any &other) const noexcept {
- return !(*this == other);
- }
- /**
- * @brief Aliasing constructor.
- * @return A wrapper that shares a reference to an unmanaged object.
- */
- [[nodiscard]] basic_any as_ref() noexcept {
- basic_any other = std::as_const(*this).as_ref();
- other.mode = (mode == any_policy::cref ? any_policy::cref : any_policy::ref);
- return other;
- }
- /*! @copydoc as_ref */
- [[nodiscard]] basic_any as_ref() const noexcept {
- basic_any other{};
- other.instance = data();
- other.vtable = vtable;
- other.underlying_type = underlying_type;
- other.mode = any_policy::cref;
- return other;
- }
- /**
- * @brief Returns true if a wrapper owns its object, false otherwise.
- * @return True if the wrapper owns its object, false otherwise.
- */
- [[nodiscard]] bool owner() const noexcept {
- return (mode == any_policy::dynamic || mode == any_policy::embedded);
- }
- /**
- * @brief Returns the current mode of an any object.
- * @return The current mode of the any object.
- */
- [[nodiscard]] any_policy policy() const noexcept {
- return mode;
- }
- private:
- vtable_type *vtable{};
- deleter_type *deleter{};
- id_type underlying_type{};
- any_policy mode{};
- };
- /**
- * @brief Performs type-safe access to the contained object.
- * @tparam Type Type to which conversion is required.
- * @tparam Len Size of the buffer reserved for the small buffer optimization.
- * @tparam Align Alignment requirement.
- * @param data Target any object.
- * @return The element converted to the requested type.
- */
- template<typename Type, std::size_t Len, std::size_t Align>
- [[nodiscard]] std::remove_const_t<Type> any_cast(const basic_any<Len, Align> &data) noexcept {
- const auto *const instance = any_cast<std::remove_reference_t<Type>>(&data);
- ENTT_ASSERT(instance, "Invalid instance");
- return static_cast<Type>(*instance);
- }
- /*! @copydoc any_cast */
- template<typename Type, std::size_t Len, std::size_t Align>
- [[nodiscard]] std::remove_const_t<Type> any_cast(basic_any<Len, Align> &data) noexcept {
- // forces const on non-reference types to make them work also with wrappers for const references
- auto *const instance = any_cast<std::remove_reference_t<const Type>>(&data);
- ENTT_ASSERT(instance, "Invalid instance");
- return static_cast<Type>(*instance);
- }
- /*! @copydoc any_cast */
- template<typename Type, std::size_t Len, std::size_t Align>
- // NOLINTNEXTLINE(cppcoreguidelines-rvalue-reference-param-not-moved)
- [[nodiscard]] std::remove_const_t<Type> any_cast(basic_any<Len, Align> &&data) noexcept {
- if constexpr(std::is_copy_constructible_v<std::remove_const_t<std::remove_reference_t<Type>>>) {
- if(auto *const instance = any_cast<std::remove_reference_t<Type>>(&data); instance) {
- return static_cast<Type>(std::move(*instance));
- }
- return any_cast<Type>(data);
- } else {
- auto *const instance = any_cast<std::remove_reference_t<Type>>(&data);
- ENTT_ASSERT(instance, "Invalid instance");
- return static_cast<Type>(std::move(*instance));
- }
- }
- /*! @copydoc any_cast */
- template<typename Type, std::size_t Len, std::size_t Align>
- [[nodiscard]] const Type *any_cast(const basic_any<Len, Align> *data) noexcept {
- return data->template data<std::remove_const_t<Type>>();
- }
- /*! @copydoc any_cast */
- template<typename Type, std::size_t Len, std::size_t Align>
- [[nodiscard]] Type *any_cast(basic_any<Len, Align> *data) noexcept {
- if constexpr(std::is_const_v<Type>) {
- // last attempt to make wrappers for const references return their values
- return any_cast<Type>(&std::as_const(*data));
- } else {
- return data->template data<Type>();
- }
- }
- /**
- * @brief Constructs a wrapper from a given type, passing it all arguments.
- * @tparam Type Type of object to use to initialize the wrapper.
- * @tparam Len Size of the buffer reserved for the small buffer optimization.
- * @tparam Align Optional alignment requirement.
- * @tparam Args Types of arguments to use to construct the new instance.
- * @param args Parameters to use to construct the instance.
- * @return A properly initialized wrapper for an object of the given type.
- */
- template<typename Type, std::size_t Len = basic_any<>::length, std::size_t Align = basic_any<Len>::alignment, typename... Args>
- [[nodiscard]] basic_any<Len, Align> make_any(Args &&...args) {
- return basic_any<Len, Align>{std::in_place_type<Type>, std::forward<Args>(args)...};
- }
- /**
- * @brief Forwards its argument and avoids copies for lvalue references.
- * @tparam Len Size of the buffer reserved for the small buffer optimization.
- * @tparam Align Optional alignment requirement.
- * @tparam Type Type of argument to use to construct the new instance.
- * @param value Parameter to use to construct the instance.
- * @return A properly initialized and not necessarily owning wrapper.
- */
- template<std::size_t Len = basic_any<>::length, std::size_t Align = basic_any<Len>::alignment, typename Type>
- [[nodiscard]] basic_any<Len, Align> forward_as_any(Type &&value) {
- return basic_any<Len, Align>{std::in_place_type<Type &&>, std::forward<Type>(value)};
- }
- } // namespace entt
- #endif
- // #include "../core/type_info.hpp"
- #ifndef ENTT_CORE_TYPE_INFO_HPP
- #define ENTT_CORE_TYPE_INFO_HPP
- #include <string_view>
- #include <type_traits>
- #include <utility>
- // #include "../config/config.h"
- // #include "fwd.hpp"
- // #include "hashed_string.hpp"
- namespace entt {
- /*! @cond TURN_OFF_DOXYGEN */
- namespace internal {
- struct ENTT_API type_index final {
- [[nodiscard]] static id_type next() noexcept {
- static ENTT_MAYBE_ATOMIC(id_type) value{};
- return value++;
- }
- };
- template<typename Type>
- [[nodiscard]] constexpr const char *pretty_function() noexcept {
- #if defined ENTT_PRETTY_FUNCTION
- return static_cast<const char *>(ENTT_PRETTY_FUNCTION);
- #else
- return "";
- #endif
- }
- template<typename Type>
- [[nodiscard]] constexpr auto stripped_type_name() noexcept {
- #if defined ENTT_PRETTY_FUNCTION
- const std::string_view full_name{pretty_function<Type>()};
- auto first = full_name.find_first_not_of(' ', full_name.find_first_of(ENTT_PRETTY_FUNCTION_PREFIX) + 1);
- auto value = full_name.substr(first, full_name.find_last_of(ENTT_PRETTY_FUNCTION_SUFFIX) - first);
- return value;
- #else
- return std::string_view{};
- #endif
- }
- template<typename Type, auto = stripped_type_name<Type>().find_first_of('.')>
- [[nodiscard]] constexpr std::string_view type_name(int) noexcept {
- constexpr auto value = stripped_type_name<Type>();
- return value;
- }
- template<typename Type>
- [[nodiscard]] std::string_view type_name(char) noexcept {
- static const auto value = stripped_type_name<Type>();
- return value;
- }
- template<typename Type, auto = stripped_type_name<Type>().find_first_of('.')>
- [[nodiscard]] constexpr id_type type_hash(int) noexcept {
- constexpr auto stripped = stripped_type_name<Type>();
- constexpr auto value = hashed_string::value(stripped.data(), stripped.size());
- return value;
- }
- template<typename Type>
- [[nodiscard]] id_type type_hash(char) noexcept {
- static const auto value = [](const auto stripped) {
- return hashed_string::value(stripped.data(), stripped.size());
- }(stripped_type_name<Type>());
- return value;
- }
- } // namespace internal
- /*! @endcond */
- /**
- * @brief Type sequential identifier.
- * @tparam Type Type for which to generate a sequential identifier.
- */
- template<typename Type, typename = void>
- struct ENTT_API type_index final {
- /**
- * @brief Returns the sequential identifier of a given type.
- * @return The sequential identifier of a given type.
- */
- [[nodiscard]] static id_type value() noexcept {
- static const id_type value = internal::type_index::next();
- return value;
- }
- /*! @copydoc value */
- [[nodiscard]] constexpr operator id_type() const noexcept {
- return value();
- }
- };
- /**
- * @brief Type hash.
- * @tparam Type Type for which to generate a hash value.
- */
- template<typename Type, typename = void>
- struct type_hash final {
- /**
- * @brief Returns the numeric representation of a given type.
- * @return The numeric representation of the given type.
- */
- #if defined ENTT_PRETTY_FUNCTION
- [[nodiscard]] static constexpr id_type value() noexcept {
- return internal::type_hash<Type>(0);
- #else
- [[nodiscard]] static constexpr id_type value() noexcept {
- return type_index<Type>::value();
- #endif
- }
- /*! @copydoc value */
- [[nodiscard]] constexpr operator id_type() const noexcept {
- return value();
- }
- };
- /**
- * @brief Type name.
- * @tparam Type Type for which to generate a name.
- */
- template<typename Type, typename = void>
- struct type_name final {
- /**
- * @brief Returns the name of a given type.
- * @return The name of the given type.
- */
- [[nodiscard]] static constexpr std::string_view value() noexcept {
- return internal::type_name<Type>(0);
- }
- /*! @copydoc value */
- [[nodiscard]] constexpr operator std::string_view() const noexcept {
- return value();
- }
- };
- /*! @brief Implementation specific information about a type. */
- struct type_info final {
- /**
- * @brief Constructs a type info object for a given type.
- * @tparam Type Type for which to construct a type info object.
- */
- template<typename Type>
- // NOLINTBEGIN(modernize-use-transparent-functors)
- constexpr type_info(std::in_place_type_t<Type>) noexcept
- : seq{type_index<std::remove_const_t<std::remove_reference_t<Type>>>::value()},
- identifier{type_hash<std::remove_const_t<std::remove_reference_t<Type>>>::value()},
- alias{type_name<std::remove_const_t<std::remove_reference_t<Type>>>::value()} {}
- // NOLINTEND(modernize-use-transparent-functors)
- /**
- * @brief Type index.
- * @return Type index.
- */
- [[nodiscard]] constexpr id_type index() const noexcept {
- return seq;
- }
- /**
- * @brief Type hash.
- * @return Type hash.
- */
- [[nodiscard]] constexpr id_type hash() const noexcept {
- return identifier;
- }
- /**
- * @brief Type name.
- * @return Type name.
- */
- [[nodiscard]] constexpr std::string_view name() const noexcept {
- return alias;
- }
- private:
- id_type seq;
- id_type identifier;
- std::string_view alias;
- };
- /**
- * @brief Compares the contents of two type info objects.
- * @param lhs A type info object.
- * @param rhs A type info object.
- * @return True if the two type info objects are identical, false otherwise.
- */
- [[nodiscard]] constexpr bool operator==(const type_info &lhs, const type_info &rhs) noexcept {
- return lhs.hash() == rhs.hash();
- }
- /**
- * @brief Compares the contents of two type info objects.
- * @param lhs A type info object.
- * @param rhs A type info object.
- * @return True if the two type info objects differ, false otherwise.
- */
- [[nodiscard]] constexpr bool operator!=(const type_info &lhs, const type_info &rhs) noexcept {
- return !(lhs == rhs);
- }
- /**
- * @brief Compares two type info objects.
- * @param lhs A valid type info object.
- * @param rhs A valid type info object.
- * @return True if the first element is less than the second, false otherwise.
- */
- [[nodiscard]] constexpr bool operator<(const type_info &lhs, const type_info &rhs) noexcept {
- return lhs.index() < rhs.index();
- }
- /**
- * @brief Compares two type info objects.
- * @param lhs A valid type info object.
- * @param rhs A valid type info object.
- * @return True if the first element is less than or equal to the second, false
- * otherwise.
- */
- [[nodiscard]] constexpr bool operator<=(const type_info &lhs, const type_info &rhs) noexcept {
- return !(rhs < lhs);
- }
- /**
- * @brief Compares two type info objects.
- * @param lhs A valid type info object.
- * @param rhs A valid type info object.
- * @return True if the first element is greater than the second, false
- * otherwise.
- */
- [[nodiscard]] constexpr bool operator>(const type_info &lhs, const type_info &rhs) noexcept {
- return rhs < lhs;
- }
- /**
- * @brief Compares two type info objects.
- * @param lhs A valid type info object.
- * @param rhs A valid type info object.
- * @return True if the first element is greater than or equal to the second,
- * false otherwise.
- */
- [[nodiscard]] constexpr bool operator>=(const type_info &lhs, const type_info &rhs) noexcept {
- return !(lhs < rhs);
- }
- /**
- * @brief Returns the type info object associated to a given type.
- *
- * The returned element refers to an object with static storage duration.<br/>
- * The type doesn't need to be a complete type. If the type is a reference, the
- * result refers to the referenced type. In all cases, top-level cv-qualifiers
- * are ignored.
- *
- * @tparam Type Type for which to generate a type info object.
- * @return A reference to a properly initialized type info object.
- */
- template<typename Type>
- [[nodiscard]] const type_info &type_id() noexcept {
- if constexpr(std::is_same_v<Type, std::remove_const_t<std::remove_reference_t<Type>>>) {
- static const type_info instance{std::in_place_type<Type>};
- return instance;
- } else {
- return type_id<std::remove_const_t<std::remove_reference_t<Type>>>();
- }
- }
- /*! @copydoc type_id */
- template<typename Type>
- // NOLINTNEXTLINE(cppcoreguidelines-missing-std-forward)
- [[nodiscard]] const type_info &type_id(Type &&) noexcept {
- return type_id<std::remove_const_t<std::remove_reference_t<Type>>>();
- }
- } // namespace entt
- #endif
- // #include "../core/type_traits.hpp"
- #ifndef ENTT_CORE_TYPE_TRAITS_HPP
- #define ENTT_CORE_TYPE_TRAITS_HPP
- #include <cstddef>
- #include <iterator>
- #include <tuple>
- #include <type_traits>
- #include <utility>
- // #include "../config/config.h"
- // #include "fwd.hpp"
- namespace entt {
- /**
- * @brief Utility class to disambiguate overloaded functions.
- * @tparam N Number of choices available.
- */
- template<std::size_t N>
- struct choice_t
- // unfortunately, doxygen cannot parse such a construct
- : /*! @cond TURN_OFF_DOXYGEN */ choice_t<N - 1> /*! @endcond */
- {};
- /*! @copybrief choice_t */
- template<>
- struct choice_t<0> {};
- /**
- * @brief Variable template for the choice trick.
- * @tparam N Number of choices available.
- */
- template<std::size_t N>
- inline constexpr choice_t<N> choice{};
- /**
- * @brief Identity type trait.
- *
- * Useful to establish non-deduced contexts in template argument deduction
- * (waiting for C++20) or to provide types through function arguments.
- *
- * @tparam Type A type.
- */
- template<typename Type>
- struct type_identity {
- /*! @brief Identity type. */
- using type = Type;
- };
- /**
- * @brief Helper type.
- * @tparam Type A type.
- */
- template<typename Type>
- using type_identity_t = typename type_identity<Type>::type;
- /**
- * @brief A type-only `sizeof` wrapper that returns 0 where `sizeof` complains.
- * @tparam Type The type of which to return the size.
- */
- template<typename Type, typename = void>
- struct size_of: std::integral_constant<std::size_t, 0u> {};
- /*! @copydoc size_of */
- template<typename Type>
- struct size_of<Type, std::void_t<decltype(sizeof(Type))>>
- // NOLINTNEXTLINE(bugprone-sizeof-expression)
- : std::integral_constant<std::size_t, sizeof(Type)> {};
- /**
- * @brief Helper variable template.
- * @tparam Type The type of which to return the size.
- */
- template<typename Type>
- inline constexpr std::size_t size_of_v = size_of<Type>::value;
- /**
- * @brief Using declaration to be used to _repeat_ the same type a number of
- * times equal to the size of a given parameter pack.
- * @tparam Type A type to repeat.
- */
- template<typename Type, typename>
- using unpack_as_type = Type;
- /**
- * @brief Helper variable template to be used to _repeat_ the same value a
- * number of times equal to the size of a given parameter pack.
- * @tparam Value A value to repeat.
- */
- template<auto Value, typename>
- inline constexpr auto unpack_as_value = Value;
- /**
- * @brief Wraps a static constant.
- * @tparam Value A static constant.
- */
- template<auto Value>
- using integral_constant = std::integral_constant<decltype(Value), Value>;
- /**
- * @brief Alias template to facilitate the creation of named values.
- * @tparam Value A constant value at least convertible to `id_type`.
- */
- template<id_type Value>
- using tag = integral_constant<Value>;
- /**
- * @brief A class to use to push around lists of types, nothing more.
- * @tparam Type Types provided by the type list.
- */
- template<typename... Type>
- struct type_list {
- /*! @brief Type list type. */
- using type = type_list;
- /*! @brief Compile-time number of elements in the type list. */
- static constexpr auto size = sizeof...(Type);
- };
- /*! @brief Primary template isn't defined on purpose. */
- template<std::size_t, typename>
- struct type_list_element;
- /**
- * @brief Provides compile-time indexed access to the types of a type list.
- * @tparam Index Index of the type to return.
- * @tparam First First type provided by the type list.
- * @tparam Other Other types provided by the type list.
- */
- template<std::size_t Index, typename First, typename... Other>
- struct type_list_element<Index, type_list<First, Other...>>
- : type_list_element<Index - 1u, type_list<Other...>> {};
- /**
- * @brief Provides compile-time indexed access to the types of a type list.
- * @tparam First First type provided by the type list.
- * @tparam Other Other types provided by the type list.
- */
- template<typename First, typename... Other>
- struct type_list_element<0u, type_list<First, Other...>> {
- /*! @brief Searched type. */
- using type = First;
- };
- /**
- * @brief Helper type.
- * @tparam Index Index of the type to return.
- * @tparam List Type list to search into.
- */
- template<std::size_t Index, typename List>
- using type_list_element_t = typename type_list_element<Index, List>::type;
- /*! @brief Primary template isn't defined on purpose. */
- template<typename, typename>
- struct type_list_index;
- /**
- * @brief Provides compile-time type access to the types of a type list.
- * @tparam Type Type to look for and for which to return the index.
- * @tparam First First type provided by the type list.
- * @tparam Other Other types provided by the type list.
- */
- template<typename Type, typename First, typename... Other>
- struct type_list_index<Type, type_list<First, Other...>> {
- /*! @brief Unsigned integer type. */
- using value_type = std::size_t;
- /*! @brief Compile-time position of the given type in the sublist. */
- static constexpr value_type value = 1u + type_list_index<Type, type_list<Other...>>::value;
- };
- /**
- * @brief Provides compile-time type access to the types of a type list.
- * @tparam Type Type to look for and for which to return the index.
- * @tparam Other Other types provided by the type list.
- */
- template<typename Type, typename... Other>
- struct type_list_index<Type, type_list<Type, Other...>> {
- static_assert(type_list_index<Type, type_list<Other...>>::value == sizeof...(Other), "Non-unique type");
- /*! @brief Unsigned integer type. */
- using value_type = std::size_t;
- /*! @brief Compile-time position of the given type in the sublist. */
- static constexpr value_type value = 0u;
- };
- /**
- * @brief Provides compile-time type access to the types of a type list.
- * @tparam Type Type to look for and for which to return the index.
- */
- template<typename Type>
- struct type_list_index<Type, type_list<>> {
- /*! @brief Unsigned integer type. */
- using value_type = std::size_t;
- /*! @brief Compile-time position of the given type in the sublist. */
- static constexpr value_type value = 0u;
- };
- /**
- * @brief Helper variable template.
- * @tparam List Type list.
- * @tparam Type Type to look for and for which to return the index.
- */
- template<typename Type, typename List>
- inline constexpr std::size_t type_list_index_v = type_list_index<Type, List>::value;
- /**
- * @brief Concatenates multiple type lists.
- * @tparam Type Types provided by the first type list.
- * @tparam Other Types provided by the second type list.
- * @return A type list composed by the types of both the type lists.
- */
- template<typename... Type, typename... Other>
- constexpr type_list<Type..., Other...> operator+(type_list<Type...>, type_list<Other...>) {
- return {};
- }
- /*! @brief Primary template isn't defined on purpose. */
- template<typename...>
- struct type_list_cat;
- /*! @brief Concatenates multiple type lists. */
- template<>
- struct type_list_cat<> {
- /*! @brief A type list composed by the types of all the type lists. */
- using type = type_list<>;
- };
- /**
- * @brief Concatenates multiple type lists.
- * @tparam Type Types provided by the first type list.
- * @tparam Other Types provided by the second type list.
- * @tparam List Other type lists, if any.
- */
- template<typename... Type, typename... Other, typename... List>
- struct type_list_cat<type_list<Type...>, type_list<Other...>, List...> {
- /*! @brief A type list composed by the types of all the type lists. */
- using type = typename type_list_cat<type_list<Type..., Other...>, List...>::type;
- };
- /**
- * @brief Concatenates multiple type lists.
- * @tparam Type Types provided by the type list.
- */
- template<typename... Type>
- struct type_list_cat<type_list<Type...>> {
- /*! @brief A type list composed by the types of all the type lists. */
- using type = type_list<Type...>;
- };
- /**
- * @brief Helper type.
- * @tparam List Type lists to concatenate.
- */
- template<typename... List>
- using type_list_cat_t = typename type_list_cat<List...>::type;
- /*! @cond TURN_OFF_DOXYGEN */
- namespace internal {
- template<typename...>
- struct type_list_unique;
- template<typename First, typename... Other, typename... Type>
- struct type_list_unique<type_list<First, Other...>, Type...>
- : std::conditional_t<(std::is_same_v<First, Type> || ...), type_list_unique<type_list<Other...>, Type...>, type_list_unique<type_list<Other...>, Type..., First>> {};
- template<typename... Type>
- struct type_list_unique<type_list<>, Type...> {
- using type = type_list<Type...>;
- };
- } // namespace internal
- /*! @endcond */
- /**
- * @brief Removes duplicates types from a type list.
- * @tparam List Type list.
- */
- template<typename List>
- struct type_list_unique {
- /*! @brief A type list without duplicate types. */
- using type = typename internal::type_list_unique<List>::type;
- };
- /**
- * @brief Helper type.
- * @tparam List Type list.
- */
- template<typename List>
- using type_list_unique_t = typename type_list_unique<List>::type;
- /**
- * @brief Provides the member constant `value` to true if a type list contains a
- * given type, false otherwise.
- * @tparam List Type list.
- * @tparam Type Type to look for.
- */
- template<typename List, typename Type>
- struct type_list_contains;
- /**
- * @copybrief type_list_contains
- * @tparam Type Types provided by the type list.
- * @tparam Other Type to look for.
- */
- template<typename... Type, typename Other>
- struct type_list_contains<type_list<Type...>, Other>
- : std::bool_constant<(std::is_same_v<Type, Other> || ...)> {};
- /**
- * @brief Helper variable template.
- * @tparam List Type list.
- * @tparam Type Type to look for.
- */
- template<typename List, typename Type>
- inline constexpr bool type_list_contains_v = type_list_contains<List, Type>::value;
- /*! @brief Primary template isn't defined on purpose. */
- template<typename...>
- struct type_list_diff;
- /**
- * @brief Computes the difference between two type lists.
- * @tparam Type Types provided by the first type list.
- * @tparam Other Types provided by the second type list.
- */
- template<typename... Type, typename... Other>
- struct type_list_diff<type_list<Type...>, type_list<Other...>> {
- /*! @brief A type list that is the difference between the two type lists. */
- using type = type_list_cat_t<std::conditional_t<type_list_contains_v<type_list<Other...>, Type>, type_list<>, type_list<Type>>...>;
- };
- /**
- * @brief Helper type.
- * @tparam List Type lists between which to compute the difference.
- */
- template<typename... List>
- using type_list_diff_t = typename type_list_diff<List...>::type;
- /*! @brief Primary template isn't defined on purpose. */
- template<typename, template<typename...> class>
- struct type_list_transform;
- /**
- * @brief Applies a given _function_ to a type list and generate a new list.
- * @tparam Type Types provided by the type list.
- * @tparam Op Unary operation as template class with a type member named `type`.
- */
- template<typename... Type, template<typename...> class Op>
- struct type_list_transform<type_list<Type...>, Op> {
- /*! @brief Resulting type list after applying the transform function. */
- // NOLINTNEXTLINE(modernize-type-traits)
- using type = type_list<typename Op<Type>::type...>;
- };
- /**
- * @brief Helper type.
- * @tparam List Type list.
- * @tparam Op Unary operation as template class with a type member named `type`.
- */
- template<typename List, template<typename...> class Op>
- using type_list_transform_t = typename type_list_transform<List, Op>::type;
- /**
- * @brief A class to use to push around lists of constant values, nothing more.
- * @tparam Value Values provided by the value list.
- */
- template<auto... Value>
- struct value_list {
- /*! @brief Value list type. */
- using type = value_list;
- /*! @brief Compile-time number of elements in the value list. */
- static constexpr auto size = sizeof...(Value);
- };
- /*! @brief Primary template isn't defined on purpose. */
- template<std::size_t, typename>
- struct value_list_element;
- /**
- * @brief Provides compile-time indexed access to the values of a value list.
- * @tparam Index Index of the value to return.
- * @tparam Value First value provided by the value list.
- * @tparam Other Other values provided by the value list.
- */
- template<std::size_t Index, auto Value, auto... Other>
- struct value_list_element<Index, value_list<Value, Other...>>
- : value_list_element<Index - 1u, value_list<Other...>> {};
- /**
- * @brief Provides compile-time indexed access to the types of a type list.
- * @tparam Value First value provided by the value list.
- * @tparam Other Other values provided by the value list.
- */
- template<auto Value, auto... Other>
- struct value_list_element<0u, value_list<Value, Other...>> {
- /*! @brief Searched type. */
- using type = decltype(Value);
- /*! @brief Searched value. */
- static constexpr auto value = Value;
- };
- /**
- * @brief Helper type.
- * @tparam Index Index of the type to return.
- * @tparam List Value list to search into.
- */
- template<std::size_t Index, typename List>
- using value_list_element_t = typename value_list_element<Index, List>::type;
- /**
- * @brief Helper type.
- * @tparam Index Index of the value to return.
- * @tparam List Value list to search into.
- */
- template<std::size_t Index, typename List>
- inline constexpr auto value_list_element_v = value_list_element<Index, List>::value;
- /*! @brief Primary template isn't defined on purpose. */
- template<auto, typename>
- struct value_list_index;
- /**
- * @brief Provides compile-time type access to the values of a value list.
- * @tparam Value Value to look for and for which to return the index.
- * @tparam First First value provided by the value list.
- * @tparam Other Other values provided by the value list.
- */
- template<auto Value, auto First, auto... Other>
- struct value_list_index<Value, value_list<First, Other...>> {
- /*! @brief Unsigned integer type. */
- using value_type = std::size_t;
- /*! @brief Compile-time position of the given value in the sublist. */
- static constexpr value_type value = 1u + value_list_index<Value, value_list<Other...>>::value;
- };
- /**
- * @brief Provides compile-time type access to the values of a value list.
- * @tparam Value Value to look for and for which to return the index.
- * @tparam Other Other values provided by the value list.
- */
- template<auto Value, auto... Other>
- struct value_list_index<Value, value_list<Value, Other...>> {
- static_assert(value_list_index<Value, value_list<Other...>>::value == sizeof...(Other), "Non-unique type");
- /*! @brief Unsigned integer type. */
- using value_type = std::size_t;
- /*! @brief Compile-time position of the given value in the sublist. */
- static constexpr value_type value = 0u;
- };
- /**
- * @brief Provides compile-time type access to the values of a value list.
- * @tparam Value Value to look for and for which to return the index.
- */
- template<auto Value>
- struct value_list_index<Value, value_list<>> {
- /*! @brief Unsigned integer type. */
- using value_type = std::size_t;
- /*! @brief Compile-time position of the given type in the sublist. */
- static constexpr value_type value = 0u;
- };
- /**
- * @brief Helper variable template.
- * @tparam List Value list.
- * @tparam Value Value to look for and for which to return the index.
- */
- template<auto Value, typename List>
- inline constexpr std::size_t value_list_index_v = value_list_index<Value, List>::value;
- /**
- * @brief Concatenates multiple value lists.
- * @tparam Value Values provided by the first value list.
- * @tparam Other Values provided by the second value list.
- * @return A value list composed by the values of both the value lists.
- */
- template<auto... Value, auto... Other>
- constexpr value_list<Value..., Other...> operator+(value_list<Value...>, value_list<Other...>) {
- return {};
- }
- /*! @brief Primary template isn't defined on purpose. */
- template<typename...>
- struct value_list_cat;
- /*! @brief Concatenates multiple value lists. */
- template<>
- struct value_list_cat<> {
- /*! @brief A value list composed by the values of all the value lists. */
- using type = value_list<>;
- };
- /**
- * @brief Concatenates multiple value lists.
- * @tparam Value Values provided by the first value list.
- * @tparam Other Values provided by the second value list.
- * @tparam List Other value lists, if any.
- */
- template<auto... Value, auto... Other, typename... List>
- struct value_list_cat<value_list<Value...>, value_list<Other...>, List...> {
- /*! @brief A value list composed by the values of all the value lists. */
- using type = typename value_list_cat<value_list<Value..., Other...>, List...>::type;
- };
- /**
- * @brief Concatenates multiple value lists.
- * @tparam Value Values provided by the value list.
- */
- template<auto... Value>
- struct value_list_cat<value_list<Value...>> {
- /*! @brief A value list composed by the values of all the value lists. */
- using type = value_list<Value...>;
- };
- /**
- * @brief Helper type.
- * @tparam List Value lists to concatenate.
- */
- template<typename... List>
- using value_list_cat_t = typename value_list_cat<List...>::type;
- /*! @brief Primary template isn't defined on purpose. */
- template<typename>
- struct value_list_unique;
- /**
- * @brief Removes duplicates values from a value list.
- * @tparam Value One of the values provided by the given value list.
- * @tparam Other The other values provided by the given value list.
- */
- template<auto Value, auto... Other>
- struct value_list_unique<value_list<Value, Other...>> {
- /*! @brief A value list without duplicate types. */
- using type = std::conditional_t<
- ((Value == Other) || ...),
- typename value_list_unique<value_list<Other...>>::type,
- value_list_cat_t<value_list<Value>, typename value_list_unique<value_list<Other...>>::type>>;
- };
- /*! @brief Removes duplicates values from a value list. */
- template<>
- struct value_list_unique<value_list<>> {
- /*! @brief A value list without duplicate types. */
- using type = value_list<>;
- };
- /**
- * @brief Helper type.
- * @tparam Type A value list.
- */
- template<typename Type>
- using value_list_unique_t = typename value_list_unique<Type>::type;
- /**
- * @brief Provides the member constant `value` to true if a value list contains
- * a given value, false otherwise.
- * @tparam List Value list.
- * @tparam Value Value to look for.
- */
- template<typename List, auto Value>
- struct value_list_contains;
- /**
- * @copybrief value_list_contains
- * @tparam Value Values provided by the value list.
- * @tparam Other Value to look for.
- */
- template<auto... Value, auto Other>
- struct value_list_contains<value_list<Value...>, Other>
- : std::bool_constant<((Value == Other) || ...)> {};
- /**
- * @brief Helper variable template.
- * @tparam List Value list.
- * @tparam Value Value to look for.
- */
- template<typename List, auto Value>
- inline constexpr bool value_list_contains_v = value_list_contains<List, Value>::value;
- /*! @brief Primary template isn't defined on purpose. */
- template<typename...>
- struct value_list_diff;
- /**
- * @brief Computes the difference between two value lists.
- * @tparam Value Values provided by the first value list.
- * @tparam Other Values provided by the second value list.
- */
- template<auto... Value, auto... Other>
- struct value_list_diff<value_list<Value...>, value_list<Other...>> {
- /*! @brief A value list that is the difference between the two value lists. */
- using type = value_list_cat_t<std::conditional_t<value_list_contains_v<value_list<Other...>, Value>, value_list<>, value_list<Value>>...>;
- };
- /**
- * @brief Helper type.
- * @tparam List Value lists between which to compute the difference.
- */
- template<typename... List>
- using value_list_diff_t = typename value_list_diff<List...>::type;
- /*! @brief Same as std::is_invocable, but with tuples. */
- template<typename, typename>
- struct is_applicable: std::false_type {};
- /**
- * @copybrief is_applicable
- * @tparam Func A valid function type.
- * @tparam Tuple Tuple-like type.
- * @tparam Args The list of arguments to use to probe the function type.
- */
- template<typename Func, template<typename...> class Tuple, typename... Args>
- struct is_applicable<Func, Tuple<Args...>>: std::is_invocable<Func, Args...> {};
- /**
- * @copybrief is_applicable
- * @tparam Func A valid function type.
- * @tparam Tuple Tuple-like type.
- * @tparam Args The list of arguments to use to probe the function type.
- */
- template<typename Func, template<typename...> class Tuple, typename... Args>
- struct is_applicable<Func, const Tuple<Args...>>: std::is_invocable<Func, Args...> {};
- /**
- * @brief Helper variable template.
- * @tparam Func A valid function type.
- * @tparam Args The list of arguments to use to probe the function type.
- */
- template<typename Func, typename Args>
- inline constexpr bool is_applicable_v = is_applicable<Func, Args>::value;
- /*! @brief Same as std::is_invocable_r, but with tuples for arguments. */
- template<typename, typename, typename>
- struct is_applicable_r: std::false_type {};
- /**
- * @copybrief is_applicable_r
- * @tparam Ret The type to which the return type of the function should be
- * convertible.
- * @tparam Func A valid function type.
- * @tparam Args The list of arguments to use to probe the function type.
- */
- template<typename Ret, typename Func, typename... Args>
- struct is_applicable_r<Ret, Func, std::tuple<Args...>>: std::is_invocable_r<Ret, Func, Args...> {};
- /**
- * @brief Helper variable template.
- * @tparam Ret The type to which the return type of the function should be
- * convertible.
- * @tparam Func A valid function type.
- * @tparam Args The list of arguments to use to probe the function type.
- */
- template<typename Ret, typename Func, typename Args>
- inline constexpr bool is_applicable_r_v = is_applicable_r<Ret, Func, Args>::value;
- /**
- * @brief Provides the member constant `value` to true if a given type is
- * complete, false otherwise.
- * @tparam Type The type to test.
- */
- template<typename Type, typename = void>
- struct is_complete: std::false_type {};
- /*! @copydoc is_complete */
- template<typename Type>
- struct is_complete<Type, std::void_t<decltype(sizeof(Type))>>: std::true_type {};
- /**
- * @brief Helper variable template.
- * @tparam Type The type to test.
- */
- template<typename Type>
- inline constexpr bool is_complete_v = is_complete<Type>::value;
- /**
- * @brief Provides the member constant `value` to true if a given type is an
- * iterator, false otherwise.
- * @tparam Type The type to test.
- */
- template<typename Type, typename = void>
- struct is_iterator: std::false_type {};
- /*! @cond TURN_OFF_DOXYGEN */
- namespace internal {
- template<typename, typename = void>
- struct has_iterator_category: std::false_type {};
- template<typename Type>
- struct has_iterator_category<Type, std::void_t<typename std::iterator_traits<Type>::iterator_category>>: std::true_type {};
- } // namespace internal
- /*! @endcond */
- /*! @copydoc is_iterator */
- template<typename Type>
- struct is_iterator<Type, std::enable_if_t<!std::is_void_v<std::remove_const_t<std::remove_pointer_t<Type>>>>>
- : internal::has_iterator_category<Type> {};
- /**
- * @brief Helper variable template.
- * @tparam Type The type to test.
- */
- template<typename Type>
- inline constexpr bool is_iterator_v = is_iterator<Type>::value;
- /**
- * @brief Provides the member constant `value` to true if a given type is both
- * an empty and non-final class, false otherwise.
- * @tparam Type The type to test
- */
- template<typename Type>
- struct is_ebco_eligible
- : std::bool_constant<std::is_empty_v<Type> && !std::is_final_v<Type>> {};
- /**
- * @brief Helper variable template.
- * @tparam Type The type to test.
- */
- template<typename Type>
- inline constexpr bool is_ebco_eligible_v = is_ebco_eligible<Type>::value;
- /**
- * @brief Provides the member constant `value` to true if `Type::is_transparent`
- * is valid and denotes a type, false otherwise.
- * @tparam Type The type to test.
- */
- template<typename Type, typename = void>
- struct is_transparent: std::false_type {};
- /*! @copydoc is_transparent */
- template<typename Type>
- struct is_transparent<Type, std::void_t<typename Type::is_transparent>>: std::true_type {};
- /**
- * @brief Helper variable template.
- * @tparam Type The type to test.
- */
- template<typename Type>
- inline constexpr bool is_transparent_v = is_transparent<Type>::value;
- /*! @cond TURN_OFF_DOXYGEN */
- namespace internal {
- template<typename, typename = void>
- struct has_tuple_size_value: std::false_type {};
- template<typename Type>
- struct has_tuple_size_value<Type, std::void_t<decltype(std::tuple_size<const Type>::value)>>: std::true_type {};
- template<typename, typename = void>
- struct has_value_type: std::false_type {};
- template<typename Type>
- struct has_value_type<Type, std::void_t<typename Type::value_type>>: std::true_type {};
- template<typename>
- [[nodiscard]] constexpr bool dispatch_is_equality_comparable();
- template<typename Type, std::size_t... Index>
- [[nodiscard]] constexpr bool unpack_maybe_equality_comparable(std::index_sequence<Index...>) {
- return (dispatch_is_equality_comparable<std::tuple_element_t<Index, Type>>() && ...);
- }
- template<typename>
- [[nodiscard]] constexpr bool maybe_equality_comparable(char) {
- return false;
- }
- template<typename Type>
- [[nodiscard]] constexpr auto maybe_equality_comparable(int) -> decltype(std::declval<Type>() == std::declval<Type>()) {
- return true;
- }
- template<typename Type>
- [[nodiscard]] constexpr bool dispatch_is_equality_comparable() {
- // NOLINTBEGIN(modernize-use-transparent-functors)
- if constexpr(std::is_array_v<Type>) {
- return false;
- } else if constexpr(is_complete_v<std::tuple_size<std::remove_const_t<Type>>>) {
- if constexpr(has_tuple_size_value<Type>::value) {
- return maybe_equality_comparable<Type>(0) && unpack_maybe_equality_comparable<Type>(std::make_index_sequence<std::tuple_size<Type>::value>{});
- } else {
- return maybe_equality_comparable<Type>(0);
- }
- } else if constexpr(has_value_type<Type>::value) {
- if constexpr(is_iterator_v<Type> || std::is_same_v<typename Type::value_type, Type> || dispatch_is_equality_comparable<typename Type::value_type>()) {
- return maybe_equality_comparable<Type>(0);
- } else {
- return false;
- }
- } else {
- return maybe_equality_comparable<Type>(0);
- }
- // NOLINTEND(modernize-use-transparent-functors)
- }
- } // namespace internal
- /*! @endcond */
- /**
- * @brief Provides the member constant `value` to true if a given type is
- * equality comparable, false otherwise.
- * @tparam Type The type to test.
- */
- template<typename Type>
- struct is_equality_comparable: std::bool_constant<internal::dispatch_is_equality_comparable<Type>()> {};
- /*! @copydoc is_equality_comparable */
- template<typename Type>
- struct is_equality_comparable<const Type>: is_equality_comparable<Type> {};
- /**
- * @brief Helper variable template.
- * @tparam Type The type to test.
- */
- template<typename Type>
- inline constexpr bool is_equality_comparable_v = is_equality_comparable<Type>::value;
- /**
- * @brief Transcribes the constness of a type to another type.
- * @tparam To The type to which to transcribe the constness.
- * @tparam From The type from which to transcribe the constness.
- */
- template<typename To, typename From>
- struct constness_as {
- /*! @brief The type resulting from the transcription of the constness. */
- using type = std::remove_const_t<To>;
- };
- /*! @copydoc constness_as */
- template<typename To, typename From>
- struct constness_as<To, const From> {
- /*! @brief The type resulting from the transcription of the constness. */
- using type = const To;
- };
- /**
- * @brief Alias template to facilitate the transcription of the constness.
- * @tparam To The type to which to transcribe the constness.
- * @tparam From The type from which to transcribe the constness.
- */
- template<typename To, typename From>
- using constness_as_t = typename constness_as<To, From>::type;
- /**
- * @brief Extracts the class of a non-static member object or function.
- * @tparam Member A pointer to a non-static member object or function.
- */
- template<typename Member>
- class member_class {
- static_assert(std::is_member_pointer_v<Member>, "Invalid pointer type to non-static member object or function");
- template<typename Class, typename Ret, typename... Args>
- static Class *clazz(Ret (Class::*)(Args...));
- template<typename Class, typename Ret, typename... Args>
- static Class *clazz(Ret (Class::*)(Args...) const);
- template<typename Class, typename Type>
- static Class *clazz(Type Class::*);
- public:
- /*! @brief The class of the given non-static member object or function. */
- using type = std::remove_pointer_t<decltype(clazz(std::declval<Member>()))>;
- };
- /**
- * @brief Helper type.
- * @tparam Member A pointer to a non-static member object or function.
- */
- template<typename Member>
- using member_class_t = typename member_class<Member>::type;
- /**
- * @brief Extracts the n-th argument of a _callable_ type.
- * @tparam Index The index of the argument to extract.
- * @tparam Candidate A valid _callable_ type.
- */
- template<std::size_t Index, typename Candidate>
- class nth_argument {
- template<typename Ret, typename... Args>
- static constexpr type_list<Args...> pick_up(Ret (*)(Args...));
- template<typename Ret, typename Class, typename... Args>
- static constexpr type_list<Args...> pick_up(Ret (Class ::*)(Args...));
- template<typename Ret, typename Class, typename... Args>
- static constexpr type_list<Args...> pick_up(Ret (Class ::*)(Args...) const);
- template<typename Type, typename Class>
- static constexpr type_list<Type> pick_up(Type Class ::*);
- template<typename Type>
- static constexpr decltype(pick_up(&Type::operator())) pick_up(Type &&);
- public:
- /*! @brief N-th argument of the _callable_ type. */
- using type = type_list_element_t<Index, decltype(pick_up(std::declval<Candidate>()))>;
- };
- /**
- * @brief Helper type.
- * @tparam Index The index of the argument to extract.
- * @tparam Candidate A valid function, member function or data member type.
- */
- template<std::size_t Index, typename Candidate>
- using nth_argument_t = typename nth_argument<Index, Candidate>::type;
- } // namespace entt
- template<typename... Type>
- struct std::tuple_size<entt::type_list<Type...>>: std::integral_constant<std::size_t, entt::type_list<Type...>::size> {};
- template<std::size_t Index, typename... Type>
- struct std::tuple_element<Index, entt::type_list<Type...>>: entt::type_list_element<Index, entt::type_list<Type...>> {};
- template<auto... Value>
- struct std::tuple_size<entt::value_list<Value...>>: std::integral_constant<std::size_t, entt::value_list<Value...>::size> {};
- template<std::size_t Index, auto... Value>
- struct std::tuple_element<Index, entt::value_list<Value...>>: entt::value_list_element<Index, entt::value_list<Value...>> {};
- #endif
- // #include "fwd.hpp"
- #ifndef ENTT_POLY_FWD_HPP
- #define ENTT_POLY_FWD_HPP
- #include <cstddef>
- namespace entt {
- // NOLINTNEXTLINE(cppcoreguidelines-avoid-c-arrays, modernize-avoid-c-arrays)
- template<typename, std::size_t Len = sizeof(double[2]), std::size_t = alignof(double[2])>
- class basic_poly;
- /**
- * @brief Alias declaration for the most common use case.
- * @tparam Concept Concept descriptor.
- */
- template<typename Concept>
- using poly = basic_poly<Concept>;
- } // namespace entt
- #endif
- namespace entt {
- /*! @brief Inspector class used to infer the type of the virtual table. */
- struct poly_inspector {
- /**
- * @brief Generic conversion operator (definition only).
- * @tparam Type Type to which conversion is requested.
- */
- template<typename Type>
- operator Type &&() const;
- /**
- * @brief Dummy invocation function (definition only).
- * @tparam Member Index of the function to invoke.
- * @tparam Args Types of arguments to pass to the function.
- * @param args The arguments to pass to the function.
- * @return A poly inspector convertible to any type.
- */
- template<std::size_t Member, typename... Args>
- [[nodiscard]] poly_inspector invoke(Args &&...args) const;
- /*! @copydoc invoke */
- template<std::size_t Member, typename... Args>
- [[nodiscard]] poly_inspector invoke(Args &&...args);
- };
- /**
- * @brief Static virtual table factory.
- * @tparam Concept Concept descriptor.
- * @tparam Len Size of the storage reserved for the small buffer optimization.
- * @tparam Align Alignment requirement.
- */
- template<typename Concept, std::size_t Len, std::size_t Align>
- class poly_vtable {
- using inspector = typename Concept::template type<poly_inspector>;
- template<typename Ret, typename Clazz, typename... Args>
- static auto vtable_entry(Ret (*)(Clazz &, Args...))
- -> std::enable_if_t<std::is_base_of_v<std::remove_const_t<Clazz>, inspector>, Ret (*)(constness_as_t<basic_any<Len, Align>, Clazz> &, Args...)>;
- template<typename Ret, typename... Args>
- static auto vtable_entry(Ret (*)(Args...))
- -> Ret (*)(const basic_any<Len, Align> &, Args...);
- template<typename Ret, typename Clazz, typename... Args>
- static auto vtable_entry(Ret (Clazz::*)(Args...))
- -> std::enable_if_t<std::is_base_of_v<Clazz, inspector>, Ret (*)(basic_any<Len, Align> &, Args...)>;
- template<typename Ret, typename Clazz, typename... Args>
- static auto vtable_entry(Ret (Clazz::*)(Args...) const)
- -> std::enable_if_t<std::is_base_of_v<Clazz, inspector>, Ret (*)(const basic_any<Len, Align> &, Args...)>;
- template<auto... Candidate>
- static auto make_vtable(value_list<Candidate...>) noexcept
- -> decltype(std::make_tuple(vtable_entry(Candidate)...));
- template<typename... Func>
- [[nodiscard]] static constexpr auto make_vtable(type_list<Func...>) noexcept {
- if constexpr(sizeof...(Func) == 0u) {
- return decltype(make_vtable(typename Concept::template impl<inspector>{})){};
- } else if constexpr((std::is_function_v<Func> && ...)) {
- return decltype(std::make_tuple(vtable_entry(std::declval<Func inspector::*>())...)){};
- }
- }
- template<typename Type, auto Candidate, typename Ret, typename Any, typename... Args>
- static void fill_vtable_entry(Ret (*&entry)(Any &, Args...)) noexcept {
- if constexpr(std::is_invocable_r_v<Ret, decltype(Candidate), Args...>) {
- entry = +[](Any &, Args... args) -> Ret {
- return std::invoke(Candidate, std::forward<Args>(args)...);
- };
- } else {
- entry = +[](Any &instance, Args... args) -> Ret {
- return static_cast<Ret>(std::invoke(Candidate, any_cast<constness_as_t<Type, Any> &>(instance), std::forward<Args>(args)...));
- };
- }
- }
- template<typename Type, auto... Index>
- [[nodiscard]] static auto fill_vtable(std::index_sequence<Index...>) noexcept {
- vtable_type impl{};
- (fill_vtable_entry<Type, value_list_element_v<Index, typename Concept::template impl<Type>>>(std::get<Index>(impl)), ...);
- return impl;
- }
- using vtable_type = decltype(make_vtable(Concept{}));
- static constexpr bool is_mono = std::tuple_size_v<vtable_type> == 1u;
- public:
- /*! @brief Virtual table type. */
- using type = std::conditional_t<is_mono, std::tuple_element_t<0u, vtable_type>, const vtable_type *>;
- /**
- * @brief Returns a static virtual table for a specific concept and type.
- * @tparam Type The type for which to generate the virtual table.
- * @return A static virtual table for the given concept and type.
- */
- template<typename Type>
- [[nodiscard]] static type instance() noexcept {
- static_assert(std::is_same_v<Type, std::decay_t<Type>>, "Type differs from its decayed form");
- static const vtable_type vtable = fill_vtable<Type>(std::make_index_sequence<Concept::template impl<Type>::size>{});
- if constexpr(is_mono) {
- return std::get<0>(vtable);
- } else {
- return &vtable;
- }
- }
- };
- /**
- * @brief Poly base class used to inject functionalities into concepts.
- * @tparam Poly The outermost poly class.
- */
- template<typename Poly>
- struct poly_base {
- /**
- * @brief Invokes a function from the static virtual table.
- * @tparam Member Index of the function to invoke.
- * @tparam Args Types of arguments to pass to the function.
- * @param self A reference to the poly object that made the call.
- * @param args The arguments to pass to the function.
- * @return The return value of the invoked function, if any.
- */
- template<std::size_t Member, typename... Args>
- [[nodiscard]] decltype(auto) invoke(const poly_base &self, Args &&...args) const {
- const auto &poly = static_cast<const Poly &>(self);
- if constexpr(std::is_function_v<std::remove_pointer_t<decltype(poly.vtable)>>) {
- return poly.vtable(poly.storage, std::forward<Args>(args)...);
- } else {
- return std::get<Member>(*poly.vtable)(poly.storage, std::forward<Args>(args)...);
- }
- }
- /*! @copydoc invoke */
- template<std::size_t Member, typename... Args>
- [[nodiscard]] decltype(auto) invoke(poly_base &self, Args &&...args) {
- auto &poly = static_cast<Poly &>(self);
- if constexpr(std::is_function_v<std::remove_pointer_t<decltype(poly.vtable)>>) {
- static_assert(Member == 0u, "Unknown member");
- return poly.vtable(poly.storage, std::forward<Args>(args)...);
- } else {
- return std::get<Member>(*poly.vtable)(poly.storage, std::forward<Args>(args)...);
- }
- }
- };
- /**
- * @brief Shortcut for calling `poly_base<Type>::invoke`.
- * @tparam Member Index of the function to invoke.
- * @tparam Poly A fully defined poly object.
- * @tparam Args Types of arguments to pass to the function.
- * @param self A reference to the poly object that made the call.
- * @param args The arguments to pass to the function.
- * @return The return value of the invoked function, if any.
- */
- template<std::size_t Member, typename Poly, typename... Args>
- decltype(auto) poly_call(Poly &&self, Args &&...args) {
- return std::forward<Poly>(self).template invoke<Member>(self, std::forward<Args>(args)...);
- }
- /**
- * @brief Static polymorphism made simple and within everyone's reach.
- *
- * Static polymorphism is a very powerful tool in C++, albeit sometimes
- * cumbersome to obtain.<br/>
- * This class aims to make it simple and easy to use.
- *
- * @note
- * Both deduced and defined static virtual tables are supported.<br/>
- * Moreover, the `poly` class template also works with unmanaged objects.
- *
- * @tparam Concept Concept descriptor.
- * @tparam Len Size of the storage reserved for the small buffer optimization.
- * @tparam Align Optional alignment requirement.
- */
- template<typename Concept, std::size_t Len, std::size_t Align>
- class basic_poly: private Concept::template type<poly_base<basic_poly<Concept, Len, Align>>> {
- friend struct poly_base<basic_poly>;
- public:
- /*! @brief Concept type. */
- using concept_type = typename Concept::template type<poly_base<basic_poly>>;
- /*! @brief Virtual table type. */
- using vtable_type = typename poly_vtable<Concept, Len, Align>::type;
- /*! @brief Default constructor. */
- basic_poly() noexcept = default;
- /**
- * @brief Constructs a poly by directly initializing the new object.
- * @tparam Type Type of object to use to initialize the poly.
- * @tparam Args Types of arguments to use to construct the new instance.
- * @param args Parameters to use to construct the instance.
- */
- template<typename Type, typename... Args>
- explicit basic_poly(std::in_place_type_t<Type>, Args &&...args)
- : storage{std::in_place_type<Type>, std::forward<Args>(args)...},
- vtable{poly_vtable<Concept, Len, Align>::template instance<std::remove_const_t<std::remove_reference_t<Type>>>()} {}
- /**
- * @brief Constructs a poly from a given value.
- * @tparam Type Type of object to use to initialize the poly.
- * @param value An instance of an object to use to initialize the poly.
- */
- template<typename Type, typename = std::enable_if_t<!std::is_same_v<std::remove_const_t<std::remove_reference_t<Type>>, basic_poly>>>
- basic_poly(Type &&value) noexcept
- : basic_poly{std::in_place_type<std::remove_const_t<std::remove_reference_t<Type>>>, std::forward<Type>(value)} {}
- /**
- * @brief Returns the object type info if any, `type_id<void>()` otherwise.
- * @return The object type info if any, `type_id<void>()` otherwise.
- */
- [[nodiscard]] const type_info &info() const noexcept {
- return storage.info();
- }
- /*! @copydoc info */
- [[deprecated("use ::info instead")]] [[nodiscard]] const type_info &type() const noexcept {
- return info();
- }
- /**
- * @brief Returns an opaque pointer to the contained instance.
- * @return An opaque pointer the contained instance, if any.
- */
- [[nodiscard]] const void *data() const noexcept {
- return storage.data();
- }
- /*! @copydoc data */
- [[nodiscard]] void *data() noexcept {
- return storage.data();
- }
- /**
- * @brief Replaces the contained object by creating a new instance directly.
- * @tparam Type Type of object to use to initialize the poly.
- * @tparam Args Types of arguments to use to construct the new instance.
- * @param args Parameters to use to construct the instance.
- */
- template<typename Type, typename... Args>
- void emplace(Args &&...args) {
- storage.template emplace<Type>(std::forward<Args>(args)...);
- vtable = poly_vtable<Concept, Len, Align>::template instance<std::remove_const_t<std::remove_reference_t<Type>>>();
- }
- /*! @brief Destroys contained object */
- void reset() {
- storage.reset();
- vtable = {};
- }
- /**
- * @brief Returns false if a poly is empty, true otherwise.
- * @return False if the poly is empty, true otherwise.
- */
- [[nodiscard]] explicit operator bool() const noexcept {
- return static_cast<bool>(storage);
- }
- /**
- * @brief Returns a pointer to the underlying concept.
- * @return A pointer to the underlying concept.
- */
- [[nodiscard]] concept_type *operator->() noexcept {
- return this;
- }
- /*! @copydoc operator-> */
- [[nodiscard]] const concept_type *operator->() const noexcept {
- return this;
- }
- /**
- * @brief Aliasing constructor.
- * @return A poly that shares a reference to an unmanaged object.
- */
- [[nodiscard]] basic_poly as_ref() noexcept {
- basic_poly ref{};
- ref.storage = storage.as_ref();
- ref.vtable = vtable;
- return ref;
- }
- /*! @copydoc as_ref */
- [[nodiscard]] basic_poly as_ref() const noexcept {
- basic_poly ref{};
- ref.storage = storage.as_ref();
- ref.vtable = vtable;
- return ref;
- }
- private:
- basic_any<Len, Align> storage{};
- vtable_type vtable{};
- };
- } // namespace entt
- #endif
- // #include "process/process.hpp"
- #ifndef ENTT_PROCESS_PROCESS_HPP
- #define ENTT_PROCESS_PROCESS_HPP
- #include <cstdint>
- #include <memory>
- #include <type_traits>
- #include <utility>
- // #include "../core/compressed_pair.hpp"
- #ifndef ENTT_CORE_COMPRESSED_PAIR_HPP
- #define ENTT_CORE_COMPRESSED_PAIR_HPP
- #include <cstddef>
- #include <tuple>
- #include <type_traits>
- #include <utility>
- // #include "fwd.hpp"
- #ifndef ENTT_CORE_FWD_HPP
- #define ENTT_CORE_FWD_HPP
- #include <cstddef>
- #include <cstdint>
- // #include "../config/config.h"
- #ifndef ENTT_CONFIG_CONFIG_H
- #define ENTT_CONFIG_CONFIG_H
- // #include "version.h"
- #ifndef ENTT_CONFIG_VERSION_H
- #define ENTT_CONFIG_VERSION_H
- // #include "macro.h"
- #ifndef ENTT_CONFIG_MACRO_H
- #define ENTT_CONFIG_MACRO_H
- // NOLINTBEGIN(cppcoreguidelines-macro-usage)
- #define ENTT_STR(arg) #arg
- #define ENTT_XSTR(arg) ENTT_STR(arg)
- // NOLINTEND(cppcoreguidelines-macro-usage)
- #endif
- // NOLINTBEGIN(cppcoreguidelines-macro-*,modernize-macro-*)
- #define ENTT_VERSION_MAJOR 3
- #define ENTT_VERSION_MINOR 16
- #define ENTT_VERSION_PATCH 0
- #define ENTT_VERSION \
- ENTT_XSTR(ENTT_VERSION_MAJOR) \
- "." ENTT_XSTR(ENTT_VERSION_MINOR) "." ENTT_XSTR(ENTT_VERSION_PATCH)
- // NOLINTEND(cppcoreguidelines-macro-*,modernize-macro-*)
- #endif
- // NOLINTBEGIN(cppcoreguidelines-macro-usage)
- #if defined(__cpp_exceptions) && !defined(ENTT_NOEXCEPTION)
- # define ENTT_CONSTEXPR
- # define ENTT_THROW throw
- # define ENTT_TRY try
- # define ENTT_CATCH catch(...)
- #else
- # define ENTT_CONSTEXPR constexpr // use only with throwing functions (waiting for C++20)
- # define ENTT_THROW
- # define ENTT_TRY if(true)
- # define ENTT_CATCH if(false)
- #endif
- #if __has_include(<version>)
- # include <version>
- #
- # if defined(__cpp_consteval)
- # define ENTT_CONSTEVAL consteval
- # endif
- #endif
- #ifndef ENTT_CONSTEVAL
- # define ENTT_CONSTEVAL constexpr
- #endif
- #ifdef ENTT_USE_ATOMIC
- # include <atomic>
- # define ENTT_MAYBE_ATOMIC(Type) std::atomic<Type>
- #else
- # define ENTT_MAYBE_ATOMIC(Type) Type
- #endif
- #ifndef ENTT_ID_TYPE
- # include <cstdint>
- # define ENTT_ID_TYPE std::uint32_t
- #else
- # include <cstdint> // provides coverage for types in the std namespace
- #endif
- #ifndef ENTT_SPARSE_PAGE
- # define ENTT_SPARSE_PAGE 4096
- #endif
- #ifndef ENTT_PACKED_PAGE
- # define ENTT_PACKED_PAGE 1024
- #endif
- #ifdef ENTT_DISABLE_ASSERT
- # undef ENTT_ASSERT
- # define ENTT_ASSERT(condition, msg) (void(0))
- #elif !defined ENTT_ASSERT
- # include <cassert>
- # define ENTT_ASSERT(condition, msg) assert(((condition) && (msg)))
- #endif
- #ifdef ENTT_DISABLE_ASSERT
- # undef ENTT_ASSERT_CONSTEXPR
- # define ENTT_ASSERT_CONSTEXPR(condition, msg) (void(0))
- #elif !defined ENTT_ASSERT_CONSTEXPR
- # define ENTT_ASSERT_CONSTEXPR(condition, msg) ENTT_ASSERT(condition, msg)
- #endif
- #define ENTT_FAIL(msg) ENTT_ASSERT(false, msg);
- #ifdef ENTT_NO_ETO
- # define ENTT_ETO_TYPE(Type) void
- #else
- # define ENTT_ETO_TYPE(Type) Type
- #endif
- #ifdef ENTT_NO_MIXIN
- # define ENTT_STORAGE(Mixin, ...) __VA_ARGS__
- #else
- # define ENTT_STORAGE(Mixin, ...) Mixin<__VA_ARGS__>
- #endif
- #ifdef ENTT_STANDARD_CPP
- # define ENTT_NONSTD false
- #else
- # define ENTT_NONSTD true
- # if defined __clang__ || defined __GNUC__
- # define ENTT_PRETTY_FUNCTION __PRETTY_FUNCTION__
- # define ENTT_PRETTY_FUNCTION_PREFIX '='
- # define ENTT_PRETTY_FUNCTION_SUFFIX ']'
- # elif defined _MSC_VER
- # define ENTT_PRETTY_FUNCTION __FUNCSIG__
- # define ENTT_PRETTY_FUNCTION_PREFIX '<'
- # define ENTT_PRETTY_FUNCTION_SUFFIX '>'
- # endif
- #endif
- #ifndef ENTT_EXPORT
- # if defined _WIN32 || defined __CYGWIN__ || defined _MSC_VER
- # define ENTT_EXPORT __declspec(dllexport)
- # define ENTT_IMPORT __declspec(dllimport)
- # define ENTT_HIDDEN
- # elif defined __GNUC__ && __GNUC__ >= 4
- # define ENTT_EXPORT __attribute__((visibility("default")))
- # define ENTT_IMPORT __attribute__((visibility("default")))
- # define ENTT_HIDDEN __attribute__((visibility("hidden")))
- # else /* Unsupported compiler */
- # define ENTT_EXPORT
- # define ENTT_IMPORT
- # define ENTT_HIDDEN
- # endif
- #endif
- #ifndef ENTT_API
- # if defined ENTT_API_EXPORT
- # define ENTT_API ENTT_EXPORT
- # elif defined ENTT_API_IMPORT
- # define ENTT_API ENTT_IMPORT
- # else /* No API */
- # define ENTT_API
- # endif
- #endif
- #if defined _MSC_VER
- # pragma detect_mismatch("entt.version", ENTT_VERSION)
- # pragma detect_mismatch("entt.noexcept", ENTT_XSTR(ENTT_TRY))
- # pragma detect_mismatch("entt.id", ENTT_XSTR(ENTT_ID_TYPE))
- # pragma detect_mismatch("entt.nonstd", ENTT_XSTR(ENTT_NONSTD))
- #endif
- // NOLINTEND(cppcoreguidelines-macro-usage)
- #endif
- namespace entt {
- /*! @brief Possible modes of an any object. */
- enum class any_policy : std::uint8_t {
- /*! @brief Default mode, no element available. */
- empty,
- /*! @brief Owning mode, dynamically allocated element. */
- dynamic,
- /*! @brief Owning mode, embedded element. */
- embedded,
- /*! @brief Aliasing mode, non-const reference. */
- ref,
- /*! @brief Const aliasing mode, const reference. */
- cref
- };
- // NOLINTNEXTLINE(cppcoreguidelines-avoid-c-arrays, modernize-avoid-c-arrays)
- template<std::size_t Len = sizeof(double[2]), std::size_t = alignof(double[2])>
- class basic_any;
- /*! @brief Alias declaration for type identifiers. */
- using id_type = ENTT_ID_TYPE;
- /*! @brief Alias declaration for the most common use case. */
- using any = basic_any<>;
- template<typename, typename>
- class compressed_pair;
- template<typename>
- class basic_hashed_string;
- /*! @brief Aliases for common character types. */
- using hashed_string = basic_hashed_string<char>;
- /*! @brief Aliases for common character types. */
- using hashed_wstring = basic_hashed_string<wchar_t>;
- // NOLINTNEXTLINE(bugprone-forward-declaration-namespace)
- struct type_info;
- } // namespace entt
- #endif
- // #include "type_traits.hpp"
- #ifndef ENTT_CORE_TYPE_TRAITS_HPP
- #define ENTT_CORE_TYPE_TRAITS_HPP
- #include <cstddef>
- #include <iterator>
- #include <tuple>
- #include <type_traits>
- #include <utility>
- // #include "../config/config.h"
- // #include "fwd.hpp"
- namespace entt {
- /**
- * @brief Utility class to disambiguate overloaded functions.
- * @tparam N Number of choices available.
- */
- template<std::size_t N>
- struct choice_t
- // unfortunately, doxygen cannot parse such a construct
- : /*! @cond TURN_OFF_DOXYGEN */ choice_t<N - 1> /*! @endcond */
- {};
- /*! @copybrief choice_t */
- template<>
- struct choice_t<0> {};
- /**
- * @brief Variable template for the choice trick.
- * @tparam N Number of choices available.
- */
- template<std::size_t N>
- inline constexpr choice_t<N> choice{};
- /**
- * @brief Identity type trait.
- *
- * Useful to establish non-deduced contexts in template argument deduction
- * (waiting for C++20) or to provide types through function arguments.
- *
- * @tparam Type A type.
- */
- template<typename Type>
- struct type_identity {
- /*! @brief Identity type. */
- using type = Type;
- };
- /**
- * @brief Helper type.
- * @tparam Type A type.
- */
- template<typename Type>
- using type_identity_t = typename type_identity<Type>::type;
- /**
- * @brief A type-only `sizeof` wrapper that returns 0 where `sizeof` complains.
- * @tparam Type The type of which to return the size.
- */
- template<typename Type, typename = void>
- struct size_of: std::integral_constant<std::size_t, 0u> {};
- /*! @copydoc size_of */
- template<typename Type>
- struct size_of<Type, std::void_t<decltype(sizeof(Type))>>
- // NOLINTNEXTLINE(bugprone-sizeof-expression)
- : std::integral_constant<std::size_t, sizeof(Type)> {};
- /**
- * @brief Helper variable template.
- * @tparam Type The type of which to return the size.
- */
- template<typename Type>
- inline constexpr std::size_t size_of_v = size_of<Type>::value;
- /**
- * @brief Using declaration to be used to _repeat_ the same type a number of
- * times equal to the size of a given parameter pack.
- * @tparam Type A type to repeat.
- */
- template<typename Type, typename>
- using unpack_as_type = Type;
- /**
- * @brief Helper variable template to be used to _repeat_ the same value a
- * number of times equal to the size of a given parameter pack.
- * @tparam Value A value to repeat.
- */
- template<auto Value, typename>
- inline constexpr auto unpack_as_value = Value;
- /**
- * @brief Wraps a static constant.
- * @tparam Value A static constant.
- */
- template<auto Value>
- using integral_constant = std::integral_constant<decltype(Value), Value>;
- /**
- * @brief Alias template to facilitate the creation of named values.
- * @tparam Value A constant value at least convertible to `id_type`.
- */
- template<id_type Value>
- using tag = integral_constant<Value>;
- /**
- * @brief A class to use to push around lists of types, nothing more.
- * @tparam Type Types provided by the type list.
- */
- template<typename... Type>
- struct type_list {
- /*! @brief Type list type. */
- using type = type_list;
- /*! @brief Compile-time number of elements in the type list. */
- static constexpr auto size = sizeof...(Type);
- };
- /*! @brief Primary template isn't defined on purpose. */
- template<std::size_t, typename>
- struct type_list_element;
- /**
- * @brief Provides compile-time indexed access to the types of a type list.
- * @tparam Index Index of the type to return.
- * @tparam First First type provided by the type list.
- * @tparam Other Other types provided by the type list.
- */
- template<std::size_t Index, typename First, typename... Other>
- struct type_list_element<Index, type_list<First, Other...>>
- : type_list_element<Index - 1u, type_list<Other...>> {};
- /**
- * @brief Provides compile-time indexed access to the types of a type list.
- * @tparam First First type provided by the type list.
- * @tparam Other Other types provided by the type list.
- */
- template<typename First, typename... Other>
- struct type_list_element<0u, type_list<First, Other...>> {
- /*! @brief Searched type. */
- using type = First;
- };
- /**
- * @brief Helper type.
- * @tparam Index Index of the type to return.
- * @tparam List Type list to search into.
- */
- template<std::size_t Index, typename List>
- using type_list_element_t = typename type_list_element<Index, List>::type;
- /*! @brief Primary template isn't defined on purpose. */
- template<typename, typename>
- struct type_list_index;
- /**
- * @brief Provides compile-time type access to the types of a type list.
- * @tparam Type Type to look for and for which to return the index.
- * @tparam First First type provided by the type list.
- * @tparam Other Other types provided by the type list.
- */
- template<typename Type, typename First, typename... Other>
- struct type_list_index<Type, type_list<First, Other...>> {
- /*! @brief Unsigned integer type. */
- using value_type = std::size_t;
- /*! @brief Compile-time position of the given type in the sublist. */
- static constexpr value_type value = 1u + type_list_index<Type, type_list<Other...>>::value;
- };
- /**
- * @brief Provides compile-time type access to the types of a type list.
- * @tparam Type Type to look for and for which to return the index.
- * @tparam Other Other types provided by the type list.
- */
- template<typename Type, typename... Other>
- struct type_list_index<Type, type_list<Type, Other...>> {
- static_assert(type_list_index<Type, type_list<Other...>>::value == sizeof...(Other), "Non-unique type");
- /*! @brief Unsigned integer type. */
- using value_type = std::size_t;
- /*! @brief Compile-time position of the given type in the sublist. */
- static constexpr value_type value = 0u;
- };
- /**
- * @brief Provides compile-time type access to the types of a type list.
- * @tparam Type Type to look for and for which to return the index.
- */
- template<typename Type>
- struct type_list_index<Type, type_list<>> {
- /*! @brief Unsigned integer type. */
- using value_type = std::size_t;
- /*! @brief Compile-time position of the given type in the sublist. */
- static constexpr value_type value = 0u;
- };
- /**
- * @brief Helper variable template.
- * @tparam List Type list.
- * @tparam Type Type to look for and for which to return the index.
- */
- template<typename Type, typename List>
- inline constexpr std::size_t type_list_index_v = type_list_index<Type, List>::value;
- /**
- * @brief Concatenates multiple type lists.
- * @tparam Type Types provided by the first type list.
- * @tparam Other Types provided by the second type list.
- * @return A type list composed by the types of both the type lists.
- */
- template<typename... Type, typename... Other>
- constexpr type_list<Type..., Other...> operator+(type_list<Type...>, type_list<Other...>) {
- return {};
- }
- /*! @brief Primary template isn't defined on purpose. */
- template<typename...>
- struct type_list_cat;
- /*! @brief Concatenates multiple type lists. */
- template<>
- struct type_list_cat<> {
- /*! @brief A type list composed by the types of all the type lists. */
- using type = type_list<>;
- };
- /**
- * @brief Concatenates multiple type lists.
- * @tparam Type Types provided by the first type list.
- * @tparam Other Types provided by the second type list.
- * @tparam List Other type lists, if any.
- */
- template<typename... Type, typename... Other, typename... List>
- struct type_list_cat<type_list<Type...>, type_list<Other...>, List...> {
- /*! @brief A type list composed by the types of all the type lists. */
- using type = typename type_list_cat<type_list<Type..., Other...>, List...>::type;
- };
- /**
- * @brief Concatenates multiple type lists.
- * @tparam Type Types provided by the type list.
- */
- template<typename... Type>
- struct type_list_cat<type_list<Type...>> {
- /*! @brief A type list composed by the types of all the type lists. */
- using type = type_list<Type...>;
- };
- /**
- * @brief Helper type.
- * @tparam List Type lists to concatenate.
- */
- template<typename... List>
- using type_list_cat_t = typename type_list_cat<List...>::type;
- /*! @cond TURN_OFF_DOXYGEN */
- namespace internal {
- template<typename...>
- struct type_list_unique;
- template<typename First, typename... Other, typename... Type>
- struct type_list_unique<type_list<First, Other...>, Type...>
- : std::conditional_t<(std::is_same_v<First, Type> || ...), type_list_unique<type_list<Other...>, Type...>, type_list_unique<type_list<Other...>, Type..., First>> {};
- template<typename... Type>
- struct type_list_unique<type_list<>, Type...> {
- using type = type_list<Type...>;
- };
- } // namespace internal
- /*! @endcond */
- /**
- * @brief Removes duplicates types from a type list.
- * @tparam List Type list.
- */
- template<typename List>
- struct type_list_unique {
- /*! @brief A type list without duplicate types. */
- using type = typename internal::type_list_unique<List>::type;
- };
- /**
- * @brief Helper type.
- * @tparam List Type list.
- */
- template<typename List>
- using type_list_unique_t = typename type_list_unique<List>::type;
- /**
- * @brief Provides the member constant `value` to true if a type list contains a
- * given type, false otherwise.
- * @tparam List Type list.
- * @tparam Type Type to look for.
- */
- template<typename List, typename Type>
- struct type_list_contains;
- /**
- * @copybrief type_list_contains
- * @tparam Type Types provided by the type list.
- * @tparam Other Type to look for.
- */
- template<typename... Type, typename Other>
- struct type_list_contains<type_list<Type...>, Other>
- : std::bool_constant<(std::is_same_v<Type, Other> || ...)> {};
- /**
- * @brief Helper variable template.
- * @tparam List Type list.
- * @tparam Type Type to look for.
- */
- template<typename List, typename Type>
- inline constexpr bool type_list_contains_v = type_list_contains<List, Type>::value;
- /*! @brief Primary template isn't defined on purpose. */
- template<typename...>
- struct type_list_diff;
- /**
- * @brief Computes the difference between two type lists.
- * @tparam Type Types provided by the first type list.
- * @tparam Other Types provided by the second type list.
- */
- template<typename... Type, typename... Other>
- struct type_list_diff<type_list<Type...>, type_list<Other...>> {
- /*! @brief A type list that is the difference between the two type lists. */
- using type = type_list_cat_t<std::conditional_t<type_list_contains_v<type_list<Other...>, Type>, type_list<>, type_list<Type>>...>;
- };
- /**
- * @brief Helper type.
- * @tparam List Type lists between which to compute the difference.
- */
- template<typename... List>
- using type_list_diff_t = typename type_list_diff<List...>::type;
- /*! @brief Primary template isn't defined on purpose. */
- template<typename, template<typename...> class>
- struct type_list_transform;
- /**
- * @brief Applies a given _function_ to a type list and generate a new list.
- * @tparam Type Types provided by the type list.
- * @tparam Op Unary operation as template class with a type member named `type`.
- */
- template<typename... Type, template<typename...> class Op>
- struct type_list_transform<type_list<Type...>, Op> {
- /*! @brief Resulting type list after applying the transform function. */
- // NOLINTNEXTLINE(modernize-type-traits)
- using type = type_list<typename Op<Type>::type...>;
- };
- /**
- * @brief Helper type.
- * @tparam List Type list.
- * @tparam Op Unary operation as template class with a type member named `type`.
- */
- template<typename List, template<typename...> class Op>
- using type_list_transform_t = typename type_list_transform<List, Op>::type;
- /**
- * @brief A class to use to push around lists of constant values, nothing more.
- * @tparam Value Values provided by the value list.
- */
- template<auto... Value>
- struct value_list {
- /*! @brief Value list type. */
- using type = value_list;
- /*! @brief Compile-time number of elements in the value list. */
- static constexpr auto size = sizeof...(Value);
- };
- /*! @brief Primary template isn't defined on purpose. */
- template<std::size_t, typename>
- struct value_list_element;
- /**
- * @brief Provides compile-time indexed access to the values of a value list.
- * @tparam Index Index of the value to return.
- * @tparam Value First value provided by the value list.
- * @tparam Other Other values provided by the value list.
- */
- template<std::size_t Index, auto Value, auto... Other>
- struct value_list_element<Index, value_list<Value, Other...>>
- : value_list_element<Index - 1u, value_list<Other...>> {};
- /**
- * @brief Provides compile-time indexed access to the types of a type list.
- * @tparam Value First value provided by the value list.
- * @tparam Other Other values provided by the value list.
- */
- template<auto Value, auto... Other>
- struct value_list_element<0u, value_list<Value, Other...>> {
- /*! @brief Searched type. */
- using type = decltype(Value);
- /*! @brief Searched value. */
- static constexpr auto value = Value;
- };
- /**
- * @brief Helper type.
- * @tparam Index Index of the type to return.
- * @tparam List Value list to search into.
- */
- template<std::size_t Index, typename List>
- using value_list_element_t = typename value_list_element<Index, List>::type;
- /**
- * @brief Helper type.
- * @tparam Index Index of the value to return.
- * @tparam List Value list to search into.
- */
- template<std::size_t Index, typename List>
- inline constexpr auto value_list_element_v = value_list_element<Index, List>::value;
- /*! @brief Primary template isn't defined on purpose. */
- template<auto, typename>
- struct value_list_index;
- /**
- * @brief Provides compile-time type access to the values of a value list.
- * @tparam Value Value to look for and for which to return the index.
- * @tparam First First value provided by the value list.
- * @tparam Other Other values provided by the value list.
- */
- template<auto Value, auto First, auto... Other>
- struct value_list_index<Value, value_list<First, Other...>> {
- /*! @brief Unsigned integer type. */
- using value_type = std::size_t;
- /*! @brief Compile-time position of the given value in the sublist. */
- static constexpr value_type value = 1u + value_list_index<Value, value_list<Other...>>::value;
- };
- /**
- * @brief Provides compile-time type access to the values of a value list.
- * @tparam Value Value to look for and for which to return the index.
- * @tparam Other Other values provided by the value list.
- */
- template<auto Value, auto... Other>
- struct value_list_index<Value, value_list<Value, Other...>> {
- static_assert(value_list_index<Value, value_list<Other...>>::value == sizeof...(Other), "Non-unique type");
- /*! @brief Unsigned integer type. */
- using value_type = std::size_t;
- /*! @brief Compile-time position of the given value in the sublist. */
- static constexpr value_type value = 0u;
- };
- /**
- * @brief Provides compile-time type access to the values of a value list.
- * @tparam Value Value to look for and for which to return the index.
- */
- template<auto Value>
- struct value_list_index<Value, value_list<>> {
- /*! @brief Unsigned integer type. */
- using value_type = std::size_t;
- /*! @brief Compile-time position of the given type in the sublist. */
- static constexpr value_type value = 0u;
- };
- /**
- * @brief Helper variable template.
- * @tparam List Value list.
- * @tparam Value Value to look for and for which to return the index.
- */
- template<auto Value, typename List>
- inline constexpr std::size_t value_list_index_v = value_list_index<Value, List>::value;
- /**
- * @brief Concatenates multiple value lists.
- * @tparam Value Values provided by the first value list.
- * @tparam Other Values provided by the second value list.
- * @return A value list composed by the values of both the value lists.
- */
- template<auto... Value, auto... Other>
- constexpr value_list<Value..., Other...> operator+(value_list<Value...>, value_list<Other...>) {
- return {};
- }
- /*! @brief Primary template isn't defined on purpose. */
- template<typename...>
- struct value_list_cat;
- /*! @brief Concatenates multiple value lists. */
- template<>
- struct value_list_cat<> {
- /*! @brief A value list composed by the values of all the value lists. */
- using type = value_list<>;
- };
- /**
- * @brief Concatenates multiple value lists.
- * @tparam Value Values provided by the first value list.
- * @tparam Other Values provided by the second value list.
- * @tparam List Other value lists, if any.
- */
- template<auto... Value, auto... Other, typename... List>
- struct value_list_cat<value_list<Value...>, value_list<Other...>, List...> {
- /*! @brief A value list composed by the values of all the value lists. */
- using type = typename value_list_cat<value_list<Value..., Other...>, List...>::type;
- };
- /**
- * @brief Concatenates multiple value lists.
- * @tparam Value Values provided by the value list.
- */
- template<auto... Value>
- struct value_list_cat<value_list<Value...>> {
- /*! @brief A value list composed by the values of all the value lists. */
- using type = value_list<Value...>;
- };
- /**
- * @brief Helper type.
- * @tparam List Value lists to concatenate.
- */
- template<typename... List>
- using value_list_cat_t = typename value_list_cat<List...>::type;
- /*! @brief Primary template isn't defined on purpose. */
- template<typename>
- struct value_list_unique;
- /**
- * @brief Removes duplicates values from a value list.
- * @tparam Value One of the values provided by the given value list.
- * @tparam Other The other values provided by the given value list.
- */
- template<auto Value, auto... Other>
- struct value_list_unique<value_list<Value, Other...>> {
- /*! @brief A value list without duplicate types. */
- using type = std::conditional_t<
- ((Value == Other) || ...),
- typename value_list_unique<value_list<Other...>>::type,
- value_list_cat_t<value_list<Value>, typename value_list_unique<value_list<Other...>>::type>>;
- };
- /*! @brief Removes duplicates values from a value list. */
- template<>
- struct value_list_unique<value_list<>> {
- /*! @brief A value list without duplicate types. */
- using type = value_list<>;
- };
- /**
- * @brief Helper type.
- * @tparam Type A value list.
- */
- template<typename Type>
- using value_list_unique_t = typename value_list_unique<Type>::type;
- /**
- * @brief Provides the member constant `value` to true if a value list contains
- * a given value, false otherwise.
- * @tparam List Value list.
- * @tparam Value Value to look for.
- */
- template<typename List, auto Value>
- struct value_list_contains;
- /**
- * @copybrief value_list_contains
- * @tparam Value Values provided by the value list.
- * @tparam Other Value to look for.
- */
- template<auto... Value, auto Other>
- struct value_list_contains<value_list<Value...>, Other>
- : std::bool_constant<((Value == Other) || ...)> {};
- /**
- * @brief Helper variable template.
- * @tparam List Value list.
- * @tparam Value Value to look for.
- */
- template<typename List, auto Value>
- inline constexpr bool value_list_contains_v = value_list_contains<List, Value>::value;
- /*! @brief Primary template isn't defined on purpose. */
- template<typename...>
- struct value_list_diff;
- /**
- * @brief Computes the difference between two value lists.
- * @tparam Value Values provided by the first value list.
- * @tparam Other Values provided by the second value list.
- */
- template<auto... Value, auto... Other>
- struct value_list_diff<value_list<Value...>, value_list<Other...>> {
- /*! @brief A value list that is the difference between the two value lists. */
- using type = value_list_cat_t<std::conditional_t<value_list_contains_v<value_list<Other...>, Value>, value_list<>, value_list<Value>>...>;
- };
- /**
- * @brief Helper type.
- * @tparam List Value lists between which to compute the difference.
- */
- template<typename... List>
- using value_list_diff_t = typename value_list_diff<List...>::type;
- /*! @brief Same as std::is_invocable, but with tuples. */
- template<typename, typename>
- struct is_applicable: std::false_type {};
- /**
- * @copybrief is_applicable
- * @tparam Func A valid function type.
- * @tparam Tuple Tuple-like type.
- * @tparam Args The list of arguments to use to probe the function type.
- */
- template<typename Func, template<typename...> class Tuple, typename... Args>
- struct is_applicable<Func, Tuple<Args...>>: std::is_invocable<Func, Args...> {};
- /**
- * @copybrief is_applicable
- * @tparam Func A valid function type.
- * @tparam Tuple Tuple-like type.
- * @tparam Args The list of arguments to use to probe the function type.
- */
- template<typename Func, template<typename...> class Tuple, typename... Args>
- struct is_applicable<Func, const Tuple<Args...>>: std::is_invocable<Func, Args...> {};
- /**
- * @brief Helper variable template.
- * @tparam Func A valid function type.
- * @tparam Args The list of arguments to use to probe the function type.
- */
- template<typename Func, typename Args>
- inline constexpr bool is_applicable_v = is_applicable<Func, Args>::value;
- /*! @brief Same as std::is_invocable_r, but with tuples for arguments. */
- template<typename, typename, typename>
- struct is_applicable_r: std::false_type {};
- /**
- * @copybrief is_applicable_r
- * @tparam Ret The type to which the return type of the function should be
- * convertible.
- * @tparam Func A valid function type.
- * @tparam Args The list of arguments to use to probe the function type.
- */
- template<typename Ret, typename Func, typename... Args>
- struct is_applicable_r<Ret, Func, std::tuple<Args...>>: std::is_invocable_r<Ret, Func, Args...> {};
- /**
- * @brief Helper variable template.
- * @tparam Ret The type to which the return type of the function should be
- * convertible.
- * @tparam Func A valid function type.
- * @tparam Args The list of arguments to use to probe the function type.
- */
- template<typename Ret, typename Func, typename Args>
- inline constexpr bool is_applicable_r_v = is_applicable_r<Ret, Func, Args>::value;
- /**
- * @brief Provides the member constant `value` to true if a given type is
- * complete, false otherwise.
- * @tparam Type The type to test.
- */
- template<typename Type, typename = void>
- struct is_complete: std::false_type {};
- /*! @copydoc is_complete */
- template<typename Type>
- struct is_complete<Type, std::void_t<decltype(sizeof(Type))>>: std::true_type {};
- /**
- * @brief Helper variable template.
- * @tparam Type The type to test.
- */
- template<typename Type>
- inline constexpr bool is_complete_v = is_complete<Type>::value;
- /**
- * @brief Provides the member constant `value` to true if a given type is an
- * iterator, false otherwise.
- * @tparam Type The type to test.
- */
- template<typename Type, typename = void>
- struct is_iterator: std::false_type {};
- /*! @cond TURN_OFF_DOXYGEN */
- namespace internal {
- template<typename, typename = void>
- struct has_iterator_category: std::false_type {};
- template<typename Type>
- struct has_iterator_category<Type, std::void_t<typename std::iterator_traits<Type>::iterator_category>>: std::true_type {};
- } // namespace internal
- /*! @endcond */
- /*! @copydoc is_iterator */
- template<typename Type>
- struct is_iterator<Type, std::enable_if_t<!std::is_void_v<std::remove_const_t<std::remove_pointer_t<Type>>>>>
- : internal::has_iterator_category<Type> {};
- /**
- * @brief Helper variable template.
- * @tparam Type The type to test.
- */
- template<typename Type>
- inline constexpr bool is_iterator_v = is_iterator<Type>::value;
- /**
- * @brief Provides the member constant `value` to true if a given type is both
- * an empty and non-final class, false otherwise.
- * @tparam Type The type to test
- */
- template<typename Type>
- struct is_ebco_eligible
- : std::bool_constant<std::is_empty_v<Type> && !std::is_final_v<Type>> {};
- /**
- * @brief Helper variable template.
- * @tparam Type The type to test.
- */
- template<typename Type>
- inline constexpr bool is_ebco_eligible_v = is_ebco_eligible<Type>::value;
- /**
- * @brief Provides the member constant `value` to true if `Type::is_transparent`
- * is valid and denotes a type, false otherwise.
- * @tparam Type The type to test.
- */
- template<typename Type, typename = void>
- struct is_transparent: std::false_type {};
- /*! @copydoc is_transparent */
- template<typename Type>
- struct is_transparent<Type, std::void_t<typename Type::is_transparent>>: std::true_type {};
- /**
- * @brief Helper variable template.
- * @tparam Type The type to test.
- */
- template<typename Type>
- inline constexpr bool is_transparent_v = is_transparent<Type>::value;
- /*! @cond TURN_OFF_DOXYGEN */
- namespace internal {
- template<typename, typename = void>
- struct has_tuple_size_value: std::false_type {};
- template<typename Type>
- struct has_tuple_size_value<Type, std::void_t<decltype(std::tuple_size<const Type>::value)>>: std::true_type {};
- template<typename, typename = void>
- struct has_value_type: std::false_type {};
- template<typename Type>
- struct has_value_type<Type, std::void_t<typename Type::value_type>>: std::true_type {};
- template<typename>
- [[nodiscard]] constexpr bool dispatch_is_equality_comparable();
- template<typename Type, std::size_t... Index>
- [[nodiscard]] constexpr bool unpack_maybe_equality_comparable(std::index_sequence<Index...>) {
- return (dispatch_is_equality_comparable<std::tuple_element_t<Index, Type>>() && ...);
- }
- template<typename>
- [[nodiscard]] constexpr bool maybe_equality_comparable(char) {
- return false;
- }
- template<typename Type>
- [[nodiscard]] constexpr auto maybe_equality_comparable(int) -> decltype(std::declval<Type>() == std::declval<Type>()) {
- return true;
- }
- template<typename Type>
- [[nodiscard]] constexpr bool dispatch_is_equality_comparable() {
- // NOLINTBEGIN(modernize-use-transparent-functors)
- if constexpr(std::is_array_v<Type>) {
- return false;
- } else if constexpr(is_complete_v<std::tuple_size<std::remove_const_t<Type>>>) {
- if constexpr(has_tuple_size_value<Type>::value) {
- return maybe_equality_comparable<Type>(0) && unpack_maybe_equality_comparable<Type>(std::make_index_sequence<std::tuple_size<Type>::value>{});
- } else {
- return maybe_equality_comparable<Type>(0);
- }
- } else if constexpr(has_value_type<Type>::value) {
- if constexpr(is_iterator_v<Type> || std::is_same_v<typename Type::value_type, Type> || dispatch_is_equality_comparable<typename Type::value_type>()) {
- return maybe_equality_comparable<Type>(0);
- } else {
- return false;
- }
- } else {
- return maybe_equality_comparable<Type>(0);
- }
- // NOLINTEND(modernize-use-transparent-functors)
- }
- } // namespace internal
- /*! @endcond */
- /**
- * @brief Provides the member constant `value` to true if a given type is
- * equality comparable, false otherwise.
- * @tparam Type The type to test.
- */
- template<typename Type>
- struct is_equality_comparable: std::bool_constant<internal::dispatch_is_equality_comparable<Type>()> {};
- /*! @copydoc is_equality_comparable */
- template<typename Type>
- struct is_equality_comparable<const Type>: is_equality_comparable<Type> {};
- /**
- * @brief Helper variable template.
- * @tparam Type The type to test.
- */
- template<typename Type>
- inline constexpr bool is_equality_comparable_v = is_equality_comparable<Type>::value;
- /**
- * @brief Transcribes the constness of a type to another type.
- * @tparam To The type to which to transcribe the constness.
- * @tparam From The type from which to transcribe the constness.
- */
- template<typename To, typename From>
- struct constness_as {
- /*! @brief The type resulting from the transcription of the constness. */
- using type = std::remove_const_t<To>;
- };
- /*! @copydoc constness_as */
- template<typename To, typename From>
- struct constness_as<To, const From> {
- /*! @brief The type resulting from the transcription of the constness. */
- using type = const To;
- };
- /**
- * @brief Alias template to facilitate the transcription of the constness.
- * @tparam To The type to which to transcribe the constness.
- * @tparam From The type from which to transcribe the constness.
- */
- template<typename To, typename From>
- using constness_as_t = typename constness_as<To, From>::type;
- /**
- * @brief Extracts the class of a non-static member object or function.
- * @tparam Member A pointer to a non-static member object or function.
- */
- template<typename Member>
- class member_class {
- static_assert(std::is_member_pointer_v<Member>, "Invalid pointer type to non-static member object or function");
- template<typename Class, typename Ret, typename... Args>
- static Class *clazz(Ret (Class::*)(Args...));
- template<typename Class, typename Ret, typename... Args>
- static Class *clazz(Ret (Class::*)(Args...) const);
- template<typename Class, typename Type>
- static Class *clazz(Type Class::*);
- public:
- /*! @brief The class of the given non-static member object or function. */
- using type = std::remove_pointer_t<decltype(clazz(std::declval<Member>()))>;
- };
- /**
- * @brief Helper type.
- * @tparam Member A pointer to a non-static member object or function.
- */
- template<typename Member>
- using member_class_t = typename member_class<Member>::type;
- /**
- * @brief Extracts the n-th argument of a _callable_ type.
- * @tparam Index The index of the argument to extract.
- * @tparam Candidate A valid _callable_ type.
- */
- template<std::size_t Index, typename Candidate>
- class nth_argument {
- template<typename Ret, typename... Args>
- static constexpr type_list<Args...> pick_up(Ret (*)(Args...));
- template<typename Ret, typename Class, typename... Args>
- static constexpr type_list<Args...> pick_up(Ret (Class ::*)(Args...));
- template<typename Ret, typename Class, typename... Args>
- static constexpr type_list<Args...> pick_up(Ret (Class ::*)(Args...) const);
- template<typename Type, typename Class>
- static constexpr type_list<Type> pick_up(Type Class ::*);
- template<typename Type>
- static constexpr decltype(pick_up(&Type::operator())) pick_up(Type &&);
- public:
- /*! @brief N-th argument of the _callable_ type. */
- using type = type_list_element_t<Index, decltype(pick_up(std::declval<Candidate>()))>;
- };
- /**
- * @brief Helper type.
- * @tparam Index The index of the argument to extract.
- * @tparam Candidate A valid function, member function or data member type.
- */
- template<std::size_t Index, typename Candidate>
- using nth_argument_t = typename nth_argument<Index, Candidate>::type;
- } // namespace entt
- template<typename... Type>
- struct std::tuple_size<entt::type_list<Type...>>: std::integral_constant<std::size_t, entt::type_list<Type...>::size> {};
- template<std::size_t Index, typename... Type>
- struct std::tuple_element<Index, entt::type_list<Type...>>: entt::type_list_element<Index, entt::type_list<Type...>> {};
- template<auto... Value>
- struct std::tuple_size<entt::value_list<Value...>>: std::integral_constant<std::size_t, entt::value_list<Value...>::size> {};
- template<std::size_t Index, auto... Value>
- struct std::tuple_element<Index, entt::value_list<Value...>>: entt::value_list_element<Index, entt::value_list<Value...>> {};
- #endif
- namespace entt {
- /*! @cond TURN_OFF_DOXYGEN */
- namespace internal {
- template<typename Type, std::size_t, typename = void>
- struct compressed_pair_element {
- using reference = Type &;
- using const_reference = const Type &;
- template<typename Dummy = Type, typename = std::enable_if_t<std::is_default_constructible_v<Dummy>>>
- // NOLINTNEXTLINE(modernize-use-equals-default)
- constexpr compressed_pair_element() noexcept(std::is_nothrow_default_constructible_v<Type>) {}
- template<typename Arg, typename = std::enable_if_t<!std::is_same_v<std::remove_const_t<std::remove_reference_t<Arg>>, compressed_pair_element>>>
- constexpr compressed_pair_element(Arg &&arg) noexcept(std::is_nothrow_constructible_v<Type, Arg>)
- : value{std::forward<Arg>(arg)} {}
- template<typename... Args, std::size_t... Index>
- constexpr compressed_pair_element(std::tuple<Args...> args, std::index_sequence<Index...>) noexcept(std::is_nothrow_constructible_v<Type, Args...>)
- : value{std::forward<Args>(std::get<Index>(args))...} {}
- [[nodiscard]] constexpr reference get() noexcept {
- return value;
- }
- [[nodiscard]] constexpr const_reference get() const noexcept {
- return value;
- }
- private:
- Type value{};
- };
- template<typename Type, std::size_t Tag>
- struct compressed_pair_element<Type, Tag, std::enable_if_t<is_ebco_eligible_v<Type>>>: Type {
- using reference = Type &;
- using const_reference = const Type &;
- using base_type = Type;
- template<typename Dummy = Type, typename = std::enable_if_t<std::is_default_constructible_v<Dummy>>>
- constexpr compressed_pair_element() noexcept(std::is_nothrow_default_constructible_v<base_type>)
- : base_type{} {}
- template<typename Arg, typename = std::enable_if_t<!std::is_same_v<std::remove_const_t<std::remove_reference_t<Arg>>, compressed_pair_element>>>
- constexpr compressed_pair_element(Arg &&arg) noexcept(std::is_nothrow_constructible_v<base_type, Arg>)
- : base_type{std::forward<Arg>(arg)} {}
- template<typename... Args, std::size_t... Index>
- constexpr compressed_pair_element(std::tuple<Args...> args, std::index_sequence<Index...>) noexcept(std::is_nothrow_constructible_v<base_type, Args...>)
- : base_type{std::forward<Args>(std::get<Index>(args))...} {}
- [[nodiscard]] constexpr reference get() noexcept {
- return *this;
- }
- [[nodiscard]] constexpr const_reference get() const noexcept {
- return *this;
- }
- };
- } // namespace internal
- /*! @endcond */
- /**
- * @brief A compressed pair.
- *
- * A pair that exploits the _Empty Base Class Optimization_ (or _EBCO_) to
- * reduce its final size to a minimum.
- *
- * @tparam First The type of the first element that the pair stores.
- * @tparam Second The type of the second element that the pair stores.
- */
- template<typename First, typename Second>
- class compressed_pair final
- : internal::compressed_pair_element<First, 0u>,
- internal::compressed_pair_element<Second, 1u> {
- using first_base = internal::compressed_pair_element<First, 0u>;
- using second_base = internal::compressed_pair_element<Second, 1u>;
- public:
- /*! @brief The type of the first element that the pair stores. */
- using first_type = First;
- /*! @brief The type of the second element that the pair stores. */
- using second_type = Second;
- /**
- * @brief Default constructor, conditionally enabled.
- *
- * This constructor is only available when the types that the pair stores
- * are both at least default constructible.
- *
- * @tparam Dummy Dummy template parameter used for internal purposes.
- */
- template<bool Dummy = true, typename = std::enable_if_t<Dummy && std::is_default_constructible_v<first_type> && std::is_default_constructible_v<second_type>>>
- constexpr compressed_pair() noexcept(std::is_nothrow_default_constructible_v<first_base> && std::is_nothrow_default_constructible_v<second_base>)
- : first_base{},
- second_base{} {}
- /**
- * @brief Copy constructor.
- * @param other The instance to copy from.
- */
- constexpr compressed_pair(const compressed_pair &other) = default;
- /**
- * @brief Move constructor.
- * @param other The instance to move from.
- */
- constexpr compressed_pair(compressed_pair &&other) noexcept = default;
- /**
- * @brief Constructs a pair from its values.
- * @tparam Arg Type of value to use to initialize the first element.
- * @tparam Other Type of value to use to initialize the second element.
- * @param arg Value to use to initialize the first element.
- * @param other Value to use to initialize the second element.
- */
- template<typename Arg, typename Other>
- constexpr compressed_pair(Arg &&arg, Other &&other) noexcept(std::is_nothrow_constructible_v<first_base, Arg> && std::is_nothrow_constructible_v<second_base, Other>)
- : first_base{std::forward<Arg>(arg)},
- second_base{std::forward<Other>(other)} {}
- /**
- * @brief Constructs a pair by forwarding the arguments to its parts.
- * @tparam Args Types of arguments to use to initialize the first element.
- * @tparam Other Types of arguments to use to initialize the second element.
- * @param args Arguments to use to initialize the first element.
- * @param other Arguments to use to initialize the second element.
- */
- template<typename... Args, typename... Other>
- constexpr compressed_pair(std::piecewise_construct_t, std::tuple<Args...> args, std::tuple<Other...> other) noexcept(std::is_nothrow_constructible_v<first_base, Args...> && std::is_nothrow_constructible_v<second_base, Other...>)
- : first_base{std::move(args), std::index_sequence_for<Args...>{}},
- second_base{std::move(other), std::index_sequence_for<Other...>{}} {}
- /*! @brief Default destructor. */
- ~compressed_pair() = default;
- /**
- * @brief Copy assignment operator.
- * @param other The instance to copy from.
- * @return This compressed pair object.
- */
- constexpr compressed_pair &operator=(const compressed_pair &other) = default;
- /**
- * @brief Move assignment operator.
- * @param other The instance to move from.
- * @return This compressed pair object.
- */
- constexpr compressed_pair &operator=(compressed_pair &&other) noexcept = default;
- /**
- * @brief Returns the first element that a pair stores.
- * @return The first element that a pair stores.
- */
- [[nodiscard]] constexpr first_type &first() noexcept {
- return static_cast<first_base &>(*this).get();
- }
- /*! @copydoc first */
- [[nodiscard]] constexpr const first_type &first() const noexcept {
- return static_cast<const first_base &>(*this).get();
- }
- /**
- * @brief Returns the second element that a pair stores.
- * @return The second element that a pair stores.
- */
- [[nodiscard]] constexpr second_type &second() noexcept {
- return static_cast<second_base &>(*this).get();
- }
- /*! @copydoc second */
- [[nodiscard]] constexpr const second_type &second() const noexcept {
- return static_cast<const second_base &>(*this).get();
- }
- /**
- * @brief Swaps two compressed pair objects.
- * @param other The compressed pair to swap with.
- */
- constexpr void swap(compressed_pair &other) noexcept {
- using std::swap;
- swap(first(), other.first());
- swap(second(), other.second());
- }
- /**
- * @brief Extracts an element from the compressed pair.
- * @tparam Index An integer value that is either 0 or 1.
- * @return Returns a reference to the first element if `Index` is 0 and a
- * reference to the second element if `Index` is 1.
- */
- template<std::size_t Index>
- [[nodiscard]] constexpr decltype(auto) get() noexcept {
- if constexpr(Index == 0u) {
- return first();
- } else {
- static_assert(Index == 1u, "Index out of bounds");
- return second();
- }
- }
- /*! @copydoc get */
- template<std::size_t Index>
- [[nodiscard]] constexpr decltype(auto) get() const noexcept {
- if constexpr(Index == 0u) {
- return first();
- } else {
- static_assert(Index == 1u, "Index out of bounds");
- return second();
- }
- }
- };
- /**
- * @brief Deduction guide.
- * @tparam Type Type of value to use to initialize the first element.
- * @tparam Other Type of value to use to initialize the second element.
- */
- template<typename Type, typename Other>
- compressed_pair(Type &&, Other &&) -> compressed_pair<std::decay_t<Type>, std::decay_t<Other>>;
- /**
- * @brief Swaps two compressed pair objects.
- * @tparam First The type of the first element that the pairs store.
- * @tparam Second The type of the second element that the pairs store.
- * @param lhs A valid compressed pair object.
- * @param rhs A valid compressed pair object.
- */
- template<typename First, typename Second>
- constexpr void swap(compressed_pair<First, Second> &lhs, compressed_pair<First, Second> &rhs) noexcept {
- lhs.swap(rhs);
- }
- } // namespace entt
- namespace std {
- /**
- * @brief `std::tuple_size` specialization for `compressed_pair`s.
- * @tparam First The type of the first element that the pair stores.
- * @tparam Second The type of the second element that the pair stores.
- */
- template<typename First, typename Second>
- struct tuple_size<entt::compressed_pair<First, Second>>: integral_constant<size_t, 2u> {};
- /**
- * @brief `std::tuple_element` specialization for `compressed_pair`s.
- * @tparam Index The index of the type to return.
- * @tparam First The type of the first element that the pair stores.
- * @tparam Second The type of the second element that the pair stores.
- */
- template<size_t Index, typename First, typename Second>
- struct tuple_element<Index, entt::compressed_pair<First, Second>>: conditional<Index == 0u, First, Second> {
- static_assert(Index < 2u, "Index out of bounds");
- };
- } // namespace std
- #endif
- // #include "../core/type_traits.hpp"
- #ifndef ENTT_CORE_TYPE_TRAITS_HPP
- #define ENTT_CORE_TYPE_TRAITS_HPP
- #include <cstddef>
- #include <iterator>
- #include <tuple>
- #include <type_traits>
- #include <utility>
- // #include "../config/config.h"
- // #include "fwd.hpp"
- namespace entt {
- /**
- * @brief Utility class to disambiguate overloaded functions.
- * @tparam N Number of choices available.
- */
- template<std::size_t N>
- struct choice_t
- // unfortunately, doxygen cannot parse such a construct
- : /*! @cond TURN_OFF_DOXYGEN */ choice_t<N - 1> /*! @endcond */
- {};
- /*! @copybrief choice_t */
- template<>
- struct choice_t<0> {};
- /**
- * @brief Variable template for the choice trick.
- * @tparam N Number of choices available.
- */
- template<std::size_t N>
- inline constexpr choice_t<N> choice{};
- /**
- * @brief Identity type trait.
- *
- * Useful to establish non-deduced contexts in template argument deduction
- * (waiting for C++20) or to provide types through function arguments.
- *
- * @tparam Type A type.
- */
- template<typename Type>
- struct type_identity {
- /*! @brief Identity type. */
- using type = Type;
- };
- /**
- * @brief Helper type.
- * @tparam Type A type.
- */
- template<typename Type>
- using type_identity_t = typename type_identity<Type>::type;
- /**
- * @brief A type-only `sizeof` wrapper that returns 0 where `sizeof` complains.
- * @tparam Type The type of which to return the size.
- */
- template<typename Type, typename = void>
- struct size_of: std::integral_constant<std::size_t, 0u> {};
- /*! @copydoc size_of */
- template<typename Type>
- struct size_of<Type, std::void_t<decltype(sizeof(Type))>>
- // NOLINTNEXTLINE(bugprone-sizeof-expression)
- : std::integral_constant<std::size_t, sizeof(Type)> {};
- /**
- * @brief Helper variable template.
- * @tparam Type The type of which to return the size.
- */
- template<typename Type>
- inline constexpr std::size_t size_of_v = size_of<Type>::value;
- /**
- * @brief Using declaration to be used to _repeat_ the same type a number of
- * times equal to the size of a given parameter pack.
- * @tparam Type A type to repeat.
- */
- template<typename Type, typename>
- using unpack_as_type = Type;
- /**
- * @brief Helper variable template to be used to _repeat_ the same value a
- * number of times equal to the size of a given parameter pack.
- * @tparam Value A value to repeat.
- */
- template<auto Value, typename>
- inline constexpr auto unpack_as_value = Value;
- /**
- * @brief Wraps a static constant.
- * @tparam Value A static constant.
- */
- template<auto Value>
- using integral_constant = std::integral_constant<decltype(Value), Value>;
- /**
- * @brief Alias template to facilitate the creation of named values.
- * @tparam Value A constant value at least convertible to `id_type`.
- */
- template<id_type Value>
- using tag = integral_constant<Value>;
- /**
- * @brief A class to use to push around lists of types, nothing more.
- * @tparam Type Types provided by the type list.
- */
- template<typename... Type>
- struct type_list {
- /*! @brief Type list type. */
- using type = type_list;
- /*! @brief Compile-time number of elements in the type list. */
- static constexpr auto size = sizeof...(Type);
- };
- /*! @brief Primary template isn't defined on purpose. */
- template<std::size_t, typename>
- struct type_list_element;
- /**
- * @brief Provides compile-time indexed access to the types of a type list.
- * @tparam Index Index of the type to return.
- * @tparam First First type provided by the type list.
- * @tparam Other Other types provided by the type list.
- */
- template<std::size_t Index, typename First, typename... Other>
- struct type_list_element<Index, type_list<First, Other...>>
- : type_list_element<Index - 1u, type_list<Other...>> {};
- /**
- * @brief Provides compile-time indexed access to the types of a type list.
- * @tparam First First type provided by the type list.
- * @tparam Other Other types provided by the type list.
- */
- template<typename First, typename... Other>
- struct type_list_element<0u, type_list<First, Other...>> {
- /*! @brief Searched type. */
- using type = First;
- };
- /**
- * @brief Helper type.
- * @tparam Index Index of the type to return.
- * @tparam List Type list to search into.
- */
- template<std::size_t Index, typename List>
- using type_list_element_t = typename type_list_element<Index, List>::type;
- /*! @brief Primary template isn't defined on purpose. */
- template<typename, typename>
- struct type_list_index;
- /**
- * @brief Provides compile-time type access to the types of a type list.
- * @tparam Type Type to look for and for which to return the index.
- * @tparam First First type provided by the type list.
- * @tparam Other Other types provided by the type list.
- */
- template<typename Type, typename First, typename... Other>
- struct type_list_index<Type, type_list<First, Other...>> {
- /*! @brief Unsigned integer type. */
- using value_type = std::size_t;
- /*! @brief Compile-time position of the given type in the sublist. */
- static constexpr value_type value = 1u + type_list_index<Type, type_list<Other...>>::value;
- };
- /**
- * @brief Provides compile-time type access to the types of a type list.
- * @tparam Type Type to look for and for which to return the index.
- * @tparam Other Other types provided by the type list.
- */
- template<typename Type, typename... Other>
- struct type_list_index<Type, type_list<Type, Other...>> {
- static_assert(type_list_index<Type, type_list<Other...>>::value == sizeof...(Other), "Non-unique type");
- /*! @brief Unsigned integer type. */
- using value_type = std::size_t;
- /*! @brief Compile-time position of the given type in the sublist. */
- static constexpr value_type value = 0u;
- };
- /**
- * @brief Provides compile-time type access to the types of a type list.
- * @tparam Type Type to look for and for which to return the index.
- */
- template<typename Type>
- struct type_list_index<Type, type_list<>> {
- /*! @brief Unsigned integer type. */
- using value_type = std::size_t;
- /*! @brief Compile-time position of the given type in the sublist. */
- static constexpr value_type value = 0u;
- };
- /**
- * @brief Helper variable template.
- * @tparam List Type list.
- * @tparam Type Type to look for and for which to return the index.
- */
- template<typename Type, typename List>
- inline constexpr std::size_t type_list_index_v = type_list_index<Type, List>::value;
- /**
- * @brief Concatenates multiple type lists.
- * @tparam Type Types provided by the first type list.
- * @tparam Other Types provided by the second type list.
- * @return A type list composed by the types of both the type lists.
- */
- template<typename... Type, typename... Other>
- constexpr type_list<Type..., Other...> operator+(type_list<Type...>, type_list<Other...>) {
- return {};
- }
- /*! @brief Primary template isn't defined on purpose. */
- template<typename...>
- struct type_list_cat;
- /*! @brief Concatenates multiple type lists. */
- template<>
- struct type_list_cat<> {
- /*! @brief A type list composed by the types of all the type lists. */
- using type = type_list<>;
- };
- /**
- * @brief Concatenates multiple type lists.
- * @tparam Type Types provided by the first type list.
- * @tparam Other Types provided by the second type list.
- * @tparam List Other type lists, if any.
- */
- template<typename... Type, typename... Other, typename... List>
- struct type_list_cat<type_list<Type...>, type_list<Other...>, List...> {
- /*! @brief A type list composed by the types of all the type lists. */
- using type = typename type_list_cat<type_list<Type..., Other...>, List...>::type;
- };
- /**
- * @brief Concatenates multiple type lists.
- * @tparam Type Types provided by the type list.
- */
- template<typename... Type>
- struct type_list_cat<type_list<Type...>> {
- /*! @brief A type list composed by the types of all the type lists. */
- using type = type_list<Type...>;
- };
- /**
- * @brief Helper type.
- * @tparam List Type lists to concatenate.
- */
- template<typename... List>
- using type_list_cat_t = typename type_list_cat<List...>::type;
- /*! @cond TURN_OFF_DOXYGEN */
- namespace internal {
- template<typename...>
- struct type_list_unique;
- template<typename First, typename... Other, typename... Type>
- struct type_list_unique<type_list<First, Other...>, Type...>
- : std::conditional_t<(std::is_same_v<First, Type> || ...), type_list_unique<type_list<Other...>, Type...>, type_list_unique<type_list<Other...>, Type..., First>> {};
- template<typename... Type>
- struct type_list_unique<type_list<>, Type...> {
- using type = type_list<Type...>;
- };
- } // namespace internal
- /*! @endcond */
- /**
- * @brief Removes duplicates types from a type list.
- * @tparam List Type list.
- */
- template<typename List>
- struct type_list_unique {
- /*! @brief A type list without duplicate types. */
- using type = typename internal::type_list_unique<List>::type;
- };
- /**
- * @brief Helper type.
- * @tparam List Type list.
- */
- template<typename List>
- using type_list_unique_t = typename type_list_unique<List>::type;
- /**
- * @brief Provides the member constant `value` to true if a type list contains a
- * given type, false otherwise.
- * @tparam List Type list.
- * @tparam Type Type to look for.
- */
- template<typename List, typename Type>
- struct type_list_contains;
- /**
- * @copybrief type_list_contains
- * @tparam Type Types provided by the type list.
- * @tparam Other Type to look for.
- */
- template<typename... Type, typename Other>
- struct type_list_contains<type_list<Type...>, Other>
- : std::bool_constant<(std::is_same_v<Type, Other> || ...)> {};
- /**
- * @brief Helper variable template.
- * @tparam List Type list.
- * @tparam Type Type to look for.
- */
- template<typename List, typename Type>
- inline constexpr bool type_list_contains_v = type_list_contains<List, Type>::value;
- /*! @brief Primary template isn't defined on purpose. */
- template<typename...>
- struct type_list_diff;
- /**
- * @brief Computes the difference between two type lists.
- * @tparam Type Types provided by the first type list.
- * @tparam Other Types provided by the second type list.
- */
- template<typename... Type, typename... Other>
- struct type_list_diff<type_list<Type...>, type_list<Other...>> {
- /*! @brief A type list that is the difference between the two type lists. */
- using type = type_list_cat_t<std::conditional_t<type_list_contains_v<type_list<Other...>, Type>, type_list<>, type_list<Type>>...>;
- };
- /**
- * @brief Helper type.
- * @tparam List Type lists between which to compute the difference.
- */
- template<typename... List>
- using type_list_diff_t = typename type_list_diff<List...>::type;
- /*! @brief Primary template isn't defined on purpose. */
- template<typename, template<typename...> class>
- struct type_list_transform;
- /**
- * @brief Applies a given _function_ to a type list and generate a new list.
- * @tparam Type Types provided by the type list.
- * @tparam Op Unary operation as template class with a type member named `type`.
- */
- template<typename... Type, template<typename...> class Op>
- struct type_list_transform<type_list<Type...>, Op> {
- /*! @brief Resulting type list after applying the transform function. */
- // NOLINTNEXTLINE(modernize-type-traits)
- using type = type_list<typename Op<Type>::type...>;
- };
- /**
- * @brief Helper type.
- * @tparam List Type list.
- * @tparam Op Unary operation as template class with a type member named `type`.
- */
- template<typename List, template<typename...> class Op>
- using type_list_transform_t = typename type_list_transform<List, Op>::type;
- /**
- * @brief A class to use to push around lists of constant values, nothing more.
- * @tparam Value Values provided by the value list.
- */
- template<auto... Value>
- struct value_list {
- /*! @brief Value list type. */
- using type = value_list;
- /*! @brief Compile-time number of elements in the value list. */
- static constexpr auto size = sizeof...(Value);
- };
- /*! @brief Primary template isn't defined on purpose. */
- template<std::size_t, typename>
- struct value_list_element;
- /**
- * @brief Provides compile-time indexed access to the values of a value list.
- * @tparam Index Index of the value to return.
- * @tparam Value First value provided by the value list.
- * @tparam Other Other values provided by the value list.
- */
- template<std::size_t Index, auto Value, auto... Other>
- struct value_list_element<Index, value_list<Value, Other...>>
- : value_list_element<Index - 1u, value_list<Other...>> {};
- /**
- * @brief Provides compile-time indexed access to the types of a type list.
- * @tparam Value First value provided by the value list.
- * @tparam Other Other values provided by the value list.
- */
- template<auto Value, auto... Other>
- struct value_list_element<0u, value_list<Value, Other...>> {
- /*! @brief Searched type. */
- using type = decltype(Value);
- /*! @brief Searched value. */
- static constexpr auto value = Value;
- };
- /**
- * @brief Helper type.
- * @tparam Index Index of the type to return.
- * @tparam List Value list to search into.
- */
- template<std::size_t Index, typename List>
- using value_list_element_t = typename value_list_element<Index, List>::type;
- /**
- * @brief Helper type.
- * @tparam Index Index of the value to return.
- * @tparam List Value list to search into.
- */
- template<std::size_t Index, typename List>
- inline constexpr auto value_list_element_v = value_list_element<Index, List>::value;
- /*! @brief Primary template isn't defined on purpose. */
- template<auto, typename>
- struct value_list_index;
- /**
- * @brief Provides compile-time type access to the values of a value list.
- * @tparam Value Value to look for and for which to return the index.
- * @tparam First First value provided by the value list.
- * @tparam Other Other values provided by the value list.
- */
- template<auto Value, auto First, auto... Other>
- struct value_list_index<Value, value_list<First, Other...>> {
- /*! @brief Unsigned integer type. */
- using value_type = std::size_t;
- /*! @brief Compile-time position of the given value in the sublist. */
- static constexpr value_type value = 1u + value_list_index<Value, value_list<Other...>>::value;
- };
- /**
- * @brief Provides compile-time type access to the values of a value list.
- * @tparam Value Value to look for and for which to return the index.
- * @tparam Other Other values provided by the value list.
- */
- template<auto Value, auto... Other>
- struct value_list_index<Value, value_list<Value, Other...>> {
- static_assert(value_list_index<Value, value_list<Other...>>::value == sizeof...(Other), "Non-unique type");
- /*! @brief Unsigned integer type. */
- using value_type = std::size_t;
- /*! @brief Compile-time position of the given value in the sublist. */
- static constexpr value_type value = 0u;
- };
- /**
- * @brief Provides compile-time type access to the values of a value list.
- * @tparam Value Value to look for and for which to return the index.
- */
- template<auto Value>
- struct value_list_index<Value, value_list<>> {
- /*! @brief Unsigned integer type. */
- using value_type = std::size_t;
- /*! @brief Compile-time position of the given type in the sublist. */
- static constexpr value_type value = 0u;
- };
- /**
- * @brief Helper variable template.
- * @tparam List Value list.
- * @tparam Value Value to look for and for which to return the index.
- */
- template<auto Value, typename List>
- inline constexpr std::size_t value_list_index_v = value_list_index<Value, List>::value;
- /**
- * @brief Concatenates multiple value lists.
- * @tparam Value Values provided by the first value list.
- * @tparam Other Values provided by the second value list.
- * @return A value list composed by the values of both the value lists.
- */
- template<auto... Value, auto... Other>
- constexpr value_list<Value..., Other...> operator+(value_list<Value...>, value_list<Other...>) {
- return {};
- }
- /*! @brief Primary template isn't defined on purpose. */
- template<typename...>
- struct value_list_cat;
- /*! @brief Concatenates multiple value lists. */
- template<>
- struct value_list_cat<> {
- /*! @brief A value list composed by the values of all the value lists. */
- using type = value_list<>;
- };
- /**
- * @brief Concatenates multiple value lists.
- * @tparam Value Values provided by the first value list.
- * @tparam Other Values provided by the second value list.
- * @tparam List Other value lists, if any.
- */
- template<auto... Value, auto... Other, typename... List>
- struct value_list_cat<value_list<Value...>, value_list<Other...>, List...> {
- /*! @brief A value list composed by the values of all the value lists. */
- using type = typename value_list_cat<value_list<Value..., Other...>, List...>::type;
- };
- /**
- * @brief Concatenates multiple value lists.
- * @tparam Value Values provided by the value list.
- */
- template<auto... Value>
- struct value_list_cat<value_list<Value...>> {
- /*! @brief A value list composed by the values of all the value lists. */
- using type = value_list<Value...>;
- };
- /**
- * @brief Helper type.
- * @tparam List Value lists to concatenate.
- */
- template<typename... List>
- using value_list_cat_t = typename value_list_cat<List...>::type;
- /*! @brief Primary template isn't defined on purpose. */
- template<typename>
- struct value_list_unique;
- /**
- * @brief Removes duplicates values from a value list.
- * @tparam Value One of the values provided by the given value list.
- * @tparam Other The other values provided by the given value list.
- */
- template<auto Value, auto... Other>
- struct value_list_unique<value_list<Value, Other...>> {
- /*! @brief A value list without duplicate types. */
- using type = std::conditional_t<
- ((Value == Other) || ...),
- typename value_list_unique<value_list<Other...>>::type,
- value_list_cat_t<value_list<Value>, typename value_list_unique<value_list<Other...>>::type>>;
- };
- /*! @brief Removes duplicates values from a value list. */
- template<>
- struct value_list_unique<value_list<>> {
- /*! @brief A value list without duplicate types. */
- using type = value_list<>;
- };
- /**
- * @brief Helper type.
- * @tparam Type A value list.
- */
- template<typename Type>
- using value_list_unique_t = typename value_list_unique<Type>::type;
- /**
- * @brief Provides the member constant `value` to true if a value list contains
- * a given value, false otherwise.
- * @tparam List Value list.
- * @tparam Value Value to look for.
- */
- template<typename List, auto Value>
- struct value_list_contains;
- /**
- * @copybrief value_list_contains
- * @tparam Value Values provided by the value list.
- * @tparam Other Value to look for.
- */
- template<auto... Value, auto Other>
- struct value_list_contains<value_list<Value...>, Other>
- : std::bool_constant<((Value == Other) || ...)> {};
- /**
- * @brief Helper variable template.
- * @tparam List Value list.
- * @tparam Value Value to look for.
- */
- template<typename List, auto Value>
- inline constexpr bool value_list_contains_v = value_list_contains<List, Value>::value;
- /*! @brief Primary template isn't defined on purpose. */
- template<typename...>
- struct value_list_diff;
- /**
- * @brief Computes the difference between two value lists.
- * @tparam Value Values provided by the first value list.
- * @tparam Other Values provided by the second value list.
- */
- template<auto... Value, auto... Other>
- struct value_list_diff<value_list<Value...>, value_list<Other...>> {
- /*! @brief A value list that is the difference between the two value lists. */
- using type = value_list_cat_t<std::conditional_t<value_list_contains_v<value_list<Other...>, Value>, value_list<>, value_list<Value>>...>;
- };
- /**
- * @brief Helper type.
- * @tparam List Value lists between which to compute the difference.
- */
- template<typename... List>
- using value_list_diff_t = typename value_list_diff<List...>::type;
- /*! @brief Same as std::is_invocable, but with tuples. */
- template<typename, typename>
- struct is_applicable: std::false_type {};
- /**
- * @copybrief is_applicable
- * @tparam Func A valid function type.
- * @tparam Tuple Tuple-like type.
- * @tparam Args The list of arguments to use to probe the function type.
- */
- template<typename Func, template<typename...> class Tuple, typename... Args>
- struct is_applicable<Func, Tuple<Args...>>: std::is_invocable<Func, Args...> {};
- /**
- * @copybrief is_applicable
- * @tparam Func A valid function type.
- * @tparam Tuple Tuple-like type.
- * @tparam Args The list of arguments to use to probe the function type.
- */
- template<typename Func, template<typename...> class Tuple, typename... Args>
- struct is_applicable<Func, const Tuple<Args...>>: std::is_invocable<Func, Args...> {};
- /**
- * @brief Helper variable template.
- * @tparam Func A valid function type.
- * @tparam Args The list of arguments to use to probe the function type.
- */
- template<typename Func, typename Args>
- inline constexpr bool is_applicable_v = is_applicable<Func, Args>::value;
- /*! @brief Same as std::is_invocable_r, but with tuples for arguments. */
- template<typename, typename, typename>
- struct is_applicable_r: std::false_type {};
- /**
- * @copybrief is_applicable_r
- * @tparam Ret The type to which the return type of the function should be
- * convertible.
- * @tparam Func A valid function type.
- * @tparam Args The list of arguments to use to probe the function type.
- */
- template<typename Ret, typename Func, typename... Args>
- struct is_applicable_r<Ret, Func, std::tuple<Args...>>: std::is_invocable_r<Ret, Func, Args...> {};
- /**
- * @brief Helper variable template.
- * @tparam Ret The type to which the return type of the function should be
- * convertible.
- * @tparam Func A valid function type.
- * @tparam Args The list of arguments to use to probe the function type.
- */
- template<typename Ret, typename Func, typename Args>
- inline constexpr bool is_applicable_r_v = is_applicable_r<Ret, Func, Args>::value;
- /**
- * @brief Provides the member constant `value` to true if a given type is
- * complete, false otherwise.
- * @tparam Type The type to test.
- */
- template<typename Type, typename = void>
- struct is_complete: std::false_type {};
- /*! @copydoc is_complete */
- template<typename Type>
- struct is_complete<Type, std::void_t<decltype(sizeof(Type))>>: std::true_type {};
- /**
- * @brief Helper variable template.
- * @tparam Type The type to test.
- */
- template<typename Type>
- inline constexpr bool is_complete_v = is_complete<Type>::value;
- /**
- * @brief Provides the member constant `value` to true if a given type is an
- * iterator, false otherwise.
- * @tparam Type The type to test.
- */
- template<typename Type, typename = void>
- struct is_iterator: std::false_type {};
- /*! @cond TURN_OFF_DOXYGEN */
- namespace internal {
- template<typename, typename = void>
- struct has_iterator_category: std::false_type {};
- template<typename Type>
- struct has_iterator_category<Type, std::void_t<typename std::iterator_traits<Type>::iterator_category>>: std::true_type {};
- } // namespace internal
- /*! @endcond */
- /*! @copydoc is_iterator */
- template<typename Type>
- struct is_iterator<Type, std::enable_if_t<!std::is_void_v<std::remove_const_t<std::remove_pointer_t<Type>>>>>
- : internal::has_iterator_category<Type> {};
- /**
- * @brief Helper variable template.
- * @tparam Type The type to test.
- */
- template<typename Type>
- inline constexpr bool is_iterator_v = is_iterator<Type>::value;
- /**
- * @brief Provides the member constant `value` to true if a given type is both
- * an empty and non-final class, false otherwise.
- * @tparam Type The type to test
- */
- template<typename Type>
- struct is_ebco_eligible
- : std::bool_constant<std::is_empty_v<Type> && !std::is_final_v<Type>> {};
- /**
- * @brief Helper variable template.
- * @tparam Type The type to test.
- */
- template<typename Type>
- inline constexpr bool is_ebco_eligible_v = is_ebco_eligible<Type>::value;
- /**
- * @brief Provides the member constant `value` to true if `Type::is_transparent`
- * is valid and denotes a type, false otherwise.
- * @tparam Type The type to test.
- */
- template<typename Type, typename = void>
- struct is_transparent: std::false_type {};
- /*! @copydoc is_transparent */
- template<typename Type>
- struct is_transparent<Type, std::void_t<typename Type::is_transparent>>: std::true_type {};
- /**
- * @brief Helper variable template.
- * @tparam Type The type to test.
- */
- template<typename Type>
- inline constexpr bool is_transparent_v = is_transparent<Type>::value;
- /*! @cond TURN_OFF_DOXYGEN */
- namespace internal {
- template<typename, typename = void>
- struct has_tuple_size_value: std::false_type {};
- template<typename Type>
- struct has_tuple_size_value<Type, std::void_t<decltype(std::tuple_size<const Type>::value)>>: std::true_type {};
- template<typename, typename = void>
- struct has_value_type: std::false_type {};
- template<typename Type>
- struct has_value_type<Type, std::void_t<typename Type::value_type>>: std::true_type {};
- template<typename>
- [[nodiscard]] constexpr bool dispatch_is_equality_comparable();
- template<typename Type, std::size_t... Index>
- [[nodiscard]] constexpr bool unpack_maybe_equality_comparable(std::index_sequence<Index...>) {
- return (dispatch_is_equality_comparable<std::tuple_element_t<Index, Type>>() && ...);
- }
- template<typename>
- [[nodiscard]] constexpr bool maybe_equality_comparable(char) {
- return false;
- }
- template<typename Type>
- [[nodiscard]] constexpr auto maybe_equality_comparable(int) -> decltype(std::declval<Type>() == std::declval<Type>()) {
- return true;
- }
- template<typename Type>
- [[nodiscard]] constexpr bool dispatch_is_equality_comparable() {
- // NOLINTBEGIN(modernize-use-transparent-functors)
- if constexpr(std::is_array_v<Type>) {
- return false;
- } else if constexpr(is_complete_v<std::tuple_size<std::remove_const_t<Type>>>) {
- if constexpr(has_tuple_size_value<Type>::value) {
- return maybe_equality_comparable<Type>(0) && unpack_maybe_equality_comparable<Type>(std::make_index_sequence<std::tuple_size<Type>::value>{});
- } else {
- return maybe_equality_comparable<Type>(0);
- }
- } else if constexpr(has_value_type<Type>::value) {
- if constexpr(is_iterator_v<Type> || std::is_same_v<typename Type::value_type, Type> || dispatch_is_equality_comparable<typename Type::value_type>()) {
- return maybe_equality_comparable<Type>(0);
- } else {
- return false;
- }
- } else {
- return maybe_equality_comparable<Type>(0);
- }
- // NOLINTEND(modernize-use-transparent-functors)
- }
- } // namespace internal
- /*! @endcond */
- /**
- * @brief Provides the member constant `value` to true if a given type is
- * equality comparable, false otherwise.
- * @tparam Type The type to test.
- */
- template<typename Type>
- struct is_equality_comparable: std::bool_constant<internal::dispatch_is_equality_comparable<Type>()> {};
- /*! @copydoc is_equality_comparable */
- template<typename Type>
- struct is_equality_comparable<const Type>: is_equality_comparable<Type> {};
- /**
- * @brief Helper variable template.
- * @tparam Type The type to test.
- */
- template<typename Type>
- inline constexpr bool is_equality_comparable_v = is_equality_comparable<Type>::value;
- /**
- * @brief Transcribes the constness of a type to another type.
- * @tparam To The type to which to transcribe the constness.
- * @tparam From The type from which to transcribe the constness.
- */
- template<typename To, typename From>
- struct constness_as {
- /*! @brief The type resulting from the transcription of the constness. */
- using type = std::remove_const_t<To>;
- };
- /*! @copydoc constness_as */
- template<typename To, typename From>
- struct constness_as<To, const From> {
- /*! @brief The type resulting from the transcription of the constness. */
- using type = const To;
- };
- /**
- * @brief Alias template to facilitate the transcription of the constness.
- * @tparam To The type to which to transcribe the constness.
- * @tparam From The type from which to transcribe the constness.
- */
- template<typename To, typename From>
- using constness_as_t = typename constness_as<To, From>::type;
- /**
- * @brief Extracts the class of a non-static member object or function.
- * @tparam Member A pointer to a non-static member object or function.
- */
- template<typename Member>
- class member_class {
- static_assert(std::is_member_pointer_v<Member>, "Invalid pointer type to non-static member object or function");
- template<typename Class, typename Ret, typename... Args>
- static Class *clazz(Ret (Class::*)(Args...));
- template<typename Class, typename Ret, typename... Args>
- static Class *clazz(Ret (Class::*)(Args...) const);
- template<typename Class, typename Type>
- static Class *clazz(Type Class::*);
- public:
- /*! @brief The class of the given non-static member object or function. */
- using type = std::remove_pointer_t<decltype(clazz(std::declval<Member>()))>;
- };
- /**
- * @brief Helper type.
- * @tparam Member A pointer to a non-static member object or function.
- */
- template<typename Member>
- using member_class_t = typename member_class<Member>::type;
- /**
- * @brief Extracts the n-th argument of a _callable_ type.
- * @tparam Index The index of the argument to extract.
- * @tparam Candidate A valid _callable_ type.
- */
- template<std::size_t Index, typename Candidate>
- class nth_argument {
- template<typename Ret, typename... Args>
- static constexpr type_list<Args...> pick_up(Ret (*)(Args...));
- template<typename Ret, typename Class, typename... Args>
- static constexpr type_list<Args...> pick_up(Ret (Class ::*)(Args...));
- template<typename Ret, typename Class, typename... Args>
- static constexpr type_list<Args...> pick_up(Ret (Class ::*)(Args...) const);
- template<typename Type, typename Class>
- static constexpr type_list<Type> pick_up(Type Class ::*);
- template<typename Type>
- static constexpr decltype(pick_up(&Type::operator())) pick_up(Type &&);
- public:
- /*! @brief N-th argument of the _callable_ type. */
- using type = type_list_element_t<Index, decltype(pick_up(std::declval<Candidate>()))>;
- };
- /**
- * @brief Helper type.
- * @tparam Index The index of the argument to extract.
- * @tparam Candidate A valid function, member function or data member type.
- */
- template<std::size_t Index, typename Candidate>
- using nth_argument_t = typename nth_argument<Index, Candidate>::type;
- } // namespace entt
- template<typename... Type>
- struct std::tuple_size<entt::type_list<Type...>>: std::integral_constant<std::size_t, entt::type_list<Type...>::size> {};
- template<std::size_t Index, typename... Type>
- struct std::tuple_element<Index, entt::type_list<Type...>>: entt::type_list_element<Index, entt::type_list<Type...>> {};
- template<auto... Value>
- struct std::tuple_size<entt::value_list<Value...>>: std::integral_constant<std::size_t, entt::value_list<Value...>::size> {};
- template<std::size_t Index, auto... Value>
- struct std::tuple_element<Index, entt::value_list<Value...>>: entt::value_list_element<Index, entt::value_list<Value...>> {};
- #endif
- // #include "fwd.hpp"
- #ifndef ENTT_PROCESS_FWD_HPP
- #define ENTT_PROCESS_FWD_HPP
- #include <cstdint>
- #include <memory>
- namespace entt {
- template<typename, typename = std::allocator<void>>
- class basic_process;
- /*! @brief Alias declaration for the most common use case. */
- using process = basic_process<std::uint32_t>;
- template<typename, typename = std::allocator<void>>
- class basic_scheduler;
- /*! @brief Alias declaration for the most common use case. */
- using scheduler = basic_scheduler<std::uint32_t>;
- } // namespace entt
- #endif
- namespace entt {
- /*! @cond TURN_OFF_DOXYGEN */
- namespace internal {
- template<typename, typename, typename>
- struct process_adaptor;
- } // namespace internal
- /*! @endcond */
- /**
- * @brief Base class for processes.
- *
- * Derived classes must specify what's the intended type for elapsed times.<br/>
- * A process can implement the following member functions whether required:
- *
- * * @code{.cpp}
- * void update(Delta, void *) override;
- * @endcode
- *
- * It's invoked once per tick until a process is explicitly aborted or it
- * terminates either with or without errors. Even though it's not mandatory to
- * declare this member function, as a rule of thumb each process should at
- * least define it to work properly. The `void *` parameter is an opaque
- * pointer to user data (if any) forwarded directly to the process during an
- * update.
- *
- * * @code{.cpp}
- * void succeeded() override;
- * @endcode
- *
- * It's invoked in case of success, immediately after an update and during the
- * same tick.
- *
- * * @code{.cpp}
- * void failed() override;
- * @endcode
- *
- * It's invoked in case of errors, immediately after an update and during the
- * same tick.
- *
- * * @code{.cpp}
- * void aborted() override;
- * @endcode
- *
- * It's invoked only if a process is explicitly aborted. There is no guarantee
- * that it executes in the same tick, this depends solely on whether the
- * process is aborted immediately or not.
- *
- * Derived classes can change the internal state of a process by invoking the
- * `succeed` and `fail` member functions and even pause or unpause the process
- * itself.
- *
- * @sa scheduler
- *
- * @tparam Delta Type to use to provide elapsed time.
- * @tparam Allocator Type of allocator used to manage memory and elements.
- */
- template<typename Delta, typename Allocator>
- class basic_process: public std::enable_shared_from_this<basic_process<Delta, Allocator>> {
- enum class state : std::uint8_t {
- idle = 0,
- running,
- paused,
- succeeded,
- failed,
- aborted,
- finished,
- rejected
- };
- virtual void update(const Delta, void *) {
- abort();
- }
- virtual void succeeded() {}
- virtual void failed() {}
- virtual void aborted() {}
- public:
- /*! @brief Allocator type. */
- using allocator_type = Allocator;
- /*! @brief Type used to provide elapsed time. */
- using delta_type = Delta;
- /*! @brief Handle type. */
- using handle_type = std::shared_ptr<basic_process>;
- /*! @brief Default constructor. */
- basic_process()
- : basic_process{allocator_type{}} {}
- /**
- * @brief Constructs a scheduler with a given allocator.
- * @param allocator The allocator to use.
- */
- explicit basic_process(const allocator_type &allocator)
- : next{nullptr, allocator},
- current{state::idle} {}
- /*! @brief Default copy constructor, deleted on purpose. */
- basic_process(const basic_process &) = delete;
- /*! @brief Default move constructor, deleted on purpose. */
- basic_process(basic_process &&) = delete;
- /*! @brief Default destructor. */
- virtual ~basic_process() = default;
- /**
- * @brief Default copy assignment operator, deleted on purpose.
- * @return This process scheduler.
- */
- basic_process &operator=(const basic_process &) = delete;
- /**
- * @brief Default move assignment operator, deleted on purpose.
- * @return This process scheduler.
- */
- basic_process &operator=(basic_process &&) = delete;
- /**
- * @brief Returns the associated allocator.
- * @return The associated allocator.
- */
- [[nodiscard]] constexpr allocator_type get_allocator() const noexcept {
- return next.second();
- }
- /*! @brief Aborts a process if it's still alive, otherwise does nothing. */
- void abort() {
- if(alive()) {
- current = state::aborted;
- }
- }
- /**
- * @brief Terminates a process with success if it's still alive, otherwise
- * does nothing.
- */
- void succeed() noexcept {
- if(alive()) {
- current = state::succeeded;
- }
- }
- /**
- * @brief Terminates a process with errors if it's still alive, otherwise
- * does nothing.
- */
- void fail() noexcept {
- if(alive()) {
- current = state::failed;
- }
- }
- /*! @brief Stops a process if it's running, otherwise does nothing. */
- void pause() noexcept {
- if(alive()) {
- current = state::paused;
- }
- }
- /*! @brief Restarts a process if it's paused, otherwise does nothing. */
- void unpause() noexcept {
- if(alive()) {
- current = state::running;
- }
- }
- /**
- * @brief Returns true if a process is either running or paused.
- * @return True if the process is still alive, false otherwise.
- */
- [[nodiscard]] bool alive() const noexcept {
- return current == state::running || current == state::paused;
- }
- /**
- * @brief Returns true if a process is already terminated.
- * @return True if the process is terminated, false otherwise.
- */
- [[nodiscard]] bool finished() const noexcept {
- return current == state::finished;
- }
- /**
- * @brief Returns true if a process is currently paused.
- * @return True if the process is paused, false otherwise.
- */
- [[nodiscard]] bool paused() const noexcept {
- return current == state::paused;
- }
- /**
- * @brief Returns true if a process terminated with errors.
- * @return True if the process terminated with errors, false otherwise.
- */
- [[nodiscard]] bool rejected() const noexcept {
- return current == state::rejected;
- }
- /**
- * @brief Assigns a child process to run in case of success.
- * @tparam Type Type of child process to create.
- * @tparam Args Types of arguments to use to initialize the child process.
- * @param args Parameters to use to initialize the child process.
- * @return A reference to the newly created child process.
- */
- template<typename Type, typename... Args>
- basic_process &then(Args &&...args) {
- const auto &allocator = next.second();
- return *(next.first() = std::allocate_shared<Type>(allocator, allocator, std::forward<Args>(args)...));
- }
- /**
- * @brief Assigns a child process to run in case of success.
- * @tparam Func Type of child process to create.
- * @param func Either a lambda or a functor to use as a child process.
- * @return A reference to the newly created child process.
- */
- template<typename Func>
- basic_process &then(Func func) {
- const auto &allocator = next.second();
- using process_type = internal::process_adaptor<delta_type, Func, allocator_type>;
- return *(next.first() = std::allocate_shared<process_type>(allocator, allocator, std::move(func)));
- }
- /**
- * @brief Returns the child process without releasing ownership, if any.
- * @return The child process attached to the object, if any.
- */
- handle_type peek() {
- return next.first();
- }
- /**
- * @brief Updates a process and its internal state, if required.
- * @param delta Elapsed time.
- * @param data Optional data.
- */
- void tick(const Delta delta, void *data = nullptr) {
- switch(current) {
- case state::idle:
- case state::running:
- current = state::running;
- update(delta, data);
- break;
- default:
- // suppress warnings
- break;
- }
- // if it's dead, it must be notified and removed immediately
- switch(current) {
- case state::succeeded:
- succeeded();
- current = state::finished;
- break;
- case state::failed:
- failed();
- current = state::rejected;
- break;
- case state::aborted:
- aborted();
- current = state::rejected;
- break;
- default:
- // suppress warnings
- break;
- }
- }
- private:
- compressed_pair<handle_type, allocator_type> next;
- state current;
- };
- /*! @cond TURN_OFF_DOXYGEN */
- namespace internal {
- template<typename Delta, typename Func, typename Allocator>
- struct process_adaptor: public basic_process<Delta, Allocator> {
- using allocator_type = Allocator;
- using base_type = basic_process<Delta, Allocator>;
- using delta_type = typename base_type::delta_type;
- process_adaptor(const allocator_type &allocator, Func proc)
- : base_type{allocator},
- func{std::move(proc)} {}
- void update(const delta_type delta, void *data) override {
- func(*this, delta, data);
- }
- private:
- Func func;
- };
- } // namespace internal
- /*! @endcond */
- } // namespace entt
- #endif
- // #include "process/scheduler.hpp"
- #ifndef ENTT_PROCESS_SCHEDULER_HPP
- #define ENTT_PROCESS_SCHEDULER_HPP
- #include <cstddef>
- #include <memory>
- #include <type_traits>
- #include <utility>
- #include <vector>
- // #include "../config/config.h"
- #ifndef ENTT_CONFIG_CONFIG_H
- #define ENTT_CONFIG_CONFIG_H
- // #include "version.h"
- #ifndef ENTT_CONFIG_VERSION_H
- #define ENTT_CONFIG_VERSION_H
- // #include "macro.h"
- #ifndef ENTT_CONFIG_MACRO_H
- #define ENTT_CONFIG_MACRO_H
- // NOLINTBEGIN(cppcoreguidelines-macro-usage)
- #define ENTT_STR(arg) #arg
- #define ENTT_XSTR(arg) ENTT_STR(arg)
- // NOLINTEND(cppcoreguidelines-macro-usage)
- #endif
- // NOLINTBEGIN(cppcoreguidelines-macro-*,modernize-macro-*)
- #define ENTT_VERSION_MAJOR 3
- #define ENTT_VERSION_MINOR 16
- #define ENTT_VERSION_PATCH 0
- #define ENTT_VERSION \
- ENTT_XSTR(ENTT_VERSION_MAJOR) \
- "." ENTT_XSTR(ENTT_VERSION_MINOR) "." ENTT_XSTR(ENTT_VERSION_PATCH)
- // NOLINTEND(cppcoreguidelines-macro-*,modernize-macro-*)
- #endif
- // NOLINTBEGIN(cppcoreguidelines-macro-usage)
- #if defined(__cpp_exceptions) && !defined(ENTT_NOEXCEPTION)
- # define ENTT_CONSTEXPR
- # define ENTT_THROW throw
- # define ENTT_TRY try
- # define ENTT_CATCH catch(...)
- #else
- # define ENTT_CONSTEXPR constexpr // use only with throwing functions (waiting for C++20)
- # define ENTT_THROW
- # define ENTT_TRY if(true)
- # define ENTT_CATCH if(false)
- #endif
- #if __has_include(<version>)
- # include <version>
- #
- # if defined(__cpp_consteval)
- # define ENTT_CONSTEVAL consteval
- # endif
- #endif
- #ifndef ENTT_CONSTEVAL
- # define ENTT_CONSTEVAL constexpr
- #endif
- #ifdef ENTT_USE_ATOMIC
- # include <atomic>
- # define ENTT_MAYBE_ATOMIC(Type) std::atomic<Type>
- #else
- # define ENTT_MAYBE_ATOMIC(Type) Type
- #endif
- #ifndef ENTT_ID_TYPE
- # include <cstdint>
- # define ENTT_ID_TYPE std::uint32_t
- #else
- # include <cstdint> // provides coverage for types in the std namespace
- #endif
- #ifndef ENTT_SPARSE_PAGE
- # define ENTT_SPARSE_PAGE 4096
- #endif
- #ifndef ENTT_PACKED_PAGE
- # define ENTT_PACKED_PAGE 1024
- #endif
- #ifdef ENTT_DISABLE_ASSERT
- # undef ENTT_ASSERT
- # define ENTT_ASSERT(condition, msg) (void(0))
- #elif !defined ENTT_ASSERT
- # include <cassert>
- # define ENTT_ASSERT(condition, msg) assert(((condition) && (msg)))
- #endif
- #ifdef ENTT_DISABLE_ASSERT
- # undef ENTT_ASSERT_CONSTEXPR
- # define ENTT_ASSERT_CONSTEXPR(condition, msg) (void(0))
- #elif !defined ENTT_ASSERT_CONSTEXPR
- # define ENTT_ASSERT_CONSTEXPR(condition, msg) ENTT_ASSERT(condition, msg)
- #endif
- #define ENTT_FAIL(msg) ENTT_ASSERT(false, msg);
- #ifdef ENTT_NO_ETO
- # define ENTT_ETO_TYPE(Type) void
- #else
- # define ENTT_ETO_TYPE(Type) Type
- #endif
- #ifdef ENTT_NO_MIXIN
- # define ENTT_STORAGE(Mixin, ...) __VA_ARGS__
- #else
- # define ENTT_STORAGE(Mixin, ...) Mixin<__VA_ARGS__>
- #endif
- #ifdef ENTT_STANDARD_CPP
- # define ENTT_NONSTD false
- #else
- # define ENTT_NONSTD true
- # if defined __clang__ || defined __GNUC__
- # define ENTT_PRETTY_FUNCTION __PRETTY_FUNCTION__
- # define ENTT_PRETTY_FUNCTION_PREFIX '='
- # define ENTT_PRETTY_FUNCTION_SUFFIX ']'
- # elif defined _MSC_VER
- # define ENTT_PRETTY_FUNCTION __FUNCSIG__
- # define ENTT_PRETTY_FUNCTION_PREFIX '<'
- # define ENTT_PRETTY_FUNCTION_SUFFIX '>'
- # endif
- #endif
- #ifndef ENTT_EXPORT
- # if defined _WIN32 || defined __CYGWIN__ || defined _MSC_VER
- # define ENTT_EXPORT __declspec(dllexport)
- # define ENTT_IMPORT __declspec(dllimport)
- # define ENTT_HIDDEN
- # elif defined __GNUC__ && __GNUC__ >= 4
- # define ENTT_EXPORT __attribute__((visibility("default")))
- # define ENTT_IMPORT __attribute__((visibility("default")))
- # define ENTT_HIDDEN __attribute__((visibility("hidden")))
- # else /* Unsupported compiler */
- # define ENTT_EXPORT
- # define ENTT_IMPORT
- # define ENTT_HIDDEN
- # endif
- #endif
- #ifndef ENTT_API
- # if defined ENTT_API_EXPORT
- # define ENTT_API ENTT_EXPORT
- # elif defined ENTT_API_IMPORT
- # define ENTT_API ENTT_IMPORT
- # else /* No API */
- # define ENTT_API
- # endif
- #endif
- #if defined _MSC_VER
- # pragma detect_mismatch("entt.version", ENTT_VERSION)
- # pragma detect_mismatch("entt.noexcept", ENTT_XSTR(ENTT_TRY))
- # pragma detect_mismatch("entt.id", ENTT_XSTR(ENTT_ID_TYPE))
- # pragma detect_mismatch("entt.nonstd", ENTT_XSTR(ENTT_NONSTD))
- #endif
- // NOLINTEND(cppcoreguidelines-macro-usage)
- #endif
- // #include "../core/compressed_pair.hpp"
- // #include "fwd.hpp"
- // #include "process.hpp"
- #ifndef ENTT_PROCESS_PROCESS_HPP
- #define ENTT_PROCESS_PROCESS_HPP
- #include <cstdint>
- #include <memory>
- #include <type_traits>
- #include <utility>
- // #include "../core/compressed_pair.hpp"
- // #include "../core/type_traits.hpp"
- // #include "fwd.hpp"
- namespace entt {
- /*! @cond TURN_OFF_DOXYGEN */
- namespace internal {
- template<typename, typename, typename>
- struct process_adaptor;
- } // namespace internal
- /*! @endcond */
- /**
- * @brief Base class for processes.
- *
- * Derived classes must specify what's the intended type for elapsed times.<br/>
- * A process can implement the following member functions whether required:
- *
- * * @code{.cpp}
- * void update(Delta, void *) override;
- * @endcode
- *
- * It's invoked once per tick until a process is explicitly aborted or it
- * terminates either with or without errors. Even though it's not mandatory to
- * declare this member function, as a rule of thumb each process should at
- * least define it to work properly. The `void *` parameter is an opaque
- * pointer to user data (if any) forwarded directly to the process during an
- * update.
- *
- * * @code{.cpp}
- * void succeeded() override;
- * @endcode
- *
- * It's invoked in case of success, immediately after an update and during the
- * same tick.
- *
- * * @code{.cpp}
- * void failed() override;
- * @endcode
- *
- * It's invoked in case of errors, immediately after an update and during the
- * same tick.
- *
- * * @code{.cpp}
- * void aborted() override;
- * @endcode
- *
- * It's invoked only if a process is explicitly aborted. There is no guarantee
- * that it executes in the same tick, this depends solely on whether the
- * process is aborted immediately or not.
- *
- * Derived classes can change the internal state of a process by invoking the
- * `succeed` and `fail` member functions and even pause or unpause the process
- * itself.
- *
- * @sa scheduler
- *
- * @tparam Delta Type to use to provide elapsed time.
- * @tparam Allocator Type of allocator used to manage memory and elements.
- */
- template<typename Delta, typename Allocator>
- class basic_process: public std::enable_shared_from_this<basic_process<Delta, Allocator>> {
- enum class state : std::uint8_t {
- idle = 0,
- running,
- paused,
- succeeded,
- failed,
- aborted,
- finished,
- rejected
- };
- virtual void update(const Delta, void *) {
- abort();
- }
- virtual void succeeded() {}
- virtual void failed() {}
- virtual void aborted() {}
- public:
- /*! @brief Allocator type. */
- using allocator_type = Allocator;
- /*! @brief Type used to provide elapsed time. */
- using delta_type = Delta;
- /*! @brief Handle type. */
- using handle_type = std::shared_ptr<basic_process>;
- /*! @brief Default constructor. */
- basic_process()
- : basic_process{allocator_type{}} {}
- /**
- * @brief Constructs a scheduler with a given allocator.
- * @param allocator The allocator to use.
- */
- explicit basic_process(const allocator_type &allocator)
- : next{nullptr, allocator},
- current{state::idle} {}
- /*! @brief Default copy constructor, deleted on purpose. */
- basic_process(const basic_process &) = delete;
- /*! @brief Default move constructor, deleted on purpose. */
- basic_process(basic_process &&) = delete;
- /*! @brief Default destructor. */
- virtual ~basic_process() = default;
- /**
- * @brief Default copy assignment operator, deleted on purpose.
- * @return This process scheduler.
- */
- basic_process &operator=(const basic_process &) = delete;
- /**
- * @brief Default move assignment operator, deleted on purpose.
- * @return This process scheduler.
- */
- basic_process &operator=(basic_process &&) = delete;
- /**
- * @brief Returns the associated allocator.
- * @return The associated allocator.
- */
- [[nodiscard]] constexpr allocator_type get_allocator() const noexcept {
- return next.second();
- }
- /*! @brief Aborts a process if it's still alive, otherwise does nothing. */
- void abort() {
- if(alive()) {
- current = state::aborted;
- }
- }
- /**
- * @brief Terminates a process with success if it's still alive, otherwise
- * does nothing.
- */
- void succeed() noexcept {
- if(alive()) {
- current = state::succeeded;
- }
- }
- /**
- * @brief Terminates a process with errors if it's still alive, otherwise
- * does nothing.
- */
- void fail() noexcept {
- if(alive()) {
- current = state::failed;
- }
- }
- /*! @brief Stops a process if it's running, otherwise does nothing. */
- void pause() noexcept {
- if(alive()) {
- current = state::paused;
- }
- }
- /*! @brief Restarts a process if it's paused, otherwise does nothing. */
- void unpause() noexcept {
- if(alive()) {
- current = state::running;
- }
- }
- /**
- * @brief Returns true if a process is either running or paused.
- * @return True if the process is still alive, false otherwise.
- */
- [[nodiscard]] bool alive() const noexcept {
- return current == state::running || current == state::paused;
- }
- /**
- * @brief Returns true if a process is already terminated.
- * @return True if the process is terminated, false otherwise.
- */
- [[nodiscard]] bool finished() const noexcept {
- return current == state::finished;
- }
- /**
- * @brief Returns true if a process is currently paused.
- * @return True if the process is paused, false otherwise.
- */
- [[nodiscard]] bool paused() const noexcept {
- return current == state::paused;
- }
- /**
- * @brief Returns true if a process terminated with errors.
- * @return True if the process terminated with errors, false otherwise.
- */
- [[nodiscard]] bool rejected() const noexcept {
- return current == state::rejected;
- }
- /**
- * @brief Assigns a child process to run in case of success.
- * @tparam Type Type of child process to create.
- * @tparam Args Types of arguments to use to initialize the child process.
- * @param args Parameters to use to initialize the child process.
- * @return A reference to the newly created child process.
- */
- template<typename Type, typename... Args>
- basic_process &then(Args &&...args) {
- const auto &allocator = next.second();
- return *(next.first() = std::allocate_shared<Type>(allocator, allocator, std::forward<Args>(args)...));
- }
- /**
- * @brief Assigns a child process to run in case of success.
- * @tparam Func Type of child process to create.
- * @param func Either a lambda or a functor to use as a child process.
- * @return A reference to the newly created child process.
- */
- template<typename Func>
- basic_process &then(Func func) {
- const auto &allocator = next.second();
- using process_type = internal::process_adaptor<delta_type, Func, allocator_type>;
- return *(next.first() = std::allocate_shared<process_type>(allocator, allocator, std::move(func)));
- }
- /**
- * @brief Returns the child process without releasing ownership, if any.
- * @return The child process attached to the object, if any.
- */
- handle_type peek() {
- return next.first();
- }
- /**
- * @brief Updates a process and its internal state, if required.
- * @param delta Elapsed time.
- * @param data Optional data.
- */
- void tick(const Delta delta, void *data = nullptr) {
- switch(current) {
- case state::idle:
- case state::running:
- current = state::running;
- update(delta, data);
- break;
- default:
- // suppress warnings
- break;
- }
- // if it's dead, it must be notified and removed immediately
- switch(current) {
- case state::succeeded:
- succeeded();
- current = state::finished;
- break;
- case state::failed:
- failed();
- current = state::rejected;
- break;
- case state::aborted:
- aborted();
- current = state::rejected;
- break;
- default:
- // suppress warnings
- break;
- }
- }
- private:
- compressed_pair<handle_type, allocator_type> next;
- state current;
- };
- /*! @cond TURN_OFF_DOXYGEN */
- namespace internal {
- template<typename Delta, typename Func, typename Allocator>
- struct process_adaptor: public basic_process<Delta, Allocator> {
- using allocator_type = Allocator;
- using base_type = basic_process<Delta, Allocator>;
- using delta_type = typename base_type::delta_type;
- process_adaptor(const allocator_type &allocator, Func proc)
- : base_type{allocator},
- func{std::move(proc)} {}
- void update(const delta_type delta, void *data) override {
- func(*this, delta, data);
- }
- private:
- Func func;
- };
- } // namespace internal
- /*! @endcond */
- } // namespace entt
- #endif
- namespace entt {
- /**
- * @brief Cooperative scheduler for processes.
- *
- * A cooperative scheduler runs processes and helps managing their life cycles.
- *
- * Each process is invoked once per tick. If a process terminates, it's
- * removed automatically from the scheduler and it's never invoked again.<br/>
- * A process can also have a child. In this case, the process is replaced with
- * its child when it terminates if it returns with success. In case of errors,
- * both the process and its child are discarded.
- *
- * In order to invoke all scheduled processes, call the `update` member function
- * passing it the elapsed time to forward to the tasks.
- *
- * @sa process
- *
- * @tparam Delta Type to use to provide elapsed time.
- * @tparam Allocator Type of allocator used to manage memory and elements.
- */
- template<typename Delta, typename Allocator>
- class basic_scheduler {
- using base_type = basic_process<Delta, Allocator>;
- using alloc_traits = std::allocator_traits<Allocator>;
- using container_allocator = typename alloc_traits::template rebind_alloc<std::shared_ptr<base_type>>;
- using container_type = std::vector<std::shared_ptr<base_type>, container_allocator>;
- public:
- /*! @brief Process type. */
- using type = base_type;
- /*! @brief Allocator type. */
- using allocator_type = Allocator;
- /*! @brief Unsigned integer type. */
- using size_type = std::size_t;
- /*! @brief Unsigned integer type. */
- using delta_type = Delta;
- /*! @brief Default constructor. */
- basic_scheduler()
- : basic_scheduler{allocator_type{}} {}
- /**
- * @brief Constructs a scheduler with a given allocator.
- * @param allocator The allocator to use.
- */
- explicit basic_scheduler(const allocator_type &allocator)
- : handlers{allocator, allocator} {}
- /*! @brief Default copy constructor, deleted on purpose. */
- basic_scheduler(const basic_scheduler &) = delete;
- /**
- * @brief Move constructor.
- * @param other The instance to move from.
- */
- basic_scheduler(basic_scheduler &&other) noexcept
- : handlers{std::move(other.handlers)} {}
- /**
- * @brief Allocator-extended move constructor.
- * @param other The instance to move from.
- * @param allocator The allocator to use.
- */
- basic_scheduler(basic_scheduler &&other, const allocator_type &allocator)
- : handlers{container_type{std::move(other.handlers.first()), allocator}, allocator} {
- ENTT_ASSERT(alloc_traits::is_always_equal::value || get_allocator() == other.get_allocator(), "Copying a scheduler is not allowed");
- }
- /*! @brief Default destructor. */
- ~basic_scheduler() = default;
- /**
- * @brief Default copy assignment operator, deleted on purpose.
- * @return This process scheduler.
- */
- basic_scheduler &operator=(const basic_scheduler &) = delete;
- /**
- * @brief Move assignment operator.
- * @param other The instance to move from.
- * @return This process scheduler.
- */
- basic_scheduler &operator=(basic_scheduler &&other) noexcept {
- ENTT_ASSERT(alloc_traits::is_always_equal::value || get_allocator() == other.get_allocator(), "Copying a scheduler is not allowed");
- swap(other);
- return *this;
- }
- /**
- * @brief Exchanges the contents with those of a given scheduler.
- * @param other Scheduler to exchange the content with.
- */
- void swap(basic_scheduler &other) noexcept {
- using std::swap;
- swap(handlers, other.handlers);
- }
- /**
- * @brief Returns the associated allocator.
- * @return The associated allocator.
- */
- [[nodiscard]] constexpr allocator_type get_allocator() const noexcept {
- return handlers.second();
- }
- /**
- * @brief Number of processes currently scheduled.
- * @return Number of processes currently scheduled.
- */
- [[nodiscard]] size_type size() const noexcept {
- return handlers.first().size();
- }
- /**
- * @brief Returns true if at least a process is currently scheduled.
- * @return True if there are scheduled processes, false otherwise.
- */
- [[nodiscard]] bool empty() const noexcept {
- return handlers.first().empty();
- }
- /**
- * @brief Discards all scheduled processes.
- *
- * Processes aren't aborted. They are discarded along with their children
- * and never executed again.
- */
- void clear() {
- handlers.first().clear();
- }
- /**
- * @brief Schedules a process for the next tick.
- * @tparam Type Type of process to create.
- * @tparam Args Types of arguments to use to initialize the process.
- * @param args Parameters to use to initialize the process.
- * @return A reference to the newly created process.
- */
- template<typename Type, typename... Args>
- type &attach(Args &&...args) {
- const auto &allocator = handlers.second();
- return *handlers.first().emplace_back(std::allocate_shared<Type>(allocator, allocator, std::forward<Args>(args)...));
- }
- /**
- * @brief Schedules a process for the next tick.
- * @tparam Func Type of process to create.
- * @param func Either a lambda or a functor to use as a process.
- * @return A reference to the newly created process.
- */
- template<typename Func>
- type &attach(Func func) {
- const auto &allocator = handlers.second();
- using process_type = internal::process_adaptor<delta_type, Func, allocator_type>;
- return *handlers.first().emplace_back(std::allocate_shared<process_type>(allocator, allocator, std::move(func)));
- }
- /**
- * @brief Updates all scheduled processes.
- *
- * All scheduled processes are executed in no specific order.<br/>
- * If a process terminates with success, it's replaced with its child, if
- * any. Otherwise, if a process terminates with an error, it's removed along
- * with its child.
- *
- * @param delta Elapsed time.
- * @param data Optional data.
- */
- void update(const delta_type delta, void *data = nullptr) {
- for(auto next = handlers.first().size(); next; --next) {
- const auto pos = next - 1u;
- handlers.first()[pos]->tick(delta, data);
- // updating might spawn/reallocate, cannot hold refs until here
- auto &elem = handlers.first()[pos];
- if(elem->finished()) {
- elem = elem->peek();
- }
- if(!elem || elem->rejected()) {
- elem = std::move(handlers.first().back());
- handlers.first().pop_back();
- }
- }
- }
- /**
- * @brief Aborts all scheduled processes.
- *
- * Unless an immediate operation is requested, the abort is scheduled for
- * the next tick. Processes won't be executed anymore in any case.<br/>
- * Once a process is fully aborted and thus finished, it's discarded along
- * with its child, if any.
- *
- * @param immediate Requests an immediate operation.
- */
- void abort(const bool immediate = false) {
- for(auto &&curr: handlers.first()) {
- curr->abort();
- if(immediate) {
- curr->tick({});
- }
- }
- }
- private:
- compressed_pair<container_type, allocator_type> handlers;
- };
- } // namespace entt
- #endif
- // #include "resource/cache.hpp"
- #ifndef ENTT_RESOURCE_RESOURCE_CACHE_HPP
- #define ENTT_RESOURCE_RESOURCE_CACHE_HPP
- #include <cstddef>
- #include <functional>
- #include <iterator>
- #include <memory>
- #include <tuple>
- #include <type_traits>
- #include <utility>
- // #include "../container/dense_map.hpp"
- #ifndef ENTT_CONTAINER_DENSE_MAP_HPP
- #define ENTT_CONTAINER_DENSE_MAP_HPP
- #include <cmath>
- #include <cstddef>
- #include <functional>
- #include <iterator>
- #include <limits>
- #include <memory>
- #include <tuple>
- #include <type_traits>
- #include <utility>
- #include <vector>
- // #include "../config/config.h"
- #ifndef ENTT_CONFIG_CONFIG_H
- #define ENTT_CONFIG_CONFIG_H
- // #include "version.h"
- #ifndef ENTT_CONFIG_VERSION_H
- #define ENTT_CONFIG_VERSION_H
- // #include "macro.h"
- #ifndef ENTT_CONFIG_MACRO_H
- #define ENTT_CONFIG_MACRO_H
- // NOLINTBEGIN(cppcoreguidelines-macro-usage)
- #define ENTT_STR(arg) #arg
- #define ENTT_XSTR(arg) ENTT_STR(arg)
- // NOLINTEND(cppcoreguidelines-macro-usage)
- #endif
- // NOLINTBEGIN(cppcoreguidelines-macro-*,modernize-macro-*)
- #define ENTT_VERSION_MAJOR 3
- #define ENTT_VERSION_MINOR 16
- #define ENTT_VERSION_PATCH 0
- #define ENTT_VERSION \
- ENTT_XSTR(ENTT_VERSION_MAJOR) \
- "." ENTT_XSTR(ENTT_VERSION_MINOR) "." ENTT_XSTR(ENTT_VERSION_PATCH)
- // NOLINTEND(cppcoreguidelines-macro-*,modernize-macro-*)
- #endif
- // NOLINTBEGIN(cppcoreguidelines-macro-usage)
- #if defined(__cpp_exceptions) && !defined(ENTT_NOEXCEPTION)
- # define ENTT_CONSTEXPR
- # define ENTT_THROW throw
- # define ENTT_TRY try
- # define ENTT_CATCH catch(...)
- #else
- # define ENTT_CONSTEXPR constexpr // use only with throwing functions (waiting for C++20)
- # define ENTT_THROW
- # define ENTT_TRY if(true)
- # define ENTT_CATCH if(false)
- #endif
- #if __has_include(<version>)
- # include <version>
- #
- # if defined(__cpp_consteval)
- # define ENTT_CONSTEVAL consteval
- # endif
- #endif
- #ifndef ENTT_CONSTEVAL
- # define ENTT_CONSTEVAL constexpr
- #endif
- #ifdef ENTT_USE_ATOMIC
- # include <atomic>
- # define ENTT_MAYBE_ATOMIC(Type) std::atomic<Type>
- #else
- # define ENTT_MAYBE_ATOMIC(Type) Type
- #endif
- #ifndef ENTT_ID_TYPE
- # include <cstdint>
- # define ENTT_ID_TYPE std::uint32_t
- #else
- # include <cstdint> // provides coverage for types in the std namespace
- #endif
- #ifndef ENTT_SPARSE_PAGE
- # define ENTT_SPARSE_PAGE 4096
- #endif
- #ifndef ENTT_PACKED_PAGE
- # define ENTT_PACKED_PAGE 1024
- #endif
- #ifdef ENTT_DISABLE_ASSERT
- # undef ENTT_ASSERT
- # define ENTT_ASSERT(condition, msg) (void(0))
- #elif !defined ENTT_ASSERT
- # include <cassert>
- # define ENTT_ASSERT(condition, msg) assert(((condition) && (msg)))
- #endif
- #ifdef ENTT_DISABLE_ASSERT
- # undef ENTT_ASSERT_CONSTEXPR
- # define ENTT_ASSERT_CONSTEXPR(condition, msg) (void(0))
- #elif !defined ENTT_ASSERT_CONSTEXPR
- # define ENTT_ASSERT_CONSTEXPR(condition, msg) ENTT_ASSERT(condition, msg)
- #endif
- #define ENTT_FAIL(msg) ENTT_ASSERT(false, msg);
- #ifdef ENTT_NO_ETO
- # define ENTT_ETO_TYPE(Type) void
- #else
- # define ENTT_ETO_TYPE(Type) Type
- #endif
- #ifdef ENTT_NO_MIXIN
- # define ENTT_STORAGE(Mixin, ...) __VA_ARGS__
- #else
- # define ENTT_STORAGE(Mixin, ...) Mixin<__VA_ARGS__>
- #endif
- #ifdef ENTT_STANDARD_CPP
- # define ENTT_NONSTD false
- #else
- # define ENTT_NONSTD true
- # if defined __clang__ || defined __GNUC__
- # define ENTT_PRETTY_FUNCTION __PRETTY_FUNCTION__
- # define ENTT_PRETTY_FUNCTION_PREFIX '='
- # define ENTT_PRETTY_FUNCTION_SUFFIX ']'
- # elif defined _MSC_VER
- # define ENTT_PRETTY_FUNCTION __FUNCSIG__
- # define ENTT_PRETTY_FUNCTION_PREFIX '<'
- # define ENTT_PRETTY_FUNCTION_SUFFIX '>'
- # endif
- #endif
- #ifndef ENTT_EXPORT
- # if defined _WIN32 || defined __CYGWIN__ || defined _MSC_VER
- # define ENTT_EXPORT __declspec(dllexport)
- # define ENTT_IMPORT __declspec(dllimport)
- # define ENTT_HIDDEN
- # elif defined __GNUC__ && __GNUC__ >= 4
- # define ENTT_EXPORT __attribute__((visibility("default")))
- # define ENTT_IMPORT __attribute__((visibility("default")))
- # define ENTT_HIDDEN __attribute__((visibility("hidden")))
- # else /* Unsupported compiler */
- # define ENTT_EXPORT
- # define ENTT_IMPORT
- # define ENTT_HIDDEN
- # endif
- #endif
- #ifndef ENTT_API
- # if defined ENTT_API_EXPORT
- # define ENTT_API ENTT_EXPORT
- # elif defined ENTT_API_IMPORT
- # define ENTT_API ENTT_IMPORT
- # else /* No API */
- # define ENTT_API
- # endif
- #endif
- #if defined _MSC_VER
- # pragma detect_mismatch("entt.version", ENTT_VERSION)
- # pragma detect_mismatch("entt.noexcept", ENTT_XSTR(ENTT_TRY))
- # pragma detect_mismatch("entt.id", ENTT_XSTR(ENTT_ID_TYPE))
- # pragma detect_mismatch("entt.nonstd", ENTT_XSTR(ENTT_NONSTD))
- #endif
- // NOLINTEND(cppcoreguidelines-macro-usage)
- #endif
- // #include "../core/bit.hpp"
- #ifndef ENTT_CORE_BIT_HPP
- #define ENTT_CORE_BIT_HPP
- #include <cstddef>
- #include <limits>
- #include <type_traits>
- // #include "../config/config.h"
- #ifndef ENTT_CONFIG_CONFIG_H
- #define ENTT_CONFIG_CONFIG_H
- // #include "version.h"
- #ifndef ENTT_CONFIG_VERSION_H
- #define ENTT_CONFIG_VERSION_H
- // #include "macro.h"
- #ifndef ENTT_CONFIG_MACRO_H
- #define ENTT_CONFIG_MACRO_H
- // NOLINTBEGIN(cppcoreguidelines-macro-usage)
- #define ENTT_STR(arg) #arg
- #define ENTT_XSTR(arg) ENTT_STR(arg)
- // NOLINTEND(cppcoreguidelines-macro-usage)
- #endif
- // NOLINTBEGIN(cppcoreguidelines-macro-*,modernize-macro-*)
- #define ENTT_VERSION_MAJOR 3
- #define ENTT_VERSION_MINOR 16
- #define ENTT_VERSION_PATCH 0
- #define ENTT_VERSION \
- ENTT_XSTR(ENTT_VERSION_MAJOR) \
- "." ENTT_XSTR(ENTT_VERSION_MINOR) "." ENTT_XSTR(ENTT_VERSION_PATCH)
- // NOLINTEND(cppcoreguidelines-macro-*,modernize-macro-*)
- #endif
- // NOLINTBEGIN(cppcoreguidelines-macro-usage)
- #if defined(__cpp_exceptions) && !defined(ENTT_NOEXCEPTION)
- # define ENTT_CONSTEXPR
- # define ENTT_THROW throw
- # define ENTT_TRY try
- # define ENTT_CATCH catch(...)
- #else
- # define ENTT_CONSTEXPR constexpr // use only with throwing functions (waiting for C++20)
- # define ENTT_THROW
- # define ENTT_TRY if(true)
- # define ENTT_CATCH if(false)
- #endif
- #if __has_include(<version>)
- # include <version>
- #
- # if defined(__cpp_consteval)
- # define ENTT_CONSTEVAL consteval
- # endif
- #endif
- #ifndef ENTT_CONSTEVAL
- # define ENTT_CONSTEVAL constexpr
- #endif
- #ifdef ENTT_USE_ATOMIC
- # include <atomic>
- # define ENTT_MAYBE_ATOMIC(Type) std::atomic<Type>
- #else
- # define ENTT_MAYBE_ATOMIC(Type) Type
- #endif
- #ifndef ENTT_ID_TYPE
- # include <cstdint>
- # define ENTT_ID_TYPE std::uint32_t
- #else
- # include <cstdint> // provides coverage for types in the std namespace
- #endif
- #ifndef ENTT_SPARSE_PAGE
- # define ENTT_SPARSE_PAGE 4096
- #endif
- #ifndef ENTT_PACKED_PAGE
- # define ENTT_PACKED_PAGE 1024
- #endif
- #ifdef ENTT_DISABLE_ASSERT
- # undef ENTT_ASSERT
- # define ENTT_ASSERT(condition, msg) (void(0))
- #elif !defined ENTT_ASSERT
- # include <cassert>
- # define ENTT_ASSERT(condition, msg) assert(((condition) && (msg)))
- #endif
- #ifdef ENTT_DISABLE_ASSERT
- # undef ENTT_ASSERT_CONSTEXPR
- # define ENTT_ASSERT_CONSTEXPR(condition, msg) (void(0))
- #elif !defined ENTT_ASSERT_CONSTEXPR
- # define ENTT_ASSERT_CONSTEXPR(condition, msg) ENTT_ASSERT(condition, msg)
- #endif
- #define ENTT_FAIL(msg) ENTT_ASSERT(false, msg);
- #ifdef ENTT_NO_ETO
- # define ENTT_ETO_TYPE(Type) void
- #else
- # define ENTT_ETO_TYPE(Type) Type
- #endif
- #ifdef ENTT_NO_MIXIN
- # define ENTT_STORAGE(Mixin, ...) __VA_ARGS__
- #else
- # define ENTT_STORAGE(Mixin, ...) Mixin<__VA_ARGS__>
- #endif
- #ifdef ENTT_STANDARD_CPP
- # define ENTT_NONSTD false
- #else
- # define ENTT_NONSTD true
- # if defined __clang__ || defined __GNUC__
- # define ENTT_PRETTY_FUNCTION __PRETTY_FUNCTION__
- # define ENTT_PRETTY_FUNCTION_PREFIX '='
- # define ENTT_PRETTY_FUNCTION_SUFFIX ']'
- # elif defined _MSC_VER
- # define ENTT_PRETTY_FUNCTION __FUNCSIG__
- # define ENTT_PRETTY_FUNCTION_PREFIX '<'
- # define ENTT_PRETTY_FUNCTION_SUFFIX '>'
- # endif
- #endif
- #ifndef ENTT_EXPORT
- # if defined _WIN32 || defined __CYGWIN__ || defined _MSC_VER
- # define ENTT_EXPORT __declspec(dllexport)
- # define ENTT_IMPORT __declspec(dllimport)
- # define ENTT_HIDDEN
- # elif defined __GNUC__ && __GNUC__ >= 4
- # define ENTT_EXPORT __attribute__((visibility("default")))
- # define ENTT_IMPORT __attribute__((visibility("default")))
- # define ENTT_HIDDEN __attribute__((visibility("hidden")))
- # else /* Unsupported compiler */
- # define ENTT_EXPORT
- # define ENTT_IMPORT
- # define ENTT_HIDDEN
- # endif
- #endif
- #ifndef ENTT_API
- # if defined ENTT_API_EXPORT
- # define ENTT_API ENTT_EXPORT
- # elif defined ENTT_API_IMPORT
- # define ENTT_API ENTT_IMPORT
- # else /* No API */
- # define ENTT_API
- # endif
- #endif
- #if defined _MSC_VER
- # pragma detect_mismatch("entt.version", ENTT_VERSION)
- # pragma detect_mismatch("entt.noexcept", ENTT_XSTR(ENTT_TRY))
- # pragma detect_mismatch("entt.id", ENTT_XSTR(ENTT_ID_TYPE))
- # pragma detect_mismatch("entt.nonstd", ENTT_XSTR(ENTT_NONSTD))
- #endif
- // NOLINTEND(cppcoreguidelines-macro-usage)
- #endif
- namespace entt {
- /**
- * @brief Returns the number of set bits in a value (waiting for C++20 and
- * `std::popcount`).
- * @tparam Type Unsigned integer type.
- * @param value A value of unsigned integer type.
- * @return The number of set bits in the value.
- */
- template<typename Type>
- [[nodiscard]] constexpr std::enable_if_t<std::is_unsigned_v<Type>, int> popcount(const Type value) noexcept {
- return value ? (int(value & 1) + popcount(static_cast<Type>(value >> 1))) : 0;
- }
- /**
- * @brief Checks whether a value is a power of two or not (waiting for C++20 and
- * `std::has_single_bit`).
- * @tparam Type Unsigned integer type.
- * @param value A value of unsigned integer type.
- * @return True if the value is a power of two, false otherwise.
- */
- template<typename Type>
- [[nodiscard]] constexpr std::enable_if_t<std::is_unsigned_v<Type>, bool> has_single_bit(const Type value) noexcept {
- return value && ((value & (value - 1)) == 0);
- }
- /**
- * @brief Computes the smallest power of two greater than or equal to a value
- * (waiting for C++20 and `std::bit_ceil`).
- * @tparam Type Unsigned integer type.
- * @param value A value of unsigned integer type.
- * @return The smallest power of two greater than or equal to the given value.
- */
- template<typename Type>
- [[nodiscard]] constexpr std::enable_if_t<std::is_unsigned_v<Type>, Type> next_power_of_two(const Type value) noexcept {
- // NOLINTNEXTLINE(bugprone-assert-side-effect)
- ENTT_ASSERT_CONSTEXPR(value < (Type{1u} << (std::numeric_limits<Type>::digits - 1)), "Numeric limits exceeded");
- Type curr = value - (value != 0u);
- for(int next = 1; next < std::numeric_limits<Type>::digits; next = next * 2) {
- curr |= (curr >> next);
- }
- return ++curr;
- }
- /**
- * @brief Fast module utility function (powers of two only).
- * @tparam Type Unsigned integer type.
- * @param value A value of unsigned integer type.
- * @param mod _Modulus_, it must be a power of two.
- * @return The common remainder.
- */
- template<typename Type>
- [[nodiscard]] constexpr std::enable_if_t<std::is_unsigned_v<Type>, Type> fast_mod(const Type value, const std::size_t mod) noexcept {
- ENTT_ASSERT_CONSTEXPR(has_single_bit(mod), "Value must be a power of two");
- return static_cast<Type>(value & (mod - 1u));
- }
- } // namespace entt
- #endif
- // #include "../core/compressed_pair.hpp"
- #ifndef ENTT_CORE_COMPRESSED_PAIR_HPP
- #define ENTT_CORE_COMPRESSED_PAIR_HPP
- #include <cstddef>
- #include <tuple>
- #include <type_traits>
- #include <utility>
- // #include "fwd.hpp"
- #ifndef ENTT_CORE_FWD_HPP
- #define ENTT_CORE_FWD_HPP
- #include <cstddef>
- #include <cstdint>
- // #include "../config/config.h"
- namespace entt {
- /*! @brief Possible modes of an any object. */
- enum class any_policy : std::uint8_t {
- /*! @brief Default mode, no element available. */
- empty,
- /*! @brief Owning mode, dynamically allocated element. */
- dynamic,
- /*! @brief Owning mode, embedded element. */
- embedded,
- /*! @brief Aliasing mode, non-const reference. */
- ref,
- /*! @brief Const aliasing mode, const reference. */
- cref
- };
- // NOLINTNEXTLINE(cppcoreguidelines-avoid-c-arrays, modernize-avoid-c-arrays)
- template<std::size_t Len = sizeof(double[2]), std::size_t = alignof(double[2])>
- class basic_any;
- /*! @brief Alias declaration for type identifiers. */
- using id_type = ENTT_ID_TYPE;
- /*! @brief Alias declaration for the most common use case. */
- using any = basic_any<>;
- template<typename, typename>
- class compressed_pair;
- template<typename>
- class basic_hashed_string;
- /*! @brief Aliases for common character types. */
- using hashed_string = basic_hashed_string<char>;
- /*! @brief Aliases for common character types. */
- using hashed_wstring = basic_hashed_string<wchar_t>;
- // NOLINTNEXTLINE(bugprone-forward-declaration-namespace)
- struct type_info;
- } // namespace entt
- #endif
- // #include "type_traits.hpp"
- #ifndef ENTT_CORE_TYPE_TRAITS_HPP
- #define ENTT_CORE_TYPE_TRAITS_HPP
- #include <cstddef>
- #include <iterator>
- #include <tuple>
- #include <type_traits>
- #include <utility>
- // #include "../config/config.h"
- // #include "fwd.hpp"
- namespace entt {
- /**
- * @brief Utility class to disambiguate overloaded functions.
- * @tparam N Number of choices available.
- */
- template<std::size_t N>
- struct choice_t
- // unfortunately, doxygen cannot parse such a construct
- : /*! @cond TURN_OFF_DOXYGEN */ choice_t<N - 1> /*! @endcond */
- {};
- /*! @copybrief choice_t */
- template<>
- struct choice_t<0> {};
- /**
- * @brief Variable template for the choice trick.
- * @tparam N Number of choices available.
- */
- template<std::size_t N>
- inline constexpr choice_t<N> choice{};
- /**
- * @brief Identity type trait.
- *
- * Useful to establish non-deduced contexts in template argument deduction
- * (waiting for C++20) or to provide types through function arguments.
- *
- * @tparam Type A type.
- */
- template<typename Type>
- struct type_identity {
- /*! @brief Identity type. */
- using type = Type;
- };
- /**
- * @brief Helper type.
- * @tparam Type A type.
- */
- template<typename Type>
- using type_identity_t = typename type_identity<Type>::type;
- /**
- * @brief A type-only `sizeof` wrapper that returns 0 where `sizeof` complains.
- * @tparam Type The type of which to return the size.
- */
- template<typename Type, typename = void>
- struct size_of: std::integral_constant<std::size_t, 0u> {};
- /*! @copydoc size_of */
- template<typename Type>
- struct size_of<Type, std::void_t<decltype(sizeof(Type))>>
- // NOLINTNEXTLINE(bugprone-sizeof-expression)
- : std::integral_constant<std::size_t, sizeof(Type)> {};
- /**
- * @brief Helper variable template.
- * @tparam Type The type of which to return the size.
- */
- template<typename Type>
- inline constexpr std::size_t size_of_v = size_of<Type>::value;
- /**
- * @brief Using declaration to be used to _repeat_ the same type a number of
- * times equal to the size of a given parameter pack.
- * @tparam Type A type to repeat.
- */
- template<typename Type, typename>
- using unpack_as_type = Type;
- /**
- * @brief Helper variable template to be used to _repeat_ the same value a
- * number of times equal to the size of a given parameter pack.
- * @tparam Value A value to repeat.
- */
- template<auto Value, typename>
- inline constexpr auto unpack_as_value = Value;
- /**
- * @brief Wraps a static constant.
- * @tparam Value A static constant.
- */
- template<auto Value>
- using integral_constant = std::integral_constant<decltype(Value), Value>;
- /**
- * @brief Alias template to facilitate the creation of named values.
- * @tparam Value A constant value at least convertible to `id_type`.
- */
- template<id_type Value>
- using tag = integral_constant<Value>;
- /**
- * @brief A class to use to push around lists of types, nothing more.
- * @tparam Type Types provided by the type list.
- */
- template<typename... Type>
- struct type_list {
- /*! @brief Type list type. */
- using type = type_list;
- /*! @brief Compile-time number of elements in the type list. */
- static constexpr auto size = sizeof...(Type);
- };
- /*! @brief Primary template isn't defined on purpose. */
- template<std::size_t, typename>
- struct type_list_element;
- /**
- * @brief Provides compile-time indexed access to the types of a type list.
- * @tparam Index Index of the type to return.
- * @tparam First First type provided by the type list.
- * @tparam Other Other types provided by the type list.
- */
- template<std::size_t Index, typename First, typename... Other>
- struct type_list_element<Index, type_list<First, Other...>>
- : type_list_element<Index - 1u, type_list<Other...>> {};
- /**
- * @brief Provides compile-time indexed access to the types of a type list.
- * @tparam First First type provided by the type list.
- * @tparam Other Other types provided by the type list.
- */
- template<typename First, typename... Other>
- struct type_list_element<0u, type_list<First, Other...>> {
- /*! @brief Searched type. */
- using type = First;
- };
- /**
- * @brief Helper type.
- * @tparam Index Index of the type to return.
- * @tparam List Type list to search into.
- */
- template<std::size_t Index, typename List>
- using type_list_element_t = typename type_list_element<Index, List>::type;
- /*! @brief Primary template isn't defined on purpose. */
- template<typename, typename>
- struct type_list_index;
- /**
- * @brief Provides compile-time type access to the types of a type list.
- * @tparam Type Type to look for and for which to return the index.
- * @tparam First First type provided by the type list.
- * @tparam Other Other types provided by the type list.
- */
- template<typename Type, typename First, typename... Other>
- struct type_list_index<Type, type_list<First, Other...>> {
- /*! @brief Unsigned integer type. */
- using value_type = std::size_t;
- /*! @brief Compile-time position of the given type in the sublist. */
- static constexpr value_type value = 1u + type_list_index<Type, type_list<Other...>>::value;
- };
- /**
- * @brief Provides compile-time type access to the types of a type list.
- * @tparam Type Type to look for and for which to return the index.
- * @tparam Other Other types provided by the type list.
- */
- template<typename Type, typename... Other>
- struct type_list_index<Type, type_list<Type, Other...>> {
- static_assert(type_list_index<Type, type_list<Other...>>::value == sizeof...(Other), "Non-unique type");
- /*! @brief Unsigned integer type. */
- using value_type = std::size_t;
- /*! @brief Compile-time position of the given type in the sublist. */
- static constexpr value_type value = 0u;
- };
- /**
- * @brief Provides compile-time type access to the types of a type list.
- * @tparam Type Type to look for and for which to return the index.
- */
- template<typename Type>
- struct type_list_index<Type, type_list<>> {
- /*! @brief Unsigned integer type. */
- using value_type = std::size_t;
- /*! @brief Compile-time position of the given type in the sublist. */
- static constexpr value_type value = 0u;
- };
- /**
- * @brief Helper variable template.
- * @tparam List Type list.
- * @tparam Type Type to look for and for which to return the index.
- */
- template<typename Type, typename List>
- inline constexpr std::size_t type_list_index_v = type_list_index<Type, List>::value;
- /**
- * @brief Concatenates multiple type lists.
- * @tparam Type Types provided by the first type list.
- * @tparam Other Types provided by the second type list.
- * @return A type list composed by the types of both the type lists.
- */
- template<typename... Type, typename... Other>
- constexpr type_list<Type..., Other...> operator+(type_list<Type...>, type_list<Other...>) {
- return {};
- }
- /*! @brief Primary template isn't defined on purpose. */
- template<typename...>
- struct type_list_cat;
- /*! @brief Concatenates multiple type lists. */
- template<>
- struct type_list_cat<> {
- /*! @brief A type list composed by the types of all the type lists. */
- using type = type_list<>;
- };
- /**
- * @brief Concatenates multiple type lists.
- * @tparam Type Types provided by the first type list.
- * @tparam Other Types provided by the second type list.
- * @tparam List Other type lists, if any.
- */
- template<typename... Type, typename... Other, typename... List>
- struct type_list_cat<type_list<Type...>, type_list<Other...>, List...> {
- /*! @brief A type list composed by the types of all the type lists. */
- using type = typename type_list_cat<type_list<Type..., Other...>, List...>::type;
- };
- /**
- * @brief Concatenates multiple type lists.
- * @tparam Type Types provided by the type list.
- */
- template<typename... Type>
- struct type_list_cat<type_list<Type...>> {
- /*! @brief A type list composed by the types of all the type lists. */
- using type = type_list<Type...>;
- };
- /**
- * @brief Helper type.
- * @tparam List Type lists to concatenate.
- */
- template<typename... List>
- using type_list_cat_t = typename type_list_cat<List...>::type;
- /*! @cond TURN_OFF_DOXYGEN */
- namespace internal {
- template<typename...>
- struct type_list_unique;
- template<typename First, typename... Other, typename... Type>
- struct type_list_unique<type_list<First, Other...>, Type...>
- : std::conditional_t<(std::is_same_v<First, Type> || ...), type_list_unique<type_list<Other...>, Type...>, type_list_unique<type_list<Other...>, Type..., First>> {};
- template<typename... Type>
- struct type_list_unique<type_list<>, Type...> {
- using type = type_list<Type...>;
- };
- } // namespace internal
- /*! @endcond */
- /**
- * @brief Removes duplicates types from a type list.
- * @tparam List Type list.
- */
- template<typename List>
- struct type_list_unique {
- /*! @brief A type list without duplicate types. */
- using type = typename internal::type_list_unique<List>::type;
- };
- /**
- * @brief Helper type.
- * @tparam List Type list.
- */
- template<typename List>
- using type_list_unique_t = typename type_list_unique<List>::type;
- /**
- * @brief Provides the member constant `value` to true if a type list contains a
- * given type, false otherwise.
- * @tparam List Type list.
- * @tparam Type Type to look for.
- */
- template<typename List, typename Type>
- struct type_list_contains;
- /**
- * @copybrief type_list_contains
- * @tparam Type Types provided by the type list.
- * @tparam Other Type to look for.
- */
- template<typename... Type, typename Other>
- struct type_list_contains<type_list<Type...>, Other>
- : std::bool_constant<(std::is_same_v<Type, Other> || ...)> {};
- /**
- * @brief Helper variable template.
- * @tparam List Type list.
- * @tparam Type Type to look for.
- */
- template<typename List, typename Type>
- inline constexpr bool type_list_contains_v = type_list_contains<List, Type>::value;
- /*! @brief Primary template isn't defined on purpose. */
- template<typename...>
- struct type_list_diff;
- /**
- * @brief Computes the difference between two type lists.
- * @tparam Type Types provided by the first type list.
- * @tparam Other Types provided by the second type list.
- */
- template<typename... Type, typename... Other>
- struct type_list_diff<type_list<Type...>, type_list<Other...>> {
- /*! @brief A type list that is the difference between the two type lists. */
- using type = type_list_cat_t<std::conditional_t<type_list_contains_v<type_list<Other...>, Type>, type_list<>, type_list<Type>>...>;
- };
- /**
- * @brief Helper type.
- * @tparam List Type lists between which to compute the difference.
- */
- template<typename... List>
- using type_list_diff_t = typename type_list_diff<List...>::type;
- /*! @brief Primary template isn't defined on purpose. */
- template<typename, template<typename...> class>
- struct type_list_transform;
- /**
- * @brief Applies a given _function_ to a type list and generate a new list.
- * @tparam Type Types provided by the type list.
- * @tparam Op Unary operation as template class with a type member named `type`.
- */
- template<typename... Type, template<typename...> class Op>
- struct type_list_transform<type_list<Type...>, Op> {
- /*! @brief Resulting type list after applying the transform function. */
- // NOLINTNEXTLINE(modernize-type-traits)
- using type = type_list<typename Op<Type>::type...>;
- };
- /**
- * @brief Helper type.
- * @tparam List Type list.
- * @tparam Op Unary operation as template class with a type member named `type`.
- */
- template<typename List, template<typename...> class Op>
- using type_list_transform_t = typename type_list_transform<List, Op>::type;
- /**
- * @brief A class to use to push around lists of constant values, nothing more.
- * @tparam Value Values provided by the value list.
- */
- template<auto... Value>
- struct value_list {
- /*! @brief Value list type. */
- using type = value_list;
- /*! @brief Compile-time number of elements in the value list. */
- static constexpr auto size = sizeof...(Value);
- };
- /*! @brief Primary template isn't defined on purpose. */
- template<std::size_t, typename>
- struct value_list_element;
- /**
- * @brief Provides compile-time indexed access to the values of a value list.
- * @tparam Index Index of the value to return.
- * @tparam Value First value provided by the value list.
- * @tparam Other Other values provided by the value list.
- */
- template<std::size_t Index, auto Value, auto... Other>
- struct value_list_element<Index, value_list<Value, Other...>>
- : value_list_element<Index - 1u, value_list<Other...>> {};
- /**
- * @brief Provides compile-time indexed access to the types of a type list.
- * @tparam Value First value provided by the value list.
- * @tparam Other Other values provided by the value list.
- */
- template<auto Value, auto... Other>
- struct value_list_element<0u, value_list<Value, Other...>> {
- /*! @brief Searched type. */
- using type = decltype(Value);
- /*! @brief Searched value. */
- static constexpr auto value = Value;
- };
- /**
- * @brief Helper type.
- * @tparam Index Index of the type to return.
- * @tparam List Value list to search into.
- */
- template<std::size_t Index, typename List>
- using value_list_element_t = typename value_list_element<Index, List>::type;
- /**
- * @brief Helper type.
- * @tparam Index Index of the value to return.
- * @tparam List Value list to search into.
- */
- template<std::size_t Index, typename List>
- inline constexpr auto value_list_element_v = value_list_element<Index, List>::value;
- /*! @brief Primary template isn't defined on purpose. */
- template<auto, typename>
- struct value_list_index;
- /**
- * @brief Provides compile-time type access to the values of a value list.
- * @tparam Value Value to look for and for which to return the index.
- * @tparam First First value provided by the value list.
- * @tparam Other Other values provided by the value list.
- */
- template<auto Value, auto First, auto... Other>
- struct value_list_index<Value, value_list<First, Other...>> {
- /*! @brief Unsigned integer type. */
- using value_type = std::size_t;
- /*! @brief Compile-time position of the given value in the sublist. */
- static constexpr value_type value = 1u + value_list_index<Value, value_list<Other...>>::value;
- };
- /**
- * @brief Provides compile-time type access to the values of a value list.
- * @tparam Value Value to look for and for which to return the index.
- * @tparam Other Other values provided by the value list.
- */
- template<auto Value, auto... Other>
- struct value_list_index<Value, value_list<Value, Other...>> {
- static_assert(value_list_index<Value, value_list<Other...>>::value == sizeof...(Other), "Non-unique type");
- /*! @brief Unsigned integer type. */
- using value_type = std::size_t;
- /*! @brief Compile-time position of the given value in the sublist. */
- static constexpr value_type value = 0u;
- };
- /**
- * @brief Provides compile-time type access to the values of a value list.
- * @tparam Value Value to look for and for which to return the index.
- */
- template<auto Value>
- struct value_list_index<Value, value_list<>> {
- /*! @brief Unsigned integer type. */
- using value_type = std::size_t;
- /*! @brief Compile-time position of the given type in the sublist. */
- static constexpr value_type value = 0u;
- };
- /**
- * @brief Helper variable template.
- * @tparam List Value list.
- * @tparam Value Value to look for and for which to return the index.
- */
- template<auto Value, typename List>
- inline constexpr std::size_t value_list_index_v = value_list_index<Value, List>::value;
- /**
- * @brief Concatenates multiple value lists.
- * @tparam Value Values provided by the first value list.
- * @tparam Other Values provided by the second value list.
- * @return A value list composed by the values of both the value lists.
- */
- template<auto... Value, auto... Other>
- constexpr value_list<Value..., Other...> operator+(value_list<Value...>, value_list<Other...>) {
- return {};
- }
- /*! @brief Primary template isn't defined on purpose. */
- template<typename...>
- struct value_list_cat;
- /*! @brief Concatenates multiple value lists. */
- template<>
- struct value_list_cat<> {
- /*! @brief A value list composed by the values of all the value lists. */
- using type = value_list<>;
- };
- /**
- * @brief Concatenates multiple value lists.
- * @tparam Value Values provided by the first value list.
- * @tparam Other Values provided by the second value list.
- * @tparam List Other value lists, if any.
- */
- template<auto... Value, auto... Other, typename... List>
- struct value_list_cat<value_list<Value...>, value_list<Other...>, List...> {
- /*! @brief A value list composed by the values of all the value lists. */
- using type = typename value_list_cat<value_list<Value..., Other...>, List...>::type;
- };
- /**
- * @brief Concatenates multiple value lists.
- * @tparam Value Values provided by the value list.
- */
- template<auto... Value>
- struct value_list_cat<value_list<Value...>> {
- /*! @brief A value list composed by the values of all the value lists. */
- using type = value_list<Value...>;
- };
- /**
- * @brief Helper type.
- * @tparam List Value lists to concatenate.
- */
- template<typename... List>
- using value_list_cat_t = typename value_list_cat<List...>::type;
- /*! @brief Primary template isn't defined on purpose. */
- template<typename>
- struct value_list_unique;
- /**
- * @brief Removes duplicates values from a value list.
- * @tparam Value One of the values provided by the given value list.
- * @tparam Other The other values provided by the given value list.
- */
- template<auto Value, auto... Other>
- struct value_list_unique<value_list<Value, Other...>> {
- /*! @brief A value list without duplicate types. */
- using type = std::conditional_t<
- ((Value == Other) || ...),
- typename value_list_unique<value_list<Other...>>::type,
- value_list_cat_t<value_list<Value>, typename value_list_unique<value_list<Other...>>::type>>;
- };
- /*! @brief Removes duplicates values from a value list. */
- template<>
- struct value_list_unique<value_list<>> {
- /*! @brief A value list without duplicate types. */
- using type = value_list<>;
- };
- /**
- * @brief Helper type.
- * @tparam Type A value list.
- */
- template<typename Type>
- using value_list_unique_t = typename value_list_unique<Type>::type;
- /**
- * @brief Provides the member constant `value` to true if a value list contains
- * a given value, false otherwise.
- * @tparam List Value list.
- * @tparam Value Value to look for.
- */
- template<typename List, auto Value>
- struct value_list_contains;
- /**
- * @copybrief value_list_contains
- * @tparam Value Values provided by the value list.
- * @tparam Other Value to look for.
- */
- template<auto... Value, auto Other>
- struct value_list_contains<value_list<Value...>, Other>
- : std::bool_constant<((Value == Other) || ...)> {};
- /**
- * @brief Helper variable template.
- * @tparam List Value list.
- * @tparam Value Value to look for.
- */
- template<typename List, auto Value>
- inline constexpr bool value_list_contains_v = value_list_contains<List, Value>::value;
- /*! @brief Primary template isn't defined on purpose. */
- template<typename...>
- struct value_list_diff;
- /**
- * @brief Computes the difference between two value lists.
- * @tparam Value Values provided by the first value list.
- * @tparam Other Values provided by the second value list.
- */
- template<auto... Value, auto... Other>
- struct value_list_diff<value_list<Value...>, value_list<Other...>> {
- /*! @brief A value list that is the difference between the two value lists. */
- using type = value_list_cat_t<std::conditional_t<value_list_contains_v<value_list<Other...>, Value>, value_list<>, value_list<Value>>...>;
- };
- /**
- * @brief Helper type.
- * @tparam List Value lists between which to compute the difference.
- */
- template<typename... List>
- using value_list_diff_t = typename value_list_diff<List...>::type;
- /*! @brief Same as std::is_invocable, but with tuples. */
- template<typename, typename>
- struct is_applicable: std::false_type {};
- /**
- * @copybrief is_applicable
- * @tparam Func A valid function type.
- * @tparam Tuple Tuple-like type.
- * @tparam Args The list of arguments to use to probe the function type.
- */
- template<typename Func, template<typename...> class Tuple, typename... Args>
- struct is_applicable<Func, Tuple<Args...>>: std::is_invocable<Func, Args...> {};
- /**
- * @copybrief is_applicable
- * @tparam Func A valid function type.
- * @tparam Tuple Tuple-like type.
- * @tparam Args The list of arguments to use to probe the function type.
- */
- template<typename Func, template<typename...> class Tuple, typename... Args>
- struct is_applicable<Func, const Tuple<Args...>>: std::is_invocable<Func, Args...> {};
- /**
- * @brief Helper variable template.
- * @tparam Func A valid function type.
- * @tparam Args The list of arguments to use to probe the function type.
- */
- template<typename Func, typename Args>
- inline constexpr bool is_applicable_v = is_applicable<Func, Args>::value;
- /*! @brief Same as std::is_invocable_r, but with tuples for arguments. */
- template<typename, typename, typename>
- struct is_applicable_r: std::false_type {};
- /**
- * @copybrief is_applicable_r
- * @tparam Ret The type to which the return type of the function should be
- * convertible.
- * @tparam Func A valid function type.
- * @tparam Args The list of arguments to use to probe the function type.
- */
- template<typename Ret, typename Func, typename... Args>
- struct is_applicable_r<Ret, Func, std::tuple<Args...>>: std::is_invocable_r<Ret, Func, Args...> {};
- /**
- * @brief Helper variable template.
- * @tparam Ret The type to which the return type of the function should be
- * convertible.
- * @tparam Func A valid function type.
- * @tparam Args The list of arguments to use to probe the function type.
- */
- template<typename Ret, typename Func, typename Args>
- inline constexpr bool is_applicable_r_v = is_applicable_r<Ret, Func, Args>::value;
- /**
- * @brief Provides the member constant `value` to true if a given type is
- * complete, false otherwise.
- * @tparam Type The type to test.
- */
- template<typename Type, typename = void>
- struct is_complete: std::false_type {};
- /*! @copydoc is_complete */
- template<typename Type>
- struct is_complete<Type, std::void_t<decltype(sizeof(Type))>>: std::true_type {};
- /**
- * @brief Helper variable template.
- * @tparam Type The type to test.
- */
- template<typename Type>
- inline constexpr bool is_complete_v = is_complete<Type>::value;
- /**
- * @brief Provides the member constant `value` to true if a given type is an
- * iterator, false otherwise.
- * @tparam Type The type to test.
- */
- template<typename Type, typename = void>
- struct is_iterator: std::false_type {};
- /*! @cond TURN_OFF_DOXYGEN */
- namespace internal {
- template<typename, typename = void>
- struct has_iterator_category: std::false_type {};
- template<typename Type>
- struct has_iterator_category<Type, std::void_t<typename std::iterator_traits<Type>::iterator_category>>: std::true_type {};
- } // namespace internal
- /*! @endcond */
- /*! @copydoc is_iterator */
- template<typename Type>
- struct is_iterator<Type, std::enable_if_t<!std::is_void_v<std::remove_const_t<std::remove_pointer_t<Type>>>>>
- : internal::has_iterator_category<Type> {};
- /**
- * @brief Helper variable template.
- * @tparam Type The type to test.
- */
- template<typename Type>
- inline constexpr bool is_iterator_v = is_iterator<Type>::value;
- /**
- * @brief Provides the member constant `value` to true if a given type is both
- * an empty and non-final class, false otherwise.
- * @tparam Type The type to test
- */
- template<typename Type>
- struct is_ebco_eligible
- : std::bool_constant<std::is_empty_v<Type> && !std::is_final_v<Type>> {};
- /**
- * @brief Helper variable template.
- * @tparam Type The type to test.
- */
- template<typename Type>
- inline constexpr bool is_ebco_eligible_v = is_ebco_eligible<Type>::value;
- /**
- * @brief Provides the member constant `value` to true if `Type::is_transparent`
- * is valid and denotes a type, false otherwise.
- * @tparam Type The type to test.
- */
- template<typename Type, typename = void>
- struct is_transparent: std::false_type {};
- /*! @copydoc is_transparent */
- template<typename Type>
- struct is_transparent<Type, std::void_t<typename Type::is_transparent>>: std::true_type {};
- /**
- * @brief Helper variable template.
- * @tparam Type The type to test.
- */
- template<typename Type>
- inline constexpr bool is_transparent_v = is_transparent<Type>::value;
- /*! @cond TURN_OFF_DOXYGEN */
- namespace internal {
- template<typename, typename = void>
- struct has_tuple_size_value: std::false_type {};
- template<typename Type>
- struct has_tuple_size_value<Type, std::void_t<decltype(std::tuple_size<const Type>::value)>>: std::true_type {};
- template<typename, typename = void>
- struct has_value_type: std::false_type {};
- template<typename Type>
- struct has_value_type<Type, std::void_t<typename Type::value_type>>: std::true_type {};
- template<typename>
- [[nodiscard]] constexpr bool dispatch_is_equality_comparable();
- template<typename Type, std::size_t... Index>
- [[nodiscard]] constexpr bool unpack_maybe_equality_comparable(std::index_sequence<Index...>) {
- return (dispatch_is_equality_comparable<std::tuple_element_t<Index, Type>>() && ...);
- }
- template<typename>
- [[nodiscard]] constexpr bool maybe_equality_comparable(char) {
- return false;
- }
- template<typename Type>
- [[nodiscard]] constexpr auto maybe_equality_comparable(int) -> decltype(std::declval<Type>() == std::declval<Type>()) {
- return true;
- }
- template<typename Type>
- [[nodiscard]] constexpr bool dispatch_is_equality_comparable() {
- // NOLINTBEGIN(modernize-use-transparent-functors)
- if constexpr(std::is_array_v<Type>) {
- return false;
- } else if constexpr(is_complete_v<std::tuple_size<std::remove_const_t<Type>>>) {
- if constexpr(has_tuple_size_value<Type>::value) {
- return maybe_equality_comparable<Type>(0) && unpack_maybe_equality_comparable<Type>(std::make_index_sequence<std::tuple_size<Type>::value>{});
- } else {
- return maybe_equality_comparable<Type>(0);
- }
- } else if constexpr(has_value_type<Type>::value) {
- if constexpr(is_iterator_v<Type> || std::is_same_v<typename Type::value_type, Type> || dispatch_is_equality_comparable<typename Type::value_type>()) {
- return maybe_equality_comparable<Type>(0);
- } else {
- return false;
- }
- } else {
- return maybe_equality_comparable<Type>(0);
- }
- // NOLINTEND(modernize-use-transparent-functors)
- }
- } // namespace internal
- /*! @endcond */
- /**
- * @brief Provides the member constant `value` to true if a given type is
- * equality comparable, false otherwise.
- * @tparam Type The type to test.
- */
- template<typename Type>
- struct is_equality_comparable: std::bool_constant<internal::dispatch_is_equality_comparable<Type>()> {};
- /*! @copydoc is_equality_comparable */
- template<typename Type>
- struct is_equality_comparable<const Type>: is_equality_comparable<Type> {};
- /**
- * @brief Helper variable template.
- * @tparam Type The type to test.
- */
- template<typename Type>
- inline constexpr bool is_equality_comparable_v = is_equality_comparable<Type>::value;
- /**
- * @brief Transcribes the constness of a type to another type.
- * @tparam To The type to which to transcribe the constness.
- * @tparam From The type from which to transcribe the constness.
- */
- template<typename To, typename From>
- struct constness_as {
- /*! @brief The type resulting from the transcription of the constness. */
- using type = std::remove_const_t<To>;
- };
- /*! @copydoc constness_as */
- template<typename To, typename From>
- struct constness_as<To, const From> {
- /*! @brief The type resulting from the transcription of the constness. */
- using type = const To;
- };
- /**
- * @brief Alias template to facilitate the transcription of the constness.
- * @tparam To The type to which to transcribe the constness.
- * @tparam From The type from which to transcribe the constness.
- */
- template<typename To, typename From>
- using constness_as_t = typename constness_as<To, From>::type;
- /**
- * @brief Extracts the class of a non-static member object or function.
- * @tparam Member A pointer to a non-static member object or function.
- */
- template<typename Member>
- class member_class {
- static_assert(std::is_member_pointer_v<Member>, "Invalid pointer type to non-static member object or function");
- template<typename Class, typename Ret, typename... Args>
- static Class *clazz(Ret (Class::*)(Args...));
- template<typename Class, typename Ret, typename... Args>
- static Class *clazz(Ret (Class::*)(Args...) const);
- template<typename Class, typename Type>
- static Class *clazz(Type Class::*);
- public:
- /*! @brief The class of the given non-static member object or function. */
- using type = std::remove_pointer_t<decltype(clazz(std::declval<Member>()))>;
- };
- /**
- * @brief Helper type.
- * @tparam Member A pointer to a non-static member object or function.
- */
- template<typename Member>
- using member_class_t = typename member_class<Member>::type;
- /**
- * @brief Extracts the n-th argument of a _callable_ type.
- * @tparam Index The index of the argument to extract.
- * @tparam Candidate A valid _callable_ type.
- */
- template<std::size_t Index, typename Candidate>
- class nth_argument {
- template<typename Ret, typename... Args>
- static constexpr type_list<Args...> pick_up(Ret (*)(Args...));
- template<typename Ret, typename Class, typename... Args>
- static constexpr type_list<Args...> pick_up(Ret (Class ::*)(Args...));
- template<typename Ret, typename Class, typename... Args>
- static constexpr type_list<Args...> pick_up(Ret (Class ::*)(Args...) const);
- template<typename Type, typename Class>
- static constexpr type_list<Type> pick_up(Type Class ::*);
- template<typename Type>
- static constexpr decltype(pick_up(&Type::operator())) pick_up(Type &&);
- public:
- /*! @brief N-th argument of the _callable_ type. */
- using type = type_list_element_t<Index, decltype(pick_up(std::declval<Candidate>()))>;
- };
- /**
- * @brief Helper type.
- * @tparam Index The index of the argument to extract.
- * @tparam Candidate A valid function, member function or data member type.
- */
- template<std::size_t Index, typename Candidate>
- using nth_argument_t = typename nth_argument<Index, Candidate>::type;
- } // namespace entt
- template<typename... Type>
- struct std::tuple_size<entt::type_list<Type...>>: std::integral_constant<std::size_t, entt::type_list<Type...>::size> {};
- template<std::size_t Index, typename... Type>
- struct std::tuple_element<Index, entt::type_list<Type...>>: entt::type_list_element<Index, entt::type_list<Type...>> {};
- template<auto... Value>
- struct std::tuple_size<entt::value_list<Value...>>: std::integral_constant<std::size_t, entt::value_list<Value...>::size> {};
- template<std::size_t Index, auto... Value>
- struct std::tuple_element<Index, entt::value_list<Value...>>: entt::value_list_element<Index, entt::value_list<Value...>> {};
- #endif
- namespace entt {
- /*! @cond TURN_OFF_DOXYGEN */
- namespace internal {
- template<typename Type, std::size_t, typename = void>
- struct compressed_pair_element {
- using reference = Type &;
- using const_reference = const Type &;
- template<typename Dummy = Type, typename = std::enable_if_t<std::is_default_constructible_v<Dummy>>>
- // NOLINTNEXTLINE(modernize-use-equals-default)
- constexpr compressed_pair_element() noexcept(std::is_nothrow_default_constructible_v<Type>) {}
- template<typename Arg, typename = std::enable_if_t<!std::is_same_v<std::remove_const_t<std::remove_reference_t<Arg>>, compressed_pair_element>>>
- constexpr compressed_pair_element(Arg &&arg) noexcept(std::is_nothrow_constructible_v<Type, Arg>)
- : value{std::forward<Arg>(arg)} {}
- template<typename... Args, std::size_t... Index>
- constexpr compressed_pair_element(std::tuple<Args...> args, std::index_sequence<Index...>) noexcept(std::is_nothrow_constructible_v<Type, Args...>)
- : value{std::forward<Args>(std::get<Index>(args))...} {}
- [[nodiscard]] constexpr reference get() noexcept {
- return value;
- }
- [[nodiscard]] constexpr const_reference get() const noexcept {
- return value;
- }
- private:
- Type value{};
- };
- template<typename Type, std::size_t Tag>
- struct compressed_pair_element<Type, Tag, std::enable_if_t<is_ebco_eligible_v<Type>>>: Type {
- using reference = Type &;
- using const_reference = const Type &;
- using base_type = Type;
- template<typename Dummy = Type, typename = std::enable_if_t<std::is_default_constructible_v<Dummy>>>
- constexpr compressed_pair_element() noexcept(std::is_nothrow_default_constructible_v<base_type>)
- : base_type{} {}
- template<typename Arg, typename = std::enable_if_t<!std::is_same_v<std::remove_const_t<std::remove_reference_t<Arg>>, compressed_pair_element>>>
- constexpr compressed_pair_element(Arg &&arg) noexcept(std::is_nothrow_constructible_v<base_type, Arg>)
- : base_type{std::forward<Arg>(arg)} {}
- template<typename... Args, std::size_t... Index>
- constexpr compressed_pair_element(std::tuple<Args...> args, std::index_sequence<Index...>) noexcept(std::is_nothrow_constructible_v<base_type, Args...>)
- : base_type{std::forward<Args>(std::get<Index>(args))...} {}
- [[nodiscard]] constexpr reference get() noexcept {
- return *this;
- }
- [[nodiscard]] constexpr const_reference get() const noexcept {
- return *this;
- }
- };
- } // namespace internal
- /*! @endcond */
- /**
- * @brief A compressed pair.
- *
- * A pair that exploits the _Empty Base Class Optimization_ (or _EBCO_) to
- * reduce its final size to a minimum.
- *
- * @tparam First The type of the first element that the pair stores.
- * @tparam Second The type of the second element that the pair stores.
- */
- template<typename First, typename Second>
- class compressed_pair final
- : internal::compressed_pair_element<First, 0u>,
- internal::compressed_pair_element<Second, 1u> {
- using first_base = internal::compressed_pair_element<First, 0u>;
- using second_base = internal::compressed_pair_element<Second, 1u>;
- public:
- /*! @brief The type of the first element that the pair stores. */
- using first_type = First;
- /*! @brief The type of the second element that the pair stores. */
- using second_type = Second;
- /**
- * @brief Default constructor, conditionally enabled.
- *
- * This constructor is only available when the types that the pair stores
- * are both at least default constructible.
- *
- * @tparam Dummy Dummy template parameter used for internal purposes.
- */
- template<bool Dummy = true, typename = std::enable_if_t<Dummy && std::is_default_constructible_v<first_type> && std::is_default_constructible_v<second_type>>>
- constexpr compressed_pair() noexcept(std::is_nothrow_default_constructible_v<first_base> && std::is_nothrow_default_constructible_v<second_base>)
- : first_base{},
- second_base{} {}
- /**
- * @brief Copy constructor.
- * @param other The instance to copy from.
- */
- constexpr compressed_pair(const compressed_pair &other) = default;
- /**
- * @brief Move constructor.
- * @param other The instance to move from.
- */
- constexpr compressed_pair(compressed_pair &&other) noexcept = default;
- /**
- * @brief Constructs a pair from its values.
- * @tparam Arg Type of value to use to initialize the first element.
- * @tparam Other Type of value to use to initialize the second element.
- * @param arg Value to use to initialize the first element.
- * @param other Value to use to initialize the second element.
- */
- template<typename Arg, typename Other>
- constexpr compressed_pair(Arg &&arg, Other &&other) noexcept(std::is_nothrow_constructible_v<first_base, Arg> && std::is_nothrow_constructible_v<second_base, Other>)
- : first_base{std::forward<Arg>(arg)},
- second_base{std::forward<Other>(other)} {}
- /**
- * @brief Constructs a pair by forwarding the arguments to its parts.
- * @tparam Args Types of arguments to use to initialize the first element.
- * @tparam Other Types of arguments to use to initialize the second element.
- * @param args Arguments to use to initialize the first element.
- * @param other Arguments to use to initialize the second element.
- */
- template<typename... Args, typename... Other>
- constexpr compressed_pair(std::piecewise_construct_t, std::tuple<Args...> args, std::tuple<Other...> other) noexcept(std::is_nothrow_constructible_v<first_base, Args...> && std::is_nothrow_constructible_v<second_base, Other...>)
- : first_base{std::move(args), std::index_sequence_for<Args...>{}},
- second_base{std::move(other), std::index_sequence_for<Other...>{}} {}
- /*! @brief Default destructor. */
- ~compressed_pair() = default;
- /**
- * @brief Copy assignment operator.
- * @param other The instance to copy from.
- * @return This compressed pair object.
- */
- constexpr compressed_pair &operator=(const compressed_pair &other) = default;
- /**
- * @brief Move assignment operator.
- * @param other The instance to move from.
- * @return This compressed pair object.
- */
- constexpr compressed_pair &operator=(compressed_pair &&other) noexcept = default;
- /**
- * @brief Returns the first element that a pair stores.
- * @return The first element that a pair stores.
- */
- [[nodiscard]] constexpr first_type &first() noexcept {
- return static_cast<first_base &>(*this).get();
- }
- /*! @copydoc first */
- [[nodiscard]] constexpr const first_type &first() const noexcept {
- return static_cast<const first_base &>(*this).get();
- }
- /**
- * @brief Returns the second element that a pair stores.
- * @return The second element that a pair stores.
- */
- [[nodiscard]] constexpr second_type &second() noexcept {
- return static_cast<second_base &>(*this).get();
- }
- /*! @copydoc second */
- [[nodiscard]] constexpr const second_type &second() const noexcept {
- return static_cast<const second_base &>(*this).get();
- }
- /**
- * @brief Swaps two compressed pair objects.
- * @param other The compressed pair to swap with.
- */
- constexpr void swap(compressed_pair &other) noexcept {
- using std::swap;
- swap(first(), other.first());
- swap(second(), other.second());
- }
- /**
- * @brief Extracts an element from the compressed pair.
- * @tparam Index An integer value that is either 0 or 1.
- * @return Returns a reference to the first element if `Index` is 0 and a
- * reference to the second element if `Index` is 1.
- */
- template<std::size_t Index>
- [[nodiscard]] constexpr decltype(auto) get() noexcept {
- if constexpr(Index == 0u) {
- return first();
- } else {
- static_assert(Index == 1u, "Index out of bounds");
- return second();
- }
- }
- /*! @copydoc get */
- template<std::size_t Index>
- [[nodiscard]] constexpr decltype(auto) get() const noexcept {
- if constexpr(Index == 0u) {
- return first();
- } else {
- static_assert(Index == 1u, "Index out of bounds");
- return second();
- }
- }
- };
- /**
- * @brief Deduction guide.
- * @tparam Type Type of value to use to initialize the first element.
- * @tparam Other Type of value to use to initialize the second element.
- */
- template<typename Type, typename Other>
- compressed_pair(Type &&, Other &&) -> compressed_pair<std::decay_t<Type>, std::decay_t<Other>>;
- /**
- * @brief Swaps two compressed pair objects.
- * @tparam First The type of the first element that the pairs store.
- * @tparam Second The type of the second element that the pairs store.
- * @param lhs A valid compressed pair object.
- * @param rhs A valid compressed pair object.
- */
- template<typename First, typename Second>
- constexpr void swap(compressed_pair<First, Second> &lhs, compressed_pair<First, Second> &rhs) noexcept {
- lhs.swap(rhs);
- }
- } // namespace entt
- namespace std {
- /**
- * @brief `std::tuple_size` specialization for `compressed_pair`s.
- * @tparam First The type of the first element that the pair stores.
- * @tparam Second The type of the second element that the pair stores.
- */
- template<typename First, typename Second>
- struct tuple_size<entt::compressed_pair<First, Second>>: integral_constant<size_t, 2u> {};
- /**
- * @brief `std::tuple_element` specialization for `compressed_pair`s.
- * @tparam Index The index of the type to return.
- * @tparam First The type of the first element that the pair stores.
- * @tparam Second The type of the second element that the pair stores.
- */
- template<size_t Index, typename First, typename Second>
- struct tuple_element<Index, entt::compressed_pair<First, Second>>: conditional<Index == 0u, First, Second> {
- static_assert(Index < 2u, "Index out of bounds");
- };
- } // namespace std
- #endif
- // #include "../core/iterator.hpp"
- #ifndef ENTT_CORE_ITERATOR_HPP
- #define ENTT_CORE_ITERATOR_HPP
- #include <iterator>
- #include <memory>
- #include <type_traits>
- #include <utility>
- namespace entt {
- /**
- * @brief Helper type to use as pointer with input iterators.
- * @tparam Type of wrapped value.
- */
- template<typename Type>
- struct input_iterator_pointer final {
- /*! @brief Value type. */
- using value_type = Type;
- /*! @brief Pointer type. */
- using pointer = Type *;
- /*! @brief Reference type. */
- using reference = Type &;
- /**
- * @brief Constructs a proxy object by move.
- * @param val Value to use to initialize the proxy object.
- */
- constexpr input_iterator_pointer(value_type &&val) noexcept(std::is_nothrow_move_constructible_v<value_type>)
- : value{std::move(val)} {}
- /**
- * @brief Access operator for accessing wrapped values.
- * @return A pointer to the wrapped value.
- */
- [[nodiscard]] constexpr pointer operator->() noexcept {
- return std::addressof(value);
- }
- /**
- * @brief Dereference operator for accessing wrapped values.
- * @return A reference to the wrapped value.
- */
- [[nodiscard]] constexpr reference operator*() noexcept {
- return value;
- }
- private:
- Type value;
- };
- /**
- * @brief Plain iota iterator (waiting for C++20).
- * @tparam Type Value type.
- */
- template<typename Type>
- class iota_iterator final {
- static_assert(std::is_integral_v<Type>, "Not an integral type");
- public:
- /*! @brief Value type, likely an integral one. */
- using value_type = Type;
- /*! @brief Invalid pointer type. */
- using pointer = void;
- /*! @brief Non-reference type, same as value type. */
- using reference = value_type;
- /*! @brief Difference type. */
- using difference_type = std::ptrdiff_t;
- /*! @brief Iterator category. */
- using iterator_category = std::input_iterator_tag;
- /*! @brief Default constructor. */
- constexpr iota_iterator() noexcept
- : current{} {}
- /**
- * @brief Constructs an iota iterator from a given value.
- * @param init The initial value assigned to the iota iterator.
- */
- constexpr iota_iterator(const value_type init) noexcept
- : current{init} {}
- /**
- * @brief Pre-increment operator.
- * @return This iota iterator.
- */
- constexpr iota_iterator &operator++() noexcept {
- return ++current, *this;
- }
- /**
- * @brief Post-increment operator.
- * @return This iota iterator.
- */
- constexpr iota_iterator operator++(int) noexcept {
- const iota_iterator orig = *this;
- return ++(*this), orig;
- }
- /**
- * @brief Dereference operator.
- * @return The underlying value.
- */
- [[nodiscard]] constexpr reference operator*() const noexcept {
- return current;
- }
- private:
- value_type current;
- };
- /**
- * @brief Comparison operator.
- * @tparam Type Value type of the iota iterator.
- * @param lhs A properly initialized iota iterator.
- * @param rhs A properly initialized iota iterator.
- * @return True if the two iterators are identical, false otherwise.
- */
- template<typename Type>
- [[nodiscard]] constexpr bool operator==(const iota_iterator<Type> &lhs, const iota_iterator<Type> &rhs) noexcept {
- return *lhs == *rhs;
- }
- /**
- * @brief Comparison operator.
- * @tparam Type Value type of the iota iterator.
- * @param lhs A properly initialized iota iterator.
- * @param rhs A properly initialized iota iterator.
- * @return True if the two iterators differ, false otherwise.
- */
- template<typename Type>
- [[nodiscard]] constexpr bool operator!=(const iota_iterator<Type> &lhs, const iota_iterator<Type> &rhs) noexcept {
- return !(lhs == rhs);
- }
- /**
- * @brief Utility class to create an iterable object from a pair of iterators.
- * @tparam It Type of iterator.
- * @tparam Sentinel Type of sentinel.
- */
- template<typename It, typename Sentinel = It>
- struct iterable_adaptor final {
- /*! @brief Value type. */
- using value_type = typename std::iterator_traits<It>::value_type;
- /*! @brief Iterator type. */
- using iterator = It;
- /*! @brief Sentinel type. */
- using sentinel = Sentinel;
- /*! @brief Default constructor. */
- constexpr iterable_adaptor() noexcept(std::is_nothrow_default_constructible_v<iterator> && std::is_nothrow_default_constructible_v<sentinel>)
- : first{},
- last{} {}
- /**
- * @brief Creates an iterable object from a pair of iterators.
- * @param from Begin iterator.
- * @param to End iterator.
- */
- constexpr iterable_adaptor(iterator from, sentinel to) noexcept(std::is_nothrow_move_constructible_v<iterator> && std::is_nothrow_move_constructible_v<sentinel>)
- : first{std::move(from)},
- last{std::move(to)} {}
- /**
- * @brief Returns an iterator to the beginning.
- * @return An iterator to the first element of the range.
- */
- [[nodiscard]] constexpr iterator begin() const noexcept {
- return first;
- }
- /**
- * @brief Returns an iterator to the end.
- * @return An iterator to the element following the last element of the
- * range.
- */
- [[nodiscard]] constexpr sentinel end() const noexcept {
- return last;
- }
- /*! @copydoc begin */
- [[nodiscard]] constexpr iterator cbegin() const noexcept {
- return begin();
- }
- /*! @copydoc end */
- [[nodiscard]] constexpr sentinel cend() const noexcept {
- return end();
- }
- private:
- It first;
- Sentinel last;
- };
- } // namespace entt
- #endif
- // #include "../core/memory.hpp"
- #ifndef ENTT_CORE_MEMORY_HPP
- #define ENTT_CORE_MEMORY_HPP
- #include <cstddef>
- #include <memory>
- #include <tuple>
- #include <type_traits>
- #include <utility>
- // #include "../config/config.h"
- namespace entt {
- /**
- * @brief Unwraps fancy pointers, does nothing otherwise (waiting for C++20).
- * @tparam Type Pointer type.
- * @param ptr Fancy or raw pointer.
- * @return A raw pointer that represents the address of the original pointer.
- */
- template<typename Type>
- [[nodiscard]] constexpr auto to_address(Type &&ptr) noexcept {
- if constexpr(std::is_pointer_v<std::decay_t<Type>>) {
- return ptr;
- } else {
- return to_address(std::forward<Type>(ptr).operator->());
- }
- }
- /**
- * @brief Utility function to design allocation-aware containers.
- * @tparam Allocator Type of allocator.
- * @param lhs A valid allocator.
- * @param rhs Another valid allocator.
- */
- template<typename Allocator>
- constexpr void propagate_on_container_copy_assignment([[maybe_unused]] Allocator &lhs, [[maybe_unused]] Allocator &rhs) noexcept {
- if constexpr(std::allocator_traits<Allocator>::propagate_on_container_copy_assignment::value) {
- lhs = rhs;
- }
- }
- /**
- * @brief Utility function to design allocation-aware containers.
- * @tparam Allocator Type of allocator.
- * @param lhs A valid allocator.
- * @param rhs Another valid allocator.
- */
- template<typename Allocator>
- constexpr void propagate_on_container_move_assignment([[maybe_unused]] Allocator &lhs, [[maybe_unused]] Allocator &rhs) noexcept {
- if constexpr(std::allocator_traits<Allocator>::propagate_on_container_move_assignment::value) {
- lhs = std::move(rhs);
- }
- }
- /**
- * @brief Utility function to design allocation-aware containers.
- * @tparam Allocator Type of allocator.
- * @param lhs A valid allocator.
- * @param rhs Another valid allocator.
- */
- template<typename Allocator>
- constexpr void propagate_on_container_swap([[maybe_unused]] Allocator &lhs, [[maybe_unused]] Allocator &rhs) noexcept {
- if constexpr(std::allocator_traits<Allocator>::propagate_on_container_swap::value) {
- using std::swap;
- swap(lhs, rhs);
- } else {
- ENTT_ASSERT_CONSTEXPR(lhs == rhs, "Cannot swap the containers");
- }
- }
- /**
- * @brief Deleter for allocator-aware unique pointers (waiting for C++20).
- * @tparam Allocator Type of allocator used to manage memory and elements.
- */
- template<typename Allocator>
- struct allocation_deleter: private Allocator {
- /*! @brief Allocator type. */
- using allocator_type = Allocator;
- /*! @brief Pointer type. */
- using pointer = typename std::allocator_traits<Allocator>::pointer;
- /**
- * @brief Inherited constructors.
- * @param alloc The allocator to use.
- */
- constexpr allocation_deleter(const allocator_type &alloc) noexcept(std::is_nothrow_copy_constructible_v<allocator_type>)
- : Allocator{alloc} {}
- /**
- * @brief Destroys the pointed object and deallocates its memory.
- * @param ptr A valid pointer to an object of the given type.
- */
- constexpr void operator()(pointer ptr) noexcept(std::is_nothrow_destructible_v<typename allocator_type::value_type>) {
- using alloc_traits = std::allocator_traits<Allocator>;
- alloc_traits::destroy(*this, to_address(ptr));
- alloc_traits::deallocate(*this, ptr, 1u);
- }
- };
- /**
- * @brief Allows `std::unique_ptr` to use allocators (waiting for C++20).
- * @tparam Type Type of object to allocate for and to construct.
- * @tparam Allocator Type of allocator used to manage memory and elements.
- * @tparam Args Types of arguments to use to construct the object.
- * @param allocator The allocator to use.
- * @param args Parameters to use to construct the object.
- * @return A properly initialized unique pointer with a custom deleter.
- */
- template<typename Type, typename Allocator, typename... Args>
- ENTT_CONSTEXPR auto allocate_unique(Allocator &allocator, Args &&...args) {
- static_assert(!std::is_array_v<Type>, "Array types are not supported");
- using alloc_traits = typename std::allocator_traits<Allocator>::template rebind_traits<Type>;
- using allocator_type = typename alloc_traits::allocator_type;
- allocator_type alloc{allocator};
- auto ptr = alloc_traits::allocate(alloc, 1u);
- ENTT_TRY {
- alloc_traits::construct(alloc, to_address(ptr), std::forward<Args>(args)...);
- }
- ENTT_CATCH {
- alloc_traits::deallocate(alloc, ptr, 1u);
- ENTT_THROW;
- }
- return std::unique_ptr<Type, allocation_deleter<allocator_type>>{ptr, alloc};
- }
- /*! @cond TURN_OFF_DOXYGEN */
- namespace internal {
- template<typename Type>
- struct uses_allocator_construction {
- template<typename Allocator, typename... Params>
- static constexpr auto args([[maybe_unused]] const Allocator &allocator, Params &&...params) noexcept {
- if constexpr(!std::uses_allocator_v<Type, Allocator> && std::is_constructible_v<Type, Params...>) {
- return std::forward_as_tuple(std::forward<Params>(params)...);
- } else {
- static_assert(std::uses_allocator_v<Type, Allocator>, "Ill-formed request");
- if constexpr(std::is_constructible_v<Type, std::allocator_arg_t, const Allocator &, Params...>) {
- return std::tuple<std::allocator_arg_t, const Allocator &, Params &&...>{std::allocator_arg, allocator, std::forward<Params>(params)...};
- } else {
- static_assert(std::is_constructible_v<Type, Params..., const Allocator &>, "Ill-formed request");
- return std::forward_as_tuple(std::forward<Params>(params)..., allocator);
- }
- }
- }
- };
- template<typename Type, typename Other>
- struct uses_allocator_construction<std::pair<Type, Other>> {
- using type = std::pair<Type, Other>;
- template<typename Allocator, typename First, typename Second>
- static constexpr auto args(const Allocator &allocator, std::piecewise_construct_t, First &&first, Second &&second) noexcept {
- return std::make_tuple(
- std::piecewise_construct,
- std::apply([&allocator](auto &&...curr) { return uses_allocator_construction<Type>::args(allocator, std::forward<decltype(curr)>(curr)...); }, std::forward<First>(first)),
- std::apply([&allocator](auto &&...curr) { return uses_allocator_construction<Other>::args(allocator, std::forward<decltype(curr)>(curr)...); }, std::forward<Second>(second)));
- }
- template<typename Allocator>
- static constexpr auto args(const Allocator &allocator) noexcept {
- return uses_allocator_construction<type>::args(allocator, std::piecewise_construct, std::tuple<>{}, std::tuple<>{});
- }
- template<typename Allocator, typename First, typename Second>
- static constexpr auto args(const Allocator &allocator, First &&first, Second &&second) noexcept {
- return uses_allocator_construction<type>::args(allocator, std::piecewise_construct, std::forward_as_tuple(std::forward<First>(first)), std::forward_as_tuple(std::forward<Second>(second)));
- }
- template<typename Allocator, typename First, typename Second>
- static constexpr auto args(const Allocator &allocator, const std::pair<First, Second> &value) noexcept {
- return uses_allocator_construction<type>::args(allocator, std::piecewise_construct, std::forward_as_tuple(value.first), std::forward_as_tuple(value.second));
- }
- template<typename Allocator, typename First, typename Second>
- static constexpr auto args(const Allocator &allocator, std::pair<First, Second> &&value) noexcept {
- return uses_allocator_construction<type>::args(allocator, std::piecewise_construct, std::forward_as_tuple(std::move(value.first)), std::forward_as_tuple(std::move(value.second)));
- }
- };
- } // namespace internal
- /*! @endcond */
- /**
- * @brief Uses-allocator construction utility (waiting for C++20).
- *
- * Primarily intended for internal use. Prepares the argument list needed to
- * create an object of a given type by means of uses-allocator construction.
- *
- * @tparam Type Type to return arguments for.
- * @tparam Allocator Type of allocator used to manage memory and elements.
- * @tparam Args Types of arguments to use to construct the object.
- * @param allocator The allocator to use.
- * @param args Parameters to use to construct the object.
- * @return The arguments needed to create an object of the given type.
- */
- template<typename Type, typename Allocator, typename... Args>
- constexpr auto uses_allocator_construction_args(const Allocator &allocator, Args &&...args) noexcept {
- return internal::uses_allocator_construction<Type>::args(allocator, std::forward<Args>(args)...);
- }
- /**
- * @brief Uses-allocator construction utility (waiting for C++20).
- *
- * Primarily intended for internal use. Creates an object of a given type by
- * means of uses-allocator construction.
- *
- * @tparam Type Type of object to create.
- * @tparam Allocator Type of allocator used to manage memory and elements.
- * @tparam Args Types of arguments to use to construct the object.
- * @param allocator The allocator to use.
- * @param args Parameters to use to construct the object.
- * @return A newly created object of the given type.
- */
- template<typename Type, typename Allocator, typename... Args>
- constexpr Type make_obj_using_allocator(const Allocator &allocator, Args &&...args) {
- return std::make_from_tuple<Type>(internal::uses_allocator_construction<Type>::args(allocator, std::forward<Args>(args)...));
- }
- /**
- * @brief Uses-allocator construction utility (waiting for C++20).
- *
- * Primarily intended for internal use. Creates an object of a given type by
- * means of uses-allocator construction at an uninitialized memory location.
- *
- * @tparam Type Type of object to create.
- * @tparam Allocator Type of allocator used to manage memory and elements.
- * @tparam Args Types of arguments to use to construct the object.
- * @param value Memory location in which to place the object.
- * @param allocator The allocator to use.
- * @param args Parameters to use to construct the object.
- * @return A pointer to the newly created object of the given type.
- */
- template<typename Type, typename Allocator, typename... Args>
- constexpr Type *uninitialized_construct_using_allocator(Type *value, const Allocator &allocator, Args &&...args) {
- return std::apply([value](auto &&...curr) { return ::new(value) Type(std::forward<decltype(curr)>(curr)...); }, internal::uses_allocator_construction<Type>::args(allocator, std::forward<Args>(args)...));
- }
- } // namespace entt
- #endif
- // #include "../core/type_traits.hpp"
- #ifndef ENTT_CORE_TYPE_TRAITS_HPP
- #define ENTT_CORE_TYPE_TRAITS_HPP
- #include <cstddef>
- #include <iterator>
- #include <tuple>
- #include <type_traits>
- #include <utility>
- // #include "../config/config.h"
- // #include "fwd.hpp"
- namespace entt {
- /**
- * @brief Utility class to disambiguate overloaded functions.
- * @tparam N Number of choices available.
- */
- template<std::size_t N>
- struct choice_t
- // unfortunately, doxygen cannot parse such a construct
- : /*! @cond TURN_OFF_DOXYGEN */ choice_t<N - 1> /*! @endcond */
- {};
- /*! @copybrief choice_t */
- template<>
- struct choice_t<0> {};
- /**
- * @brief Variable template for the choice trick.
- * @tparam N Number of choices available.
- */
- template<std::size_t N>
- inline constexpr choice_t<N> choice{};
- /**
- * @brief Identity type trait.
- *
- * Useful to establish non-deduced contexts in template argument deduction
- * (waiting for C++20) or to provide types through function arguments.
- *
- * @tparam Type A type.
- */
- template<typename Type>
- struct type_identity {
- /*! @brief Identity type. */
- using type = Type;
- };
- /**
- * @brief Helper type.
- * @tparam Type A type.
- */
- template<typename Type>
- using type_identity_t = typename type_identity<Type>::type;
- /**
- * @brief A type-only `sizeof` wrapper that returns 0 where `sizeof` complains.
- * @tparam Type The type of which to return the size.
- */
- template<typename Type, typename = void>
- struct size_of: std::integral_constant<std::size_t, 0u> {};
- /*! @copydoc size_of */
- template<typename Type>
- struct size_of<Type, std::void_t<decltype(sizeof(Type))>>
- // NOLINTNEXTLINE(bugprone-sizeof-expression)
- : std::integral_constant<std::size_t, sizeof(Type)> {};
- /**
- * @brief Helper variable template.
- * @tparam Type The type of which to return the size.
- */
- template<typename Type>
- inline constexpr std::size_t size_of_v = size_of<Type>::value;
- /**
- * @brief Using declaration to be used to _repeat_ the same type a number of
- * times equal to the size of a given parameter pack.
- * @tparam Type A type to repeat.
- */
- template<typename Type, typename>
- using unpack_as_type = Type;
- /**
- * @brief Helper variable template to be used to _repeat_ the same value a
- * number of times equal to the size of a given parameter pack.
- * @tparam Value A value to repeat.
- */
- template<auto Value, typename>
- inline constexpr auto unpack_as_value = Value;
- /**
- * @brief Wraps a static constant.
- * @tparam Value A static constant.
- */
- template<auto Value>
- using integral_constant = std::integral_constant<decltype(Value), Value>;
- /**
- * @brief Alias template to facilitate the creation of named values.
- * @tparam Value A constant value at least convertible to `id_type`.
- */
- template<id_type Value>
- using tag = integral_constant<Value>;
- /**
- * @brief A class to use to push around lists of types, nothing more.
- * @tparam Type Types provided by the type list.
- */
- template<typename... Type>
- struct type_list {
- /*! @brief Type list type. */
- using type = type_list;
- /*! @brief Compile-time number of elements in the type list. */
- static constexpr auto size = sizeof...(Type);
- };
- /*! @brief Primary template isn't defined on purpose. */
- template<std::size_t, typename>
- struct type_list_element;
- /**
- * @brief Provides compile-time indexed access to the types of a type list.
- * @tparam Index Index of the type to return.
- * @tparam First First type provided by the type list.
- * @tparam Other Other types provided by the type list.
- */
- template<std::size_t Index, typename First, typename... Other>
- struct type_list_element<Index, type_list<First, Other...>>
- : type_list_element<Index - 1u, type_list<Other...>> {};
- /**
- * @brief Provides compile-time indexed access to the types of a type list.
- * @tparam First First type provided by the type list.
- * @tparam Other Other types provided by the type list.
- */
- template<typename First, typename... Other>
- struct type_list_element<0u, type_list<First, Other...>> {
- /*! @brief Searched type. */
- using type = First;
- };
- /**
- * @brief Helper type.
- * @tparam Index Index of the type to return.
- * @tparam List Type list to search into.
- */
- template<std::size_t Index, typename List>
- using type_list_element_t = typename type_list_element<Index, List>::type;
- /*! @brief Primary template isn't defined on purpose. */
- template<typename, typename>
- struct type_list_index;
- /**
- * @brief Provides compile-time type access to the types of a type list.
- * @tparam Type Type to look for and for which to return the index.
- * @tparam First First type provided by the type list.
- * @tparam Other Other types provided by the type list.
- */
- template<typename Type, typename First, typename... Other>
- struct type_list_index<Type, type_list<First, Other...>> {
- /*! @brief Unsigned integer type. */
- using value_type = std::size_t;
- /*! @brief Compile-time position of the given type in the sublist. */
- static constexpr value_type value = 1u + type_list_index<Type, type_list<Other...>>::value;
- };
- /**
- * @brief Provides compile-time type access to the types of a type list.
- * @tparam Type Type to look for and for which to return the index.
- * @tparam Other Other types provided by the type list.
- */
- template<typename Type, typename... Other>
- struct type_list_index<Type, type_list<Type, Other...>> {
- static_assert(type_list_index<Type, type_list<Other...>>::value == sizeof...(Other), "Non-unique type");
- /*! @brief Unsigned integer type. */
- using value_type = std::size_t;
- /*! @brief Compile-time position of the given type in the sublist. */
- static constexpr value_type value = 0u;
- };
- /**
- * @brief Provides compile-time type access to the types of a type list.
- * @tparam Type Type to look for and for which to return the index.
- */
- template<typename Type>
- struct type_list_index<Type, type_list<>> {
- /*! @brief Unsigned integer type. */
- using value_type = std::size_t;
- /*! @brief Compile-time position of the given type in the sublist. */
- static constexpr value_type value = 0u;
- };
- /**
- * @brief Helper variable template.
- * @tparam List Type list.
- * @tparam Type Type to look for and for which to return the index.
- */
- template<typename Type, typename List>
- inline constexpr std::size_t type_list_index_v = type_list_index<Type, List>::value;
- /**
- * @brief Concatenates multiple type lists.
- * @tparam Type Types provided by the first type list.
- * @tparam Other Types provided by the second type list.
- * @return A type list composed by the types of both the type lists.
- */
- template<typename... Type, typename... Other>
- constexpr type_list<Type..., Other...> operator+(type_list<Type...>, type_list<Other...>) {
- return {};
- }
- /*! @brief Primary template isn't defined on purpose. */
- template<typename...>
- struct type_list_cat;
- /*! @brief Concatenates multiple type lists. */
- template<>
- struct type_list_cat<> {
- /*! @brief A type list composed by the types of all the type lists. */
- using type = type_list<>;
- };
- /**
- * @brief Concatenates multiple type lists.
- * @tparam Type Types provided by the first type list.
- * @tparam Other Types provided by the second type list.
- * @tparam List Other type lists, if any.
- */
- template<typename... Type, typename... Other, typename... List>
- struct type_list_cat<type_list<Type...>, type_list<Other...>, List...> {
- /*! @brief A type list composed by the types of all the type lists. */
- using type = typename type_list_cat<type_list<Type..., Other...>, List...>::type;
- };
- /**
- * @brief Concatenates multiple type lists.
- * @tparam Type Types provided by the type list.
- */
- template<typename... Type>
- struct type_list_cat<type_list<Type...>> {
- /*! @brief A type list composed by the types of all the type lists. */
- using type = type_list<Type...>;
- };
- /**
- * @brief Helper type.
- * @tparam List Type lists to concatenate.
- */
- template<typename... List>
- using type_list_cat_t = typename type_list_cat<List...>::type;
- /*! @cond TURN_OFF_DOXYGEN */
- namespace internal {
- template<typename...>
- struct type_list_unique;
- template<typename First, typename... Other, typename... Type>
- struct type_list_unique<type_list<First, Other...>, Type...>
- : std::conditional_t<(std::is_same_v<First, Type> || ...), type_list_unique<type_list<Other...>, Type...>, type_list_unique<type_list<Other...>, Type..., First>> {};
- template<typename... Type>
- struct type_list_unique<type_list<>, Type...> {
- using type = type_list<Type...>;
- };
- } // namespace internal
- /*! @endcond */
- /**
- * @brief Removes duplicates types from a type list.
- * @tparam List Type list.
- */
- template<typename List>
- struct type_list_unique {
- /*! @brief A type list without duplicate types. */
- using type = typename internal::type_list_unique<List>::type;
- };
- /**
- * @brief Helper type.
- * @tparam List Type list.
- */
- template<typename List>
- using type_list_unique_t = typename type_list_unique<List>::type;
- /**
- * @brief Provides the member constant `value` to true if a type list contains a
- * given type, false otherwise.
- * @tparam List Type list.
- * @tparam Type Type to look for.
- */
- template<typename List, typename Type>
- struct type_list_contains;
- /**
- * @copybrief type_list_contains
- * @tparam Type Types provided by the type list.
- * @tparam Other Type to look for.
- */
- template<typename... Type, typename Other>
- struct type_list_contains<type_list<Type...>, Other>
- : std::bool_constant<(std::is_same_v<Type, Other> || ...)> {};
- /**
- * @brief Helper variable template.
- * @tparam List Type list.
- * @tparam Type Type to look for.
- */
- template<typename List, typename Type>
- inline constexpr bool type_list_contains_v = type_list_contains<List, Type>::value;
- /*! @brief Primary template isn't defined on purpose. */
- template<typename...>
- struct type_list_diff;
- /**
- * @brief Computes the difference between two type lists.
- * @tparam Type Types provided by the first type list.
- * @tparam Other Types provided by the second type list.
- */
- template<typename... Type, typename... Other>
- struct type_list_diff<type_list<Type...>, type_list<Other...>> {
- /*! @brief A type list that is the difference between the two type lists. */
- using type = type_list_cat_t<std::conditional_t<type_list_contains_v<type_list<Other...>, Type>, type_list<>, type_list<Type>>...>;
- };
- /**
- * @brief Helper type.
- * @tparam List Type lists between which to compute the difference.
- */
- template<typename... List>
- using type_list_diff_t = typename type_list_diff<List...>::type;
- /*! @brief Primary template isn't defined on purpose. */
- template<typename, template<typename...> class>
- struct type_list_transform;
- /**
- * @brief Applies a given _function_ to a type list and generate a new list.
- * @tparam Type Types provided by the type list.
- * @tparam Op Unary operation as template class with a type member named `type`.
- */
- template<typename... Type, template<typename...> class Op>
- struct type_list_transform<type_list<Type...>, Op> {
- /*! @brief Resulting type list after applying the transform function. */
- // NOLINTNEXTLINE(modernize-type-traits)
- using type = type_list<typename Op<Type>::type...>;
- };
- /**
- * @brief Helper type.
- * @tparam List Type list.
- * @tparam Op Unary operation as template class with a type member named `type`.
- */
- template<typename List, template<typename...> class Op>
- using type_list_transform_t = typename type_list_transform<List, Op>::type;
- /**
- * @brief A class to use to push around lists of constant values, nothing more.
- * @tparam Value Values provided by the value list.
- */
- template<auto... Value>
- struct value_list {
- /*! @brief Value list type. */
- using type = value_list;
- /*! @brief Compile-time number of elements in the value list. */
- static constexpr auto size = sizeof...(Value);
- };
- /*! @brief Primary template isn't defined on purpose. */
- template<std::size_t, typename>
- struct value_list_element;
- /**
- * @brief Provides compile-time indexed access to the values of a value list.
- * @tparam Index Index of the value to return.
- * @tparam Value First value provided by the value list.
- * @tparam Other Other values provided by the value list.
- */
- template<std::size_t Index, auto Value, auto... Other>
- struct value_list_element<Index, value_list<Value, Other...>>
- : value_list_element<Index - 1u, value_list<Other...>> {};
- /**
- * @brief Provides compile-time indexed access to the types of a type list.
- * @tparam Value First value provided by the value list.
- * @tparam Other Other values provided by the value list.
- */
- template<auto Value, auto... Other>
- struct value_list_element<0u, value_list<Value, Other...>> {
- /*! @brief Searched type. */
- using type = decltype(Value);
- /*! @brief Searched value. */
- static constexpr auto value = Value;
- };
- /**
- * @brief Helper type.
- * @tparam Index Index of the type to return.
- * @tparam List Value list to search into.
- */
- template<std::size_t Index, typename List>
- using value_list_element_t = typename value_list_element<Index, List>::type;
- /**
- * @brief Helper type.
- * @tparam Index Index of the value to return.
- * @tparam List Value list to search into.
- */
- template<std::size_t Index, typename List>
- inline constexpr auto value_list_element_v = value_list_element<Index, List>::value;
- /*! @brief Primary template isn't defined on purpose. */
- template<auto, typename>
- struct value_list_index;
- /**
- * @brief Provides compile-time type access to the values of a value list.
- * @tparam Value Value to look for and for which to return the index.
- * @tparam First First value provided by the value list.
- * @tparam Other Other values provided by the value list.
- */
- template<auto Value, auto First, auto... Other>
- struct value_list_index<Value, value_list<First, Other...>> {
- /*! @brief Unsigned integer type. */
- using value_type = std::size_t;
- /*! @brief Compile-time position of the given value in the sublist. */
- static constexpr value_type value = 1u + value_list_index<Value, value_list<Other...>>::value;
- };
- /**
- * @brief Provides compile-time type access to the values of a value list.
- * @tparam Value Value to look for and for which to return the index.
- * @tparam Other Other values provided by the value list.
- */
- template<auto Value, auto... Other>
- struct value_list_index<Value, value_list<Value, Other...>> {
- static_assert(value_list_index<Value, value_list<Other...>>::value == sizeof...(Other), "Non-unique type");
- /*! @brief Unsigned integer type. */
- using value_type = std::size_t;
- /*! @brief Compile-time position of the given value in the sublist. */
- static constexpr value_type value = 0u;
- };
- /**
- * @brief Provides compile-time type access to the values of a value list.
- * @tparam Value Value to look for and for which to return the index.
- */
- template<auto Value>
- struct value_list_index<Value, value_list<>> {
- /*! @brief Unsigned integer type. */
- using value_type = std::size_t;
- /*! @brief Compile-time position of the given type in the sublist. */
- static constexpr value_type value = 0u;
- };
- /**
- * @brief Helper variable template.
- * @tparam List Value list.
- * @tparam Value Value to look for and for which to return the index.
- */
- template<auto Value, typename List>
- inline constexpr std::size_t value_list_index_v = value_list_index<Value, List>::value;
- /**
- * @brief Concatenates multiple value lists.
- * @tparam Value Values provided by the first value list.
- * @tparam Other Values provided by the second value list.
- * @return A value list composed by the values of both the value lists.
- */
- template<auto... Value, auto... Other>
- constexpr value_list<Value..., Other...> operator+(value_list<Value...>, value_list<Other...>) {
- return {};
- }
- /*! @brief Primary template isn't defined on purpose. */
- template<typename...>
- struct value_list_cat;
- /*! @brief Concatenates multiple value lists. */
- template<>
- struct value_list_cat<> {
- /*! @brief A value list composed by the values of all the value lists. */
- using type = value_list<>;
- };
- /**
- * @brief Concatenates multiple value lists.
- * @tparam Value Values provided by the first value list.
- * @tparam Other Values provided by the second value list.
- * @tparam List Other value lists, if any.
- */
- template<auto... Value, auto... Other, typename... List>
- struct value_list_cat<value_list<Value...>, value_list<Other...>, List...> {
- /*! @brief A value list composed by the values of all the value lists. */
- using type = typename value_list_cat<value_list<Value..., Other...>, List...>::type;
- };
- /**
- * @brief Concatenates multiple value lists.
- * @tparam Value Values provided by the value list.
- */
- template<auto... Value>
- struct value_list_cat<value_list<Value...>> {
- /*! @brief A value list composed by the values of all the value lists. */
- using type = value_list<Value...>;
- };
- /**
- * @brief Helper type.
- * @tparam List Value lists to concatenate.
- */
- template<typename... List>
- using value_list_cat_t = typename value_list_cat<List...>::type;
- /*! @brief Primary template isn't defined on purpose. */
- template<typename>
- struct value_list_unique;
- /**
- * @brief Removes duplicates values from a value list.
- * @tparam Value One of the values provided by the given value list.
- * @tparam Other The other values provided by the given value list.
- */
- template<auto Value, auto... Other>
- struct value_list_unique<value_list<Value, Other...>> {
- /*! @brief A value list without duplicate types. */
- using type = std::conditional_t<
- ((Value == Other) || ...),
- typename value_list_unique<value_list<Other...>>::type,
- value_list_cat_t<value_list<Value>, typename value_list_unique<value_list<Other...>>::type>>;
- };
- /*! @brief Removes duplicates values from a value list. */
- template<>
- struct value_list_unique<value_list<>> {
- /*! @brief A value list without duplicate types. */
- using type = value_list<>;
- };
- /**
- * @brief Helper type.
- * @tparam Type A value list.
- */
- template<typename Type>
- using value_list_unique_t = typename value_list_unique<Type>::type;
- /**
- * @brief Provides the member constant `value` to true if a value list contains
- * a given value, false otherwise.
- * @tparam List Value list.
- * @tparam Value Value to look for.
- */
- template<typename List, auto Value>
- struct value_list_contains;
- /**
- * @copybrief value_list_contains
- * @tparam Value Values provided by the value list.
- * @tparam Other Value to look for.
- */
- template<auto... Value, auto Other>
- struct value_list_contains<value_list<Value...>, Other>
- : std::bool_constant<((Value == Other) || ...)> {};
- /**
- * @brief Helper variable template.
- * @tparam List Value list.
- * @tparam Value Value to look for.
- */
- template<typename List, auto Value>
- inline constexpr bool value_list_contains_v = value_list_contains<List, Value>::value;
- /*! @brief Primary template isn't defined on purpose. */
- template<typename...>
- struct value_list_diff;
- /**
- * @brief Computes the difference between two value lists.
- * @tparam Value Values provided by the first value list.
- * @tparam Other Values provided by the second value list.
- */
- template<auto... Value, auto... Other>
- struct value_list_diff<value_list<Value...>, value_list<Other...>> {
- /*! @brief A value list that is the difference between the two value lists. */
- using type = value_list_cat_t<std::conditional_t<value_list_contains_v<value_list<Other...>, Value>, value_list<>, value_list<Value>>...>;
- };
- /**
- * @brief Helper type.
- * @tparam List Value lists between which to compute the difference.
- */
- template<typename... List>
- using value_list_diff_t = typename value_list_diff<List...>::type;
- /*! @brief Same as std::is_invocable, but with tuples. */
- template<typename, typename>
- struct is_applicable: std::false_type {};
- /**
- * @copybrief is_applicable
- * @tparam Func A valid function type.
- * @tparam Tuple Tuple-like type.
- * @tparam Args The list of arguments to use to probe the function type.
- */
- template<typename Func, template<typename...> class Tuple, typename... Args>
- struct is_applicable<Func, Tuple<Args...>>: std::is_invocable<Func, Args...> {};
- /**
- * @copybrief is_applicable
- * @tparam Func A valid function type.
- * @tparam Tuple Tuple-like type.
- * @tparam Args The list of arguments to use to probe the function type.
- */
- template<typename Func, template<typename...> class Tuple, typename... Args>
- struct is_applicable<Func, const Tuple<Args...>>: std::is_invocable<Func, Args...> {};
- /**
- * @brief Helper variable template.
- * @tparam Func A valid function type.
- * @tparam Args The list of arguments to use to probe the function type.
- */
- template<typename Func, typename Args>
- inline constexpr bool is_applicable_v = is_applicable<Func, Args>::value;
- /*! @brief Same as std::is_invocable_r, but with tuples for arguments. */
- template<typename, typename, typename>
- struct is_applicable_r: std::false_type {};
- /**
- * @copybrief is_applicable_r
- * @tparam Ret The type to which the return type of the function should be
- * convertible.
- * @tparam Func A valid function type.
- * @tparam Args The list of arguments to use to probe the function type.
- */
- template<typename Ret, typename Func, typename... Args>
- struct is_applicable_r<Ret, Func, std::tuple<Args...>>: std::is_invocable_r<Ret, Func, Args...> {};
- /**
- * @brief Helper variable template.
- * @tparam Ret The type to which the return type of the function should be
- * convertible.
- * @tparam Func A valid function type.
- * @tparam Args The list of arguments to use to probe the function type.
- */
- template<typename Ret, typename Func, typename Args>
- inline constexpr bool is_applicable_r_v = is_applicable_r<Ret, Func, Args>::value;
- /**
- * @brief Provides the member constant `value` to true if a given type is
- * complete, false otherwise.
- * @tparam Type The type to test.
- */
- template<typename Type, typename = void>
- struct is_complete: std::false_type {};
- /*! @copydoc is_complete */
- template<typename Type>
- struct is_complete<Type, std::void_t<decltype(sizeof(Type))>>: std::true_type {};
- /**
- * @brief Helper variable template.
- * @tparam Type The type to test.
- */
- template<typename Type>
- inline constexpr bool is_complete_v = is_complete<Type>::value;
- /**
- * @brief Provides the member constant `value` to true if a given type is an
- * iterator, false otherwise.
- * @tparam Type The type to test.
- */
- template<typename Type, typename = void>
- struct is_iterator: std::false_type {};
- /*! @cond TURN_OFF_DOXYGEN */
- namespace internal {
- template<typename, typename = void>
- struct has_iterator_category: std::false_type {};
- template<typename Type>
- struct has_iterator_category<Type, std::void_t<typename std::iterator_traits<Type>::iterator_category>>: std::true_type {};
- } // namespace internal
- /*! @endcond */
- /*! @copydoc is_iterator */
- template<typename Type>
- struct is_iterator<Type, std::enable_if_t<!std::is_void_v<std::remove_const_t<std::remove_pointer_t<Type>>>>>
- : internal::has_iterator_category<Type> {};
- /**
- * @brief Helper variable template.
- * @tparam Type The type to test.
- */
- template<typename Type>
- inline constexpr bool is_iterator_v = is_iterator<Type>::value;
- /**
- * @brief Provides the member constant `value` to true if a given type is both
- * an empty and non-final class, false otherwise.
- * @tparam Type The type to test
- */
- template<typename Type>
- struct is_ebco_eligible
- : std::bool_constant<std::is_empty_v<Type> && !std::is_final_v<Type>> {};
- /**
- * @brief Helper variable template.
- * @tparam Type The type to test.
- */
- template<typename Type>
- inline constexpr bool is_ebco_eligible_v = is_ebco_eligible<Type>::value;
- /**
- * @brief Provides the member constant `value` to true if `Type::is_transparent`
- * is valid and denotes a type, false otherwise.
- * @tparam Type The type to test.
- */
- template<typename Type, typename = void>
- struct is_transparent: std::false_type {};
- /*! @copydoc is_transparent */
- template<typename Type>
- struct is_transparent<Type, std::void_t<typename Type::is_transparent>>: std::true_type {};
- /**
- * @brief Helper variable template.
- * @tparam Type The type to test.
- */
- template<typename Type>
- inline constexpr bool is_transparent_v = is_transparent<Type>::value;
- /*! @cond TURN_OFF_DOXYGEN */
- namespace internal {
- template<typename, typename = void>
- struct has_tuple_size_value: std::false_type {};
- template<typename Type>
- struct has_tuple_size_value<Type, std::void_t<decltype(std::tuple_size<const Type>::value)>>: std::true_type {};
- template<typename, typename = void>
- struct has_value_type: std::false_type {};
- template<typename Type>
- struct has_value_type<Type, std::void_t<typename Type::value_type>>: std::true_type {};
- template<typename>
- [[nodiscard]] constexpr bool dispatch_is_equality_comparable();
- template<typename Type, std::size_t... Index>
- [[nodiscard]] constexpr bool unpack_maybe_equality_comparable(std::index_sequence<Index...>) {
- return (dispatch_is_equality_comparable<std::tuple_element_t<Index, Type>>() && ...);
- }
- template<typename>
- [[nodiscard]] constexpr bool maybe_equality_comparable(char) {
- return false;
- }
- template<typename Type>
- [[nodiscard]] constexpr auto maybe_equality_comparable(int) -> decltype(std::declval<Type>() == std::declval<Type>()) {
- return true;
- }
- template<typename Type>
- [[nodiscard]] constexpr bool dispatch_is_equality_comparable() {
- // NOLINTBEGIN(modernize-use-transparent-functors)
- if constexpr(std::is_array_v<Type>) {
- return false;
- } else if constexpr(is_complete_v<std::tuple_size<std::remove_const_t<Type>>>) {
- if constexpr(has_tuple_size_value<Type>::value) {
- return maybe_equality_comparable<Type>(0) && unpack_maybe_equality_comparable<Type>(std::make_index_sequence<std::tuple_size<Type>::value>{});
- } else {
- return maybe_equality_comparable<Type>(0);
- }
- } else if constexpr(has_value_type<Type>::value) {
- if constexpr(is_iterator_v<Type> || std::is_same_v<typename Type::value_type, Type> || dispatch_is_equality_comparable<typename Type::value_type>()) {
- return maybe_equality_comparable<Type>(0);
- } else {
- return false;
- }
- } else {
- return maybe_equality_comparable<Type>(0);
- }
- // NOLINTEND(modernize-use-transparent-functors)
- }
- } // namespace internal
- /*! @endcond */
- /**
- * @brief Provides the member constant `value` to true if a given type is
- * equality comparable, false otherwise.
- * @tparam Type The type to test.
- */
- template<typename Type>
- struct is_equality_comparable: std::bool_constant<internal::dispatch_is_equality_comparable<Type>()> {};
- /*! @copydoc is_equality_comparable */
- template<typename Type>
- struct is_equality_comparable<const Type>: is_equality_comparable<Type> {};
- /**
- * @brief Helper variable template.
- * @tparam Type The type to test.
- */
- template<typename Type>
- inline constexpr bool is_equality_comparable_v = is_equality_comparable<Type>::value;
- /**
- * @brief Transcribes the constness of a type to another type.
- * @tparam To The type to which to transcribe the constness.
- * @tparam From The type from which to transcribe the constness.
- */
- template<typename To, typename From>
- struct constness_as {
- /*! @brief The type resulting from the transcription of the constness. */
- using type = std::remove_const_t<To>;
- };
- /*! @copydoc constness_as */
- template<typename To, typename From>
- struct constness_as<To, const From> {
- /*! @brief The type resulting from the transcription of the constness. */
- using type = const To;
- };
- /**
- * @brief Alias template to facilitate the transcription of the constness.
- * @tparam To The type to which to transcribe the constness.
- * @tparam From The type from which to transcribe the constness.
- */
- template<typename To, typename From>
- using constness_as_t = typename constness_as<To, From>::type;
- /**
- * @brief Extracts the class of a non-static member object or function.
- * @tparam Member A pointer to a non-static member object or function.
- */
- template<typename Member>
- class member_class {
- static_assert(std::is_member_pointer_v<Member>, "Invalid pointer type to non-static member object or function");
- template<typename Class, typename Ret, typename... Args>
- static Class *clazz(Ret (Class::*)(Args...));
- template<typename Class, typename Ret, typename... Args>
- static Class *clazz(Ret (Class::*)(Args...) const);
- template<typename Class, typename Type>
- static Class *clazz(Type Class::*);
- public:
- /*! @brief The class of the given non-static member object or function. */
- using type = std::remove_pointer_t<decltype(clazz(std::declval<Member>()))>;
- };
- /**
- * @brief Helper type.
- * @tparam Member A pointer to a non-static member object or function.
- */
- template<typename Member>
- using member_class_t = typename member_class<Member>::type;
- /**
- * @brief Extracts the n-th argument of a _callable_ type.
- * @tparam Index The index of the argument to extract.
- * @tparam Candidate A valid _callable_ type.
- */
- template<std::size_t Index, typename Candidate>
- class nth_argument {
- template<typename Ret, typename... Args>
- static constexpr type_list<Args...> pick_up(Ret (*)(Args...));
- template<typename Ret, typename Class, typename... Args>
- static constexpr type_list<Args...> pick_up(Ret (Class ::*)(Args...));
- template<typename Ret, typename Class, typename... Args>
- static constexpr type_list<Args...> pick_up(Ret (Class ::*)(Args...) const);
- template<typename Type, typename Class>
- static constexpr type_list<Type> pick_up(Type Class ::*);
- template<typename Type>
- static constexpr decltype(pick_up(&Type::operator())) pick_up(Type &&);
- public:
- /*! @brief N-th argument of the _callable_ type. */
- using type = type_list_element_t<Index, decltype(pick_up(std::declval<Candidate>()))>;
- };
- /**
- * @brief Helper type.
- * @tparam Index The index of the argument to extract.
- * @tparam Candidate A valid function, member function or data member type.
- */
- template<std::size_t Index, typename Candidate>
- using nth_argument_t = typename nth_argument<Index, Candidate>::type;
- } // namespace entt
- template<typename... Type>
- struct std::tuple_size<entt::type_list<Type...>>: std::integral_constant<std::size_t, entt::type_list<Type...>::size> {};
- template<std::size_t Index, typename... Type>
- struct std::tuple_element<Index, entt::type_list<Type...>>: entt::type_list_element<Index, entt::type_list<Type...>> {};
- template<auto... Value>
- struct std::tuple_size<entt::value_list<Value...>>: std::integral_constant<std::size_t, entt::value_list<Value...>::size> {};
- template<std::size_t Index, auto... Value>
- struct std::tuple_element<Index, entt::value_list<Value...>>: entt::value_list_element<Index, entt::value_list<Value...>> {};
- #endif
- // #include "fwd.hpp"
- #ifndef ENTT_CONTAINER_FWD_HPP
- #define ENTT_CONTAINER_FWD_HPP
- #include <functional>
- #include <memory>
- #include <utility>
- #include <vector>
- namespace entt {
- template<
- typename Key,
- typename Type,
- typename = std::hash<Key>,
- typename = std::equal_to<>,
- typename = std::allocator<std::pair<const Key, Type>>>
- class dense_map;
- template<
- typename Type,
- typename = std::hash<Type>,
- typename = std::equal_to<>,
- typename = std::allocator<Type>>
- class dense_set;
- template<typename...>
- class basic_table;
- /**
- * @brief Alias declaration for the most common use case.
- * @tparam Type Element types.
- */
- template<typename... Type>
- using table = basic_table<std::vector<Type>...>;
- } // namespace entt
- #endif
- namespace entt {
- /*! @cond TURN_OFF_DOXYGEN */
- namespace internal {
- static constexpr std::size_t dense_map_placeholder_position = (std::numeric_limits<std::size_t>::max)();
- template<typename Key, typename Type>
- struct dense_map_node final {
- using value_type = std::pair<Key, Type>;
- template<typename... Args>
- dense_map_node(const std::size_t pos, Args &&...args)
- : next{pos},
- element{std::forward<Args>(args)...} {}
- template<typename Allocator, typename... Args>
- dense_map_node(std::allocator_arg_t, const Allocator &allocator, const std::size_t pos, Args &&...args)
- : next{pos},
- element{entt::make_obj_using_allocator<value_type>(allocator, std::forward<Args>(args)...)} {}
- template<typename Allocator>
- dense_map_node(std::allocator_arg_t, const Allocator &allocator, const dense_map_node &other)
- : next{other.next},
- element{entt::make_obj_using_allocator<value_type>(allocator, other.element)} {}
- template<typename Allocator>
- dense_map_node(std::allocator_arg_t, const Allocator &allocator, dense_map_node &&other)
- : next{other.next},
- element{entt::make_obj_using_allocator<value_type>(allocator, std::move(other.element))} {}
- std::size_t next;
- value_type element;
- };
- template<typename It>
- class dense_map_iterator final {
- template<typename>
- friend class dense_map_iterator;
- using first_type = decltype(std::as_const(std::declval<It>()->element.first));
- using second_type = decltype((std::declval<It>()->element.second));
- public:
- using value_type = std::pair<first_type, second_type>;
- using pointer = input_iterator_pointer<value_type>;
- using reference = value_type;
- using difference_type = std::ptrdiff_t;
- using iterator_category = std::input_iterator_tag;
- using iterator_concept = std::random_access_iterator_tag;
- constexpr dense_map_iterator() noexcept
- : it{} {}
- constexpr dense_map_iterator(const It iter) noexcept
- : it{iter} {}
- template<typename Other, typename = std::enable_if_t<!std::is_same_v<It, Other> && std::is_constructible_v<It, Other>>>
- constexpr dense_map_iterator(const dense_map_iterator<Other> &other) noexcept
- : it{other.it} {}
- constexpr dense_map_iterator &operator++() noexcept {
- return ++it, *this;
- }
- constexpr dense_map_iterator operator++(int) noexcept {
- const dense_map_iterator orig = *this;
- return ++(*this), orig;
- }
- constexpr dense_map_iterator &operator--() noexcept {
- return --it, *this;
- }
- constexpr dense_map_iterator operator--(int) noexcept {
- const dense_map_iterator orig = *this;
- return operator--(), orig;
- }
- constexpr dense_map_iterator &operator+=(const difference_type value) noexcept {
- it += value;
- return *this;
- }
- constexpr dense_map_iterator operator+(const difference_type value) const noexcept {
- dense_map_iterator copy = *this;
- return (copy += value);
- }
- constexpr dense_map_iterator &operator-=(const difference_type value) noexcept {
- return (*this += -value);
- }
- constexpr dense_map_iterator operator-(const difference_type value) const noexcept {
- return (*this + -value);
- }
- [[nodiscard]] constexpr reference operator[](const difference_type value) const noexcept {
- return {it[value].element.first, it[value].element.second};
- }
- [[nodiscard]] constexpr pointer operator->() const noexcept {
- return operator*();
- }
- [[nodiscard]] constexpr reference operator*() const noexcept {
- return operator[](0);
- }
- template<typename Lhs, typename Rhs>
- friend constexpr std::ptrdiff_t operator-(const dense_map_iterator<Lhs> &, const dense_map_iterator<Rhs> &) noexcept;
- template<typename Lhs, typename Rhs>
- friend constexpr bool operator==(const dense_map_iterator<Lhs> &, const dense_map_iterator<Rhs> &) noexcept;
- template<typename Lhs, typename Rhs>
- friend constexpr bool operator<(const dense_map_iterator<Lhs> &, const dense_map_iterator<Rhs> &) noexcept;
- private:
- It it;
- };
- template<typename Lhs, typename Rhs>
- [[nodiscard]] constexpr std::ptrdiff_t operator-(const dense_map_iterator<Lhs> &lhs, const dense_map_iterator<Rhs> &rhs) noexcept {
- return lhs.it - rhs.it;
- }
- template<typename Lhs, typename Rhs>
- [[nodiscard]] constexpr bool operator==(const dense_map_iterator<Lhs> &lhs, const dense_map_iterator<Rhs> &rhs) noexcept {
- return lhs.it == rhs.it;
- }
- template<typename Lhs, typename Rhs>
- [[nodiscard]] constexpr bool operator!=(const dense_map_iterator<Lhs> &lhs, const dense_map_iterator<Rhs> &rhs) noexcept {
- return !(lhs == rhs);
- }
- template<typename Lhs, typename Rhs>
- [[nodiscard]] constexpr bool operator<(const dense_map_iterator<Lhs> &lhs, const dense_map_iterator<Rhs> &rhs) noexcept {
- return lhs.it < rhs.it;
- }
- template<typename Lhs, typename Rhs>
- [[nodiscard]] constexpr bool operator>(const dense_map_iterator<Lhs> &lhs, const dense_map_iterator<Rhs> &rhs) noexcept {
- return rhs < lhs;
- }
- template<typename Lhs, typename Rhs>
- [[nodiscard]] constexpr bool operator<=(const dense_map_iterator<Lhs> &lhs, const dense_map_iterator<Rhs> &rhs) noexcept {
- return !(lhs > rhs);
- }
- template<typename Lhs, typename Rhs>
- [[nodiscard]] constexpr bool operator>=(const dense_map_iterator<Lhs> &lhs, const dense_map_iterator<Rhs> &rhs) noexcept {
- return !(lhs < rhs);
- }
- template<typename It>
- class dense_map_local_iterator final {
- template<typename>
- friend class dense_map_local_iterator;
- using first_type = decltype(std::as_const(std::declval<It>()->element.first));
- using second_type = decltype((std::declval<It>()->element.second));
- public:
- using value_type = std::pair<first_type, second_type>;
- using pointer = input_iterator_pointer<value_type>;
- using reference = value_type;
- using difference_type = std::ptrdiff_t;
- using iterator_category = std::input_iterator_tag;
- using iterator_concept = std::forward_iterator_tag;
- constexpr dense_map_local_iterator() noexcept = default;
- constexpr dense_map_local_iterator(It iter, const std::size_t pos) noexcept
- : it{iter},
- offset{pos} {}
- template<typename Other, typename = std::enable_if_t<!std::is_same_v<It, Other> && std::is_constructible_v<It, Other>>>
- constexpr dense_map_local_iterator(const dense_map_local_iterator<Other> &other) noexcept
- : it{other.it},
- offset{other.offset} {}
- constexpr dense_map_local_iterator &operator++() noexcept {
- return (offset = it[static_cast<typename It::difference_type>(offset)].next), *this;
- }
- constexpr dense_map_local_iterator operator++(int) noexcept {
- const dense_map_local_iterator orig = *this;
- return ++(*this), orig;
- }
- [[nodiscard]] constexpr pointer operator->() const noexcept {
- return operator*();
- }
- [[nodiscard]] constexpr reference operator*() const noexcept {
- const auto idx = static_cast<typename It::difference_type>(offset);
- return {it[idx].element.first, it[idx].element.second};
- }
- [[nodiscard]] constexpr std::size_t index() const noexcept {
- return offset;
- }
- private:
- It it{};
- std::size_t offset{dense_map_placeholder_position};
- };
- template<typename Lhs, typename Rhs>
- [[nodiscard]] constexpr bool operator==(const dense_map_local_iterator<Lhs> &lhs, const dense_map_local_iterator<Rhs> &rhs) noexcept {
- return lhs.index() == rhs.index();
- }
- template<typename Lhs, typename Rhs>
- [[nodiscard]] constexpr bool operator!=(const dense_map_local_iterator<Lhs> &lhs, const dense_map_local_iterator<Rhs> &rhs) noexcept {
- return !(lhs == rhs);
- }
- } // namespace internal
- /*! @endcond */
- /**
- * @brief Associative container for key-value pairs with unique keys.
- *
- * Internally, elements are organized into buckets. Which bucket an element is
- * placed into depends entirely on the hash of its key. Keys with the same hash
- * code appear in the same bucket.
- *
- * @tparam Key Key type of the associative container.
- * @tparam Type Mapped type of the associative container.
- * @tparam Hash Type of function to use to hash the keys.
- * @tparam KeyEqual Type of function to use to compare the keys for equality.
- * @tparam Allocator Type of allocator used to manage memory and elements.
- */
- template<typename Key, typename Type, typename Hash, typename KeyEqual, typename Allocator>
- class dense_map {
- static constexpr float default_threshold = 0.875f;
- static constexpr std::size_t minimum_capacity = 8u;
- static constexpr std::size_t placeholder_position = internal::dense_map_placeholder_position;
- using node_type = internal::dense_map_node<Key, Type>;
- using alloc_traits = std::allocator_traits<Allocator>;
- static_assert(std::is_same_v<typename alloc_traits::value_type, std::pair<const Key, Type>>, "Invalid value type");
- using sparse_container_type = std::vector<std::size_t, typename alloc_traits::template rebind_alloc<std::size_t>>;
- using packed_container_type = std::vector<node_type, typename alloc_traits::template rebind_alloc<node_type>>;
- template<typename Other>
- [[nodiscard]] std::size_t key_to_bucket(const Other &key) const noexcept {
- // NOLINTNEXTLINE(cppcoreguidelines-pro-bounds-array-to-pointer-decay)
- return fast_mod(static_cast<size_type>(sparse.second()(key)), bucket_count());
- }
- template<typename Other>
- [[nodiscard]] auto constrained_find(const Other &key, const std::size_t bucket) {
- for(auto offset = sparse.first()[bucket]; offset != placeholder_position; offset = packed.first()[offset].next) {
- if(packed.second()(packed.first()[offset].element.first, key)) {
- return begin() + static_cast<typename iterator::difference_type>(offset);
- }
- }
- return end();
- }
- template<typename Other>
- [[nodiscard]] auto constrained_find(const Other &key, const std::size_t bucket) const {
- for(auto offset = sparse.first()[bucket]; offset != placeholder_position; offset = packed.first()[offset].next) {
- if(packed.second()(packed.first()[offset].element.first, key)) {
- return cbegin() + static_cast<typename const_iterator::difference_type>(offset);
- }
- }
- return cend();
- }
- template<typename Other, typename... Args>
- [[nodiscard]] auto insert_or_do_nothing(Other &&key, Args &&...args) {
- const auto index = key_to_bucket(key);
- if(auto it = constrained_find(key, index); it != end()) {
- return std::make_pair(it, false);
- }
- packed.first().emplace_back(sparse.first()[index], std::piecewise_construct, std::forward_as_tuple(std::forward<Other>(key)), std::forward_as_tuple(std::forward<Args>(args)...));
- sparse.first()[index] = packed.first().size() - 1u;
- rehash_if_required();
- return std::make_pair(--end(), true);
- }
- template<typename Other, typename Arg>
- [[nodiscard]] auto insert_or_overwrite(Other &&key, Arg &&value) {
- const auto index = key_to_bucket(key);
- if(auto it = constrained_find(key, index); it != end()) {
- it->second = std::forward<Arg>(value);
- return std::make_pair(it, false);
- }
- packed.first().emplace_back(sparse.first()[index], std::forward<Other>(key), std::forward<Arg>(value));
- sparse.first()[index] = packed.first().size() - 1u;
- rehash_if_required();
- return std::make_pair(--end(), true);
- }
- void move_and_pop(const std::size_t pos) {
- if(const auto last = size() - 1u; pos != last) {
- size_type *curr = &sparse.first()[key_to_bucket(packed.first().back().element.first)];
- packed.first()[pos] = std::move(packed.first().back());
- for(; *curr != last; curr = &packed.first()[*curr].next) {}
- *curr = pos;
- }
- packed.first().pop_back();
- }
- void rehash_if_required() {
- if(const auto bc = bucket_count(); size() > static_cast<size_type>(static_cast<float>(bc) * max_load_factor())) {
- rehash(bc * 2u);
- }
- }
- public:
- /*! @brief Allocator type. */
- using allocator_type = Allocator;
- /*! @brief Key type of the container. */
- using key_type = Key;
- /*! @brief Mapped type of the container. */
- using mapped_type = Type;
- /*! @brief Key-value type of the container. */
- using value_type = std::pair<const Key, Type>;
- /*! @brief Unsigned integer type. */
- using size_type = std::size_t;
- /*! @brief Signed integer type. */
- using difference_type = std::ptrdiff_t;
- /*! @brief Type of function to use to hash the keys. */
- using hasher = Hash;
- /*! @brief Type of function to use to compare the keys for equality. */
- using key_equal = KeyEqual;
- /*! @brief Input iterator type. */
- using iterator = internal::dense_map_iterator<typename packed_container_type::iterator>;
- /*! @brief Constant input iterator type. */
- using const_iterator = internal::dense_map_iterator<typename packed_container_type::const_iterator>;
- /*! @brief Input iterator type. */
- using local_iterator = internal::dense_map_local_iterator<typename packed_container_type::iterator>;
- /*! @brief Constant input iterator type. */
- using const_local_iterator = internal::dense_map_local_iterator<typename packed_container_type::const_iterator>;
- /*! @brief Default constructor. */
- dense_map()
- : dense_map{minimum_capacity} {}
- /**
- * @brief Constructs an empty container with a given allocator.
- * @param allocator The allocator to use.
- */
- explicit dense_map(const allocator_type &allocator)
- : dense_map{minimum_capacity, hasher{}, key_equal{}, allocator} {}
- /**
- * @brief Constructs an empty container with a given allocator and user
- * supplied minimal number of buckets.
- * @param cnt Minimal number of buckets.
- * @param allocator The allocator to use.
- */
- dense_map(const size_type cnt, const allocator_type &allocator)
- : dense_map{cnt, hasher{}, key_equal{}, allocator} {}
- /**
- * @brief Constructs an empty container with a given allocator, hash
- * function and user supplied minimal number of buckets.
- * @param cnt Minimal number of buckets.
- * @param hash Hash function to use.
- * @param allocator The allocator to use.
- */
- dense_map(const size_type cnt, const hasher &hash, const allocator_type &allocator)
- : dense_map{cnt, hash, key_equal{}, allocator} {}
- /**
- * @brief Constructs an empty container with a given allocator, hash
- * function, compare function and user supplied minimal number of buckets.
- * @param cnt Minimal number of buckets.
- * @param hash Hash function to use.
- * @param equal Compare function to use.
- * @param allocator The allocator to use.
- */
- explicit dense_map(const size_type cnt, const hasher &hash = hasher{}, const key_equal &equal = key_equal{}, const allocator_type &allocator = allocator_type{})
- : sparse{allocator, hash},
- packed{allocator, equal} {
- rehash(cnt);
- }
- /*! @brief Default copy constructor. */
- dense_map(const dense_map &) = default;
- /**
- * @brief Allocator-extended copy constructor.
- * @param other The instance to copy from.
- * @param allocator The allocator to use.
- */
- dense_map(const dense_map &other, const allocator_type &allocator)
- : sparse{std::piecewise_construct, std::forward_as_tuple(other.sparse.first(), allocator), std::forward_as_tuple(other.sparse.second())},
- packed{std::piecewise_construct, std::forward_as_tuple(other.packed.first(), allocator), std::forward_as_tuple(other.packed.second())},
- threshold{other.threshold} {}
- /*! @brief Default move constructor. */
- dense_map(dense_map &&) noexcept = default;
- /**
- * @brief Allocator-extended move constructor.
- * @param other The instance to move from.
- * @param allocator The allocator to use.
- */
- dense_map(dense_map &&other, const allocator_type &allocator)
- : sparse{std::piecewise_construct, std::forward_as_tuple(std::move(other.sparse.first()), allocator), std::forward_as_tuple(std::move(other.sparse.second()))},
- packed{std::piecewise_construct, std::forward_as_tuple(std::move(other.packed.first()), allocator), std::forward_as_tuple(std::move(other.packed.second()))},
- threshold{other.threshold} {}
- /*! @brief Default destructor. */
- ~dense_map() = default;
- /**
- * @brief Default copy assignment operator.
- * @return This container.
- */
- dense_map &operator=(const dense_map &) = default;
- /**
- * @brief Default move assignment operator.
- * @return This container.
- */
- dense_map &operator=(dense_map &&) noexcept = default;
- /**
- * @brief Exchanges the contents with those of a given container.
- * @param other Container to exchange the content with.
- */
- void swap(dense_map &other) noexcept {
- using std::swap;
- swap(sparse, other.sparse);
- swap(packed, other.packed);
- swap(threshold, other.threshold);
- }
- /**
- * @brief Returns the associated allocator.
- * @return The associated allocator.
- */
- [[nodiscard]] constexpr allocator_type get_allocator() const noexcept {
- return sparse.first().get_allocator();
- }
- /**
- * @brief Returns an iterator to the beginning.
- *
- * If the array is empty, the returned iterator will be equal to `end()`.
- *
- * @return An iterator to the first instance of the internal array.
- */
- [[nodiscard]] const_iterator cbegin() const noexcept {
- return packed.first().begin();
- }
- /*! @copydoc cbegin */
- [[nodiscard]] const_iterator begin() const noexcept {
- return cbegin();
- }
- /*! @copydoc begin */
- [[nodiscard]] iterator begin() noexcept {
- return packed.first().begin();
- }
- /**
- * @brief Returns an iterator to the end.
- * @return An iterator to the element following the last instance of the
- * internal array.
- */
- [[nodiscard]] const_iterator cend() const noexcept {
- return packed.first().end();
- }
- /*! @copydoc cend */
- [[nodiscard]] const_iterator end() const noexcept {
- return cend();
- }
- /*! @copydoc end */
- [[nodiscard]] iterator end() noexcept {
- return packed.first().end();
- }
- /**
- * @brief Checks whether a container is empty.
- * @return True if the container is empty, false otherwise.
- */
- [[nodiscard]] bool empty() const noexcept {
- return packed.first().empty();
- }
- /**
- * @brief Returns the number of elements in a container.
- * @return Number of elements in a container.
- */
- [[nodiscard]] size_type size() const noexcept {
- return packed.first().size();
- }
- /**
- * @brief Returns the maximum possible number of elements.
- * @return Maximum possible number of elements.
- */
- [[nodiscard]] size_type max_size() const noexcept {
- return packed.first().max_size();
- }
- /*! @brief Clears the container. */
- void clear() noexcept {
- sparse.first().clear();
- packed.first().clear();
- rehash(0u);
- }
- /**
- * @brief Inserts an element into the container, if the key does not exist.
- * @param value A key-value pair eventually convertible to the value type.
- * @return A pair consisting of an iterator to the inserted element (or to
- * the element that prevented the insertion) and a bool denoting whether the
- * insertion took place.
- */
- std::pair<iterator, bool> insert(const value_type &value) {
- return insert_or_do_nothing(value.first, value.second);
- }
- /*! @copydoc insert */
- std::pair<iterator, bool> insert(value_type &&value) {
- return insert_or_do_nothing(std::move(value.first), std::move(value.second));
- }
- /**
- * @copydoc insert
- * @tparam Arg Type of the key-value pair to insert into the container.
- */
- template<typename Arg>
- std::enable_if_t<std::is_constructible_v<value_type, Arg &&>, std::pair<iterator, bool>>
- insert(Arg &&value) {
- return insert_or_do_nothing(std::forward<Arg>(value).first, std::forward<Arg>(value).second);
- }
- /**
- * @brief Inserts elements into the container, if their keys do not exist.
- * @tparam It Type of input iterator.
- * @param first An iterator to the first element of the range of elements.
- * @param last An iterator past the last element of the range of elements.
- */
- template<typename It>
- void insert(It first, It last) {
- for(; first != last; ++first) {
- insert(*first);
- }
- }
- /**
- * @brief Inserts an element into the container or assigns to the current
- * element if the key already exists.
- * @tparam Arg Type of the value to insert or assign.
- * @param key A key used both to look up and to insert if not found.
- * @param value A value to insert or assign.
- * @return A pair consisting of an iterator to the element and a bool
- * denoting whether the insertion took place.
- */
- template<typename Arg>
- std::pair<iterator, bool> insert_or_assign(const key_type &key, Arg &&value) {
- return insert_or_overwrite(key, std::forward<Arg>(value));
- }
- /*! @copydoc insert_or_assign */
- template<typename Arg>
- std::pair<iterator, bool> insert_or_assign(key_type &&key, Arg &&value) {
- return insert_or_overwrite(std::move(key), std::forward<Arg>(value));
- }
- /**
- * @brief Constructs an element in-place, if the key does not exist.
- *
- * The element is also constructed when the container already has the key,
- * in which case the newly constructed object is destroyed immediately.
- *
- * @tparam Args Types of arguments to forward to the constructor of the
- * element.
- * @param args Arguments to forward to the constructor of the element.
- * @return A pair consisting of an iterator to the inserted element (or to
- * the element that prevented the insertion) and a bool denoting whether the
- * insertion took place.
- */
- template<typename... Args>
- std::pair<iterator, bool> emplace([[maybe_unused]] Args &&...args) {
- if constexpr(sizeof...(Args) == 0u) {
- return insert_or_do_nothing(key_type{});
- } else if constexpr(sizeof...(Args) == 1u) {
- return insert_or_do_nothing(std::forward<Args>(args).first..., std::forward<Args>(args).second...);
- } else if constexpr(sizeof...(Args) == 2u) {
- return insert_or_do_nothing(std::forward<Args>(args)...);
- } else {
- auto &node = packed.first().emplace_back(packed.first().size(), std::forward<Args>(args)...);
- const auto index = key_to_bucket(node.element.first);
- if(auto it = constrained_find(node.element.first, index); it != end()) {
- packed.first().pop_back();
- return std::make_pair(it, false);
- }
- std::swap(node.next, sparse.first()[index]);
- rehash_if_required();
- return std::make_pair(--end(), true);
- }
- }
- /**
- * @brief Inserts in-place if the key does not exist, does nothing if the
- * key exists.
- * @tparam Args Types of arguments to forward to the constructor of the
- * element.
- * @param key A key used both to look up and to insert if not found.
- * @param args Arguments to forward to the constructor of the element.
- * @return A pair consisting of an iterator to the inserted element (or to
- * the element that prevented the insertion) and a bool denoting whether the
- * insertion took place.
- */
- template<typename... Args>
- std::pair<iterator, bool> try_emplace(const key_type &key, Args &&...args) {
- return insert_or_do_nothing(key, std::forward<Args>(args)...);
- }
- /*! @copydoc try_emplace */
- template<typename... Args>
- std::pair<iterator, bool> try_emplace(key_type &&key, Args &&...args) {
- return insert_or_do_nothing(std::move(key), std::forward<Args>(args)...);
- }
- /**
- * @brief Removes an element from a given position.
- * @param pos An iterator to the element to remove.
- * @return An iterator following the removed element.
- */
- iterator erase(const_iterator pos) {
- const auto diff = pos - cbegin();
- erase(pos->first);
- return begin() + diff;
- }
- /**
- * @brief Removes the given elements from a container.
- * @param first An iterator to the first element of the range of elements.
- * @param last An iterator past the last element of the range of elements.
- * @return An iterator following the last removed element.
- */
- iterator erase(const_iterator first, const_iterator last) {
- const auto dist = first - cbegin();
- for(auto from = last - cbegin(); from != dist; --from) {
- erase(packed.first()[static_cast<size_type>(from) - 1u].element.first);
- }
- return (begin() + dist);
- }
- /**
- * @brief Removes the element associated with a given key.
- * @param key A key value of an element to remove.
- * @return Number of elements removed (either 0 or 1).
- */
- size_type erase(const key_type &key) {
- for(size_type *curr = &sparse.first()[key_to_bucket(key)]; *curr != placeholder_position; curr = &packed.first()[*curr].next) {
- if(packed.second()(packed.first()[*curr].element.first, key)) {
- const auto index = *curr;
- *curr = packed.first()[*curr].next;
- move_and_pop(index);
- return 1u;
- }
- }
- return 0u;
- }
- /**
- * @brief Accesses a given element with bounds checking.
- * @param key A key of an element to find.
- * @return A reference to the mapped value of the requested element.
- */
- [[nodiscard]] mapped_type &at(const key_type &key) {
- auto it = find(key);
- ENTT_ASSERT(it != end(), "Invalid key");
- return it->second;
- }
- /*! @copydoc at */
- [[nodiscard]] const mapped_type &at(const key_type &key) const {
- auto it = find(key);
- ENTT_ASSERT(it != cend(), "Invalid key");
- return it->second;
- }
- /**
- * @brief Accesses a given element with bounds checking.
- * @tparam Other Type of the key of an element to find.
- * @param key A key of an element to find.
- * @return A reference to the mapped value of the requested element.
- */
- template<typename Other>
- [[nodiscard]] std::enable_if_t<is_transparent_v<hasher> && is_transparent_v<key_equal>, std::conditional_t<false, Other, mapped_type const &>>
- at(const Other &key) const {
- auto it = find(key);
- ENTT_ASSERT(it != cend(), "Invalid key");
- return it->second;
- }
- /*! @copydoc at */
- template<typename Other>
- [[nodiscard]] std::enable_if_t<is_transparent_v<hasher> && is_transparent_v<key_equal>, std::conditional_t<false, Other, mapped_type &>>
- at(const Other &key) {
- auto it = find(key);
- ENTT_ASSERT(it != end(), "Invalid key");
- return it->second;
- }
- /**
- * @brief Accesses or inserts a given element.
- * @param key A key of an element to find or insert.
- * @return A reference to the mapped value of the requested element.
- */
- [[nodiscard]] mapped_type &operator[](const key_type &key) {
- return insert_or_do_nothing(key).first->second;
- }
- /**
- * @brief Accesses or inserts a given element.
- * @param key A key of an element to find or insert.
- * @return A reference to the mapped value of the requested element.
- */
- [[nodiscard]] mapped_type &operator[](key_type &&key) {
- return insert_or_do_nothing(std::move(key)).first->second;
- }
- /**
- * @brief Returns the number of elements matching a key (either 1 or 0).
- * @param key Key value of an element to search for.
- * @return Number of elements matching the key (either 1 or 0).
- */
- [[nodiscard]] size_type count(const key_type &key) const {
- return find(key) != end();
- }
- /**
- * @brief Returns the number of elements matching a key (either 1 or 0).
- * @tparam Other Type of the key value of an element to search for.
- * @param key Key value of an element to search for.
- * @return Number of elements matching the key (either 1 or 0).
- */
- template<typename Other>
- [[nodiscard]] std::enable_if_t<is_transparent_v<hasher> && is_transparent_v<key_equal>, std::conditional_t<false, Other, size_type>>
- count(const Other &key) const {
- return find(key) != end();
- }
- /**
- * @brief Finds an element with a given key.
- * @param key Key value of an element to search for.
- * @return An iterator to an element with the given key. If no such element
- * is found, a past-the-end iterator is returned.
- */
- [[nodiscard]] iterator find(const key_type &key) {
- return constrained_find(key, key_to_bucket(key));
- }
- /*! @copydoc find */
- [[nodiscard]] const_iterator find(const key_type &key) const {
- return constrained_find(key, key_to_bucket(key));
- }
- /**
- * @brief Finds an element with a key that compares _equivalent_ to a given
- * key.
- * @tparam Other Type of the key value of an element to search for.
- * @param key Key value of an element to search for.
- * @return An iterator to an element with the given key. If no such element
- * is found, a past-the-end iterator is returned.
- */
- template<typename Other>
- [[nodiscard]] std::enable_if_t<is_transparent_v<hasher> && is_transparent_v<key_equal>, std::conditional_t<false, Other, iterator>>
- find(const Other &key) {
- return constrained_find(key, key_to_bucket(key));
- }
- /*! @copydoc find */
- template<typename Other>
- [[nodiscard]] std::enable_if_t<is_transparent_v<hasher> && is_transparent_v<key_equal>, std::conditional_t<false, Other, const_iterator>>
- find(const Other &key) const {
- return constrained_find(key, key_to_bucket(key));
- }
- /**
- * @brief Returns a range containing all elements with a given key.
- * @param key Key value of an element to search for.
- * @return A pair of iterators pointing to the first element and past the
- * last element of the range.
- */
- [[nodiscard]] std::pair<iterator, iterator> equal_range(const key_type &key) {
- const auto it = find(key);
- return {it, it + !(it == end())};
- }
- /*! @copydoc equal_range */
- [[nodiscard]] std::pair<const_iterator, const_iterator> equal_range(const key_type &key) const {
- const auto it = find(key);
- return {it, it + !(it == cend())};
- }
- /**
- * @brief Returns a range containing all elements that compare _equivalent_
- * to a given key.
- * @tparam Other Type of an element to search for.
- * @param key Key value of an element to search for.
- * @return A pair of iterators pointing to the first element and past the
- * last element of the range.
- */
- template<typename Other>
- [[nodiscard]] std::enable_if_t<is_transparent_v<hasher> && is_transparent_v<key_equal>, std::conditional_t<false, Other, std::pair<iterator, iterator>>>
- equal_range(const Other &key) {
- const auto it = find(key);
- return {it, it + !(it == end())};
- }
- /*! @copydoc equal_range */
- template<typename Other>
- [[nodiscard]] std::enable_if_t<is_transparent_v<hasher> && is_transparent_v<key_equal>, std::conditional_t<false, Other, std::pair<const_iterator, const_iterator>>>
- equal_range(const Other &key) const {
- const auto it = find(key);
- return {it, it + !(it == cend())};
- }
- /**
- * @brief Checks if the container contains an element with a given key.
- * @param key Key value of an element to search for.
- * @return True if there is such an element, false otherwise.
- */
- [[nodiscard]] bool contains(const key_type &key) const {
- return (find(key) != cend());
- }
- /**
- * @brief Checks if the container contains an element with a key that
- * compares _equivalent_ to a given value.
- * @tparam Other Type of the key value of an element to search for.
- * @param key Key value of an element to search for.
- * @return True if there is such an element, false otherwise.
- */
- template<typename Other>
- [[nodiscard]] std::enable_if_t<is_transparent_v<hasher> && is_transparent_v<key_equal>, std::conditional_t<false, Other, bool>>
- contains(const Other &key) const {
- return (find(key) != cend());
- }
- /**
- * @brief Returns an iterator to the beginning of a given bucket.
- * @param index An index of a bucket to access.
- * @return An iterator to the beginning of the given bucket.
- */
- [[nodiscard]] const_local_iterator cbegin(const size_type index) const {
- return {packed.first().begin(), sparse.first()[index]};
- }
- /**
- * @brief Returns an iterator to the beginning of a given bucket.
- * @param index An index of a bucket to access.
- * @return An iterator to the beginning of the given bucket.
- */
- [[nodiscard]] const_local_iterator begin(const size_type index) const {
- return cbegin(index);
- }
- /**
- * @brief Returns an iterator to the beginning of a given bucket.
- * @param index An index of a bucket to access.
- * @return An iterator to the beginning of the given bucket.
- */
- [[nodiscard]] local_iterator begin(const size_type index) {
- return {packed.first().begin(), sparse.first()[index]};
- }
- /**
- * @brief Returns an iterator to the end of a given bucket.
- * @param index An index of a bucket to access.
- * @return An iterator to the end of the given bucket.
- */
- [[nodiscard]] const_local_iterator cend([[maybe_unused]] const size_type index) const {
- return {};
- }
- /**
- * @brief Returns an iterator to the end of a given bucket.
- * @param index An index of a bucket to access.
- * @return An iterator to the end of the given bucket.
- */
- [[nodiscard]] const_local_iterator end(const size_type index) const {
- return cend(index);
- }
- /**
- * @brief Returns an iterator to the end of a given bucket.
- * @param index An index of a bucket to access.
- * @return An iterator to the end of the given bucket.
- */
- [[nodiscard]] local_iterator end([[maybe_unused]] const size_type index) {
- return {};
- }
- /**
- * @brief Returns the number of buckets.
- * @return The number of buckets.
- */
- [[nodiscard]] size_type bucket_count() const {
- return sparse.first().size();
- }
- /**
- * @brief Returns the maximum number of buckets.
- * @return The maximum number of buckets.
- */
- [[nodiscard]] size_type max_bucket_count() const {
- return sparse.first().max_size();
- }
- /**
- * @brief Returns the number of elements in a given bucket.
- * @param index The index of the bucket to examine.
- * @return The number of elements in the given bucket.
- */
- [[nodiscard]] size_type bucket_size(const size_type index) const {
- return static_cast<size_type>(std::distance(begin(index), end(index)));
- }
- /**
- * @brief Returns the bucket for a given key.
- * @param key The value of the key to examine.
- * @return The bucket for the given key.
- */
- [[nodiscard]] size_type bucket(const key_type &key) const {
- return key_to_bucket(key);
- }
- /**
- * @brief Returns the average number of elements per bucket.
- * @return The average number of elements per bucket.
- */
- [[nodiscard]] float load_factor() const {
- return static_cast<float>(size()) / static_cast<float>(bucket_count());
- }
- /**
- * @brief Returns the maximum average number of elements per bucket.
- * @return The maximum average number of elements per bucket.
- */
- [[nodiscard]] float max_load_factor() const {
- return threshold;
- }
- /**
- * @brief Sets the desired maximum average number of elements per bucket.
- * @param value A desired maximum average number of elements per bucket.
- */
- void max_load_factor(const float value) {
- ENTT_ASSERT(value > 0.f, "Invalid load factor");
- threshold = value;
- rehash(0u);
- }
- /**
- * @brief Reserves at least the specified number of buckets and regenerates
- * the hash table.
- * @param cnt New number of buckets.
- */
- void rehash(const size_type cnt) {
- auto value = cnt > minimum_capacity ? cnt : minimum_capacity;
- const auto cap = static_cast<size_type>(static_cast<float>(size()) / max_load_factor());
- value = value > cap ? value : cap;
- if(const auto sz = next_power_of_two(value); sz != bucket_count()) {
- sparse.first().resize(sz);
- for(auto &&elem: sparse.first()) {
- elem = placeholder_position;
- }
- for(size_type pos{}, last = size(); pos < last; ++pos) {
- const auto index = key_to_bucket(packed.first()[pos].element.first);
- packed.first()[pos].next = std::exchange(sparse.first()[index], pos);
- }
- }
- }
- /**
- * @brief Reserves space for at least the specified number of elements and
- * regenerates the hash table.
- * @param cnt New number of elements.
- */
- void reserve(const size_type cnt) {
- packed.first().reserve(cnt);
- rehash(static_cast<size_type>(std::ceil(static_cast<float>(cnt) / max_load_factor())));
- }
- /**
- * @brief Returns the function used to hash the keys.
- * @return The function used to hash the keys.
- */
- [[nodiscard]] hasher hash_function() const {
- return sparse.second();
- }
- /**
- * @brief Returns the function used to compare keys for equality.
- * @return The function used to compare keys for equality.
- */
- [[nodiscard]] key_equal key_eq() const {
- return packed.second();
- }
- private:
- compressed_pair<sparse_container_type, hasher> sparse;
- compressed_pair<packed_container_type, key_equal> packed;
- float threshold{default_threshold};
- };
- } // namespace entt
- /*! @cond TURN_OFF_DOXYGEN */
- namespace std {
- template<typename Key, typename Value, typename Allocator>
- struct uses_allocator<entt::internal::dense_map_node<Key, Value>, Allocator>
- : std::true_type {};
- } // namespace std
- /*! @endcond */
- #endif
- // #include "../core/compressed_pair.hpp"
- #ifndef ENTT_CORE_COMPRESSED_PAIR_HPP
- #define ENTT_CORE_COMPRESSED_PAIR_HPP
- #include <cstddef>
- #include <tuple>
- #include <type_traits>
- #include <utility>
- // #include "fwd.hpp"
- #ifndef ENTT_CORE_FWD_HPP
- #define ENTT_CORE_FWD_HPP
- #include <cstddef>
- #include <cstdint>
- // #include "../config/config.h"
- #ifndef ENTT_CONFIG_CONFIG_H
- #define ENTT_CONFIG_CONFIG_H
- // #include "version.h"
- #ifndef ENTT_CONFIG_VERSION_H
- #define ENTT_CONFIG_VERSION_H
- // #include "macro.h"
- #ifndef ENTT_CONFIG_MACRO_H
- #define ENTT_CONFIG_MACRO_H
- // NOLINTBEGIN(cppcoreguidelines-macro-usage)
- #define ENTT_STR(arg) #arg
- #define ENTT_XSTR(arg) ENTT_STR(arg)
- // NOLINTEND(cppcoreguidelines-macro-usage)
- #endif
- // NOLINTBEGIN(cppcoreguidelines-macro-*,modernize-macro-*)
- #define ENTT_VERSION_MAJOR 3
- #define ENTT_VERSION_MINOR 16
- #define ENTT_VERSION_PATCH 0
- #define ENTT_VERSION \
- ENTT_XSTR(ENTT_VERSION_MAJOR) \
- "." ENTT_XSTR(ENTT_VERSION_MINOR) "." ENTT_XSTR(ENTT_VERSION_PATCH)
- // NOLINTEND(cppcoreguidelines-macro-*,modernize-macro-*)
- #endif
- // NOLINTBEGIN(cppcoreguidelines-macro-usage)
- #if defined(__cpp_exceptions) && !defined(ENTT_NOEXCEPTION)
- # define ENTT_CONSTEXPR
- # define ENTT_THROW throw
- # define ENTT_TRY try
- # define ENTT_CATCH catch(...)
- #else
- # define ENTT_CONSTEXPR constexpr // use only with throwing functions (waiting for C++20)
- # define ENTT_THROW
- # define ENTT_TRY if(true)
- # define ENTT_CATCH if(false)
- #endif
- #if __has_include(<version>)
- # include <version>
- #
- # if defined(__cpp_consteval)
- # define ENTT_CONSTEVAL consteval
- # endif
- #endif
- #ifndef ENTT_CONSTEVAL
- # define ENTT_CONSTEVAL constexpr
- #endif
- #ifdef ENTT_USE_ATOMIC
- # include <atomic>
- # define ENTT_MAYBE_ATOMIC(Type) std::atomic<Type>
- #else
- # define ENTT_MAYBE_ATOMIC(Type) Type
- #endif
- #ifndef ENTT_ID_TYPE
- # include <cstdint>
- # define ENTT_ID_TYPE std::uint32_t
- #else
- # include <cstdint> // provides coverage for types in the std namespace
- #endif
- #ifndef ENTT_SPARSE_PAGE
- # define ENTT_SPARSE_PAGE 4096
- #endif
- #ifndef ENTT_PACKED_PAGE
- # define ENTT_PACKED_PAGE 1024
- #endif
- #ifdef ENTT_DISABLE_ASSERT
- # undef ENTT_ASSERT
- # define ENTT_ASSERT(condition, msg) (void(0))
- #elif !defined ENTT_ASSERT
- # include <cassert>
- # define ENTT_ASSERT(condition, msg) assert(((condition) && (msg)))
- #endif
- #ifdef ENTT_DISABLE_ASSERT
- # undef ENTT_ASSERT_CONSTEXPR
- # define ENTT_ASSERT_CONSTEXPR(condition, msg) (void(0))
- #elif !defined ENTT_ASSERT_CONSTEXPR
- # define ENTT_ASSERT_CONSTEXPR(condition, msg) ENTT_ASSERT(condition, msg)
- #endif
- #define ENTT_FAIL(msg) ENTT_ASSERT(false, msg);
- #ifdef ENTT_NO_ETO
- # define ENTT_ETO_TYPE(Type) void
- #else
- # define ENTT_ETO_TYPE(Type) Type
- #endif
- #ifdef ENTT_NO_MIXIN
- # define ENTT_STORAGE(Mixin, ...) __VA_ARGS__
- #else
- # define ENTT_STORAGE(Mixin, ...) Mixin<__VA_ARGS__>
- #endif
- #ifdef ENTT_STANDARD_CPP
- # define ENTT_NONSTD false
- #else
- # define ENTT_NONSTD true
- # if defined __clang__ || defined __GNUC__
- # define ENTT_PRETTY_FUNCTION __PRETTY_FUNCTION__
- # define ENTT_PRETTY_FUNCTION_PREFIX '='
- # define ENTT_PRETTY_FUNCTION_SUFFIX ']'
- # elif defined _MSC_VER
- # define ENTT_PRETTY_FUNCTION __FUNCSIG__
- # define ENTT_PRETTY_FUNCTION_PREFIX '<'
- # define ENTT_PRETTY_FUNCTION_SUFFIX '>'
- # endif
- #endif
- #ifndef ENTT_EXPORT
- # if defined _WIN32 || defined __CYGWIN__ || defined _MSC_VER
- # define ENTT_EXPORT __declspec(dllexport)
- # define ENTT_IMPORT __declspec(dllimport)
- # define ENTT_HIDDEN
- # elif defined __GNUC__ && __GNUC__ >= 4
- # define ENTT_EXPORT __attribute__((visibility("default")))
- # define ENTT_IMPORT __attribute__((visibility("default")))
- # define ENTT_HIDDEN __attribute__((visibility("hidden")))
- # else /* Unsupported compiler */
- # define ENTT_EXPORT
- # define ENTT_IMPORT
- # define ENTT_HIDDEN
- # endif
- #endif
- #ifndef ENTT_API
- # if defined ENTT_API_EXPORT
- # define ENTT_API ENTT_EXPORT
- # elif defined ENTT_API_IMPORT
- # define ENTT_API ENTT_IMPORT
- # else /* No API */
- # define ENTT_API
- # endif
- #endif
- #if defined _MSC_VER
- # pragma detect_mismatch("entt.version", ENTT_VERSION)
- # pragma detect_mismatch("entt.noexcept", ENTT_XSTR(ENTT_TRY))
- # pragma detect_mismatch("entt.id", ENTT_XSTR(ENTT_ID_TYPE))
- # pragma detect_mismatch("entt.nonstd", ENTT_XSTR(ENTT_NONSTD))
- #endif
- // NOLINTEND(cppcoreguidelines-macro-usage)
- #endif
- namespace entt {
- /*! @brief Possible modes of an any object. */
- enum class any_policy : std::uint8_t {
- /*! @brief Default mode, no element available. */
- empty,
- /*! @brief Owning mode, dynamically allocated element. */
- dynamic,
- /*! @brief Owning mode, embedded element. */
- embedded,
- /*! @brief Aliasing mode, non-const reference. */
- ref,
- /*! @brief Const aliasing mode, const reference. */
- cref
- };
- // NOLINTNEXTLINE(cppcoreguidelines-avoid-c-arrays, modernize-avoid-c-arrays)
- template<std::size_t Len = sizeof(double[2]), std::size_t = alignof(double[2])>
- class basic_any;
- /*! @brief Alias declaration for type identifiers. */
- using id_type = ENTT_ID_TYPE;
- /*! @brief Alias declaration for the most common use case. */
- using any = basic_any<>;
- template<typename, typename>
- class compressed_pair;
- template<typename>
- class basic_hashed_string;
- /*! @brief Aliases for common character types. */
- using hashed_string = basic_hashed_string<char>;
- /*! @brief Aliases for common character types. */
- using hashed_wstring = basic_hashed_string<wchar_t>;
- // NOLINTNEXTLINE(bugprone-forward-declaration-namespace)
- struct type_info;
- } // namespace entt
- #endif
- // #include "type_traits.hpp"
- #ifndef ENTT_CORE_TYPE_TRAITS_HPP
- #define ENTT_CORE_TYPE_TRAITS_HPP
- #include <cstddef>
- #include <iterator>
- #include <tuple>
- #include <type_traits>
- #include <utility>
- // #include "../config/config.h"
- // #include "fwd.hpp"
- namespace entt {
- /**
- * @brief Utility class to disambiguate overloaded functions.
- * @tparam N Number of choices available.
- */
- template<std::size_t N>
- struct choice_t
- // unfortunately, doxygen cannot parse such a construct
- : /*! @cond TURN_OFF_DOXYGEN */ choice_t<N - 1> /*! @endcond */
- {};
- /*! @copybrief choice_t */
- template<>
- struct choice_t<0> {};
- /**
- * @brief Variable template for the choice trick.
- * @tparam N Number of choices available.
- */
- template<std::size_t N>
- inline constexpr choice_t<N> choice{};
- /**
- * @brief Identity type trait.
- *
- * Useful to establish non-deduced contexts in template argument deduction
- * (waiting for C++20) or to provide types through function arguments.
- *
- * @tparam Type A type.
- */
- template<typename Type>
- struct type_identity {
- /*! @brief Identity type. */
- using type = Type;
- };
- /**
- * @brief Helper type.
- * @tparam Type A type.
- */
- template<typename Type>
- using type_identity_t = typename type_identity<Type>::type;
- /**
- * @brief A type-only `sizeof` wrapper that returns 0 where `sizeof` complains.
- * @tparam Type The type of which to return the size.
- */
- template<typename Type, typename = void>
- struct size_of: std::integral_constant<std::size_t, 0u> {};
- /*! @copydoc size_of */
- template<typename Type>
- struct size_of<Type, std::void_t<decltype(sizeof(Type))>>
- // NOLINTNEXTLINE(bugprone-sizeof-expression)
- : std::integral_constant<std::size_t, sizeof(Type)> {};
- /**
- * @brief Helper variable template.
- * @tparam Type The type of which to return the size.
- */
- template<typename Type>
- inline constexpr std::size_t size_of_v = size_of<Type>::value;
- /**
- * @brief Using declaration to be used to _repeat_ the same type a number of
- * times equal to the size of a given parameter pack.
- * @tparam Type A type to repeat.
- */
- template<typename Type, typename>
- using unpack_as_type = Type;
- /**
- * @brief Helper variable template to be used to _repeat_ the same value a
- * number of times equal to the size of a given parameter pack.
- * @tparam Value A value to repeat.
- */
- template<auto Value, typename>
- inline constexpr auto unpack_as_value = Value;
- /**
- * @brief Wraps a static constant.
- * @tparam Value A static constant.
- */
- template<auto Value>
- using integral_constant = std::integral_constant<decltype(Value), Value>;
- /**
- * @brief Alias template to facilitate the creation of named values.
- * @tparam Value A constant value at least convertible to `id_type`.
- */
- template<id_type Value>
- using tag = integral_constant<Value>;
- /**
- * @brief A class to use to push around lists of types, nothing more.
- * @tparam Type Types provided by the type list.
- */
- template<typename... Type>
- struct type_list {
- /*! @brief Type list type. */
- using type = type_list;
- /*! @brief Compile-time number of elements in the type list. */
- static constexpr auto size = sizeof...(Type);
- };
- /*! @brief Primary template isn't defined on purpose. */
- template<std::size_t, typename>
- struct type_list_element;
- /**
- * @brief Provides compile-time indexed access to the types of a type list.
- * @tparam Index Index of the type to return.
- * @tparam First First type provided by the type list.
- * @tparam Other Other types provided by the type list.
- */
- template<std::size_t Index, typename First, typename... Other>
- struct type_list_element<Index, type_list<First, Other...>>
- : type_list_element<Index - 1u, type_list<Other...>> {};
- /**
- * @brief Provides compile-time indexed access to the types of a type list.
- * @tparam First First type provided by the type list.
- * @tparam Other Other types provided by the type list.
- */
- template<typename First, typename... Other>
- struct type_list_element<0u, type_list<First, Other...>> {
- /*! @brief Searched type. */
- using type = First;
- };
- /**
- * @brief Helper type.
- * @tparam Index Index of the type to return.
- * @tparam List Type list to search into.
- */
- template<std::size_t Index, typename List>
- using type_list_element_t = typename type_list_element<Index, List>::type;
- /*! @brief Primary template isn't defined on purpose. */
- template<typename, typename>
- struct type_list_index;
- /**
- * @brief Provides compile-time type access to the types of a type list.
- * @tparam Type Type to look for and for which to return the index.
- * @tparam First First type provided by the type list.
- * @tparam Other Other types provided by the type list.
- */
- template<typename Type, typename First, typename... Other>
- struct type_list_index<Type, type_list<First, Other...>> {
- /*! @brief Unsigned integer type. */
- using value_type = std::size_t;
- /*! @brief Compile-time position of the given type in the sublist. */
- static constexpr value_type value = 1u + type_list_index<Type, type_list<Other...>>::value;
- };
- /**
- * @brief Provides compile-time type access to the types of a type list.
- * @tparam Type Type to look for and for which to return the index.
- * @tparam Other Other types provided by the type list.
- */
- template<typename Type, typename... Other>
- struct type_list_index<Type, type_list<Type, Other...>> {
- static_assert(type_list_index<Type, type_list<Other...>>::value == sizeof...(Other), "Non-unique type");
- /*! @brief Unsigned integer type. */
- using value_type = std::size_t;
- /*! @brief Compile-time position of the given type in the sublist. */
- static constexpr value_type value = 0u;
- };
- /**
- * @brief Provides compile-time type access to the types of a type list.
- * @tparam Type Type to look for and for which to return the index.
- */
- template<typename Type>
- struct type_list_index<Type, type_list<>> {
- /*! @brief Unsigned integer type. */
- using value_type = std::size_t;
- /*! @brief Compile-time position of the given type in the sublist. */
- static constexpr value_type value = 0u;
- };
- /**
- * @brief Helper variable template.
- * @tparam List Type list.
- * @tparam Type Type to look for and for which to return the index.
- */
- template<typename Type, typename List>
- inline constexpr std::size_t type_list_index_v = type_list_index<Type, List>::value;
- /**
- * @brief Concatenates multiple type lists.
- * @tparam Type Types provided by the first type list.
- * @tparam Other Types provided by the second type list.
- * @return A type list composed by the types of both the type lists.
- */
- template<typename... Type, typename... Other>
- constexpr type_list<Type..., Other...> operator+(type_list<Type...>, type_list<Other...>) {
- return {};
- }
- /*! @brief Primary template isn't defined on purpose. */
- template<typename...>
- struct type_list_cat;
- /*! @brief Concatenates multiple type lists. */
- template<>
- struct type_list_cat<> {
- /*! @brief A type list composed by the types of all the type lists. */
- using type = type_list<>;
- };
- /**
- * @brief Concatenates multiple type lists.
- * @tparam Type Types provided by the first type list.
- * @tparam Other Types provided by the second type list.
- * @tparam List Other type lists, if any.
- */
- template<typename... Type, typename... Other, typename... List>
- struct type_list_cat<type_list<Type...>, type_list<Other...>, List...> {
- /*! @brief A type list composed by the types of all the type lists. */
- using type = typename type_list_cat<type_list<Type..., Other...>, List...>::type;
- };
- /**
- * @brief Concatenates multiple type lists.
- * @tparam Type Types provided by the type list.
- */
- template<typename... Type>
- struct type_list_cat<type_list<Type...>> {
- /*! @brief A type list composed by the types of all the type lists. */
- using type = type_list<Type...>;
- };
- /**
- * @brief Helper type.
- * @tparam List Type lists to concatenate.
- */
- template<typename... List>
- using type_list_cat_t = typename type_list_cat<List...>::type;
- /*! @cond TURN_OFF_DOXYGEN */
- namespace internal {
- template<typename...>
- struct type_list_unique;
- template<typename First, typename... Other, typename... Type>
- struct type_list_unique<type_list<First, Other...>, Type...>
- : std::conditional_t<(std::is_same_v<First, Type> || ...), type_list_unique<type_list<Other...>, Type...>, type_list_unique<type_list<Other...>, Type..., First>> {};
- template<typename... Type>
- struct type_list_unique<type_list<>, Type...> {
- using type = type_list<Type...>;
- };
- } // namespace internal
- /*! @endcond */
- /**
- * @brief Removes duplicates types from a type list.
- * @tparam List Type list.
- */
- template<typename List>
- struct type_list_unique {
- /*! @brief A type list without duplicate types. */
- using type = typename internal::type_list_unique<List>::type;
- };
- /**
- * @brief Helper type.
- * @tparam List Type list.
- */
- template<typename List>
- using type_list_unique_t = typename type_list_unique<List>::type;
- /**
- * @brief Provides the member constant `value` to true if a type list contains a
- * given type, false otherwise.
- * @tparam List Type list.
- * @tparam Type Type to look for.
- */
- template<typename List, typename Type>
- struct type_list_contains;
- /**
- * @copybrief type_list_contains
- * @tparam Type Types provided by the type list.
- * @tparam Other Type to look for.
- */
- template<typename... Type, typename Other>
- struct type_list_contains<type_list<Type...>, Other>
- : std::bool_constant<(std::is_same_v<Type, Other> || ...)> {};
- /**
- * @brief Helper variable template.
- * @tparam List Type list.
- * @tparam Type Type to look for.
- */
- template<typename List, typename Type>
- inline constexpr bool type_list_contains_v = type_list_contains<List, Type>::value;
- /*! @brief Primary template isn't defined on purpose. */
- template<typename...>
- struct type_list_diff;
- /**
- * @brief Computes the difference between two type lists.
- * @tparam Type Types provided by the first type list.
- * @tparam Other Types provided by the second type list.
- */
- template<typename... Type, typename... Other>
- struct type_list_diff<type_list<Type...>, type_list<Other...>> {
- /*! @brief A type list that is the difference between the two type lists. */
- using type = type_list_cat_t<std::conditional_t<type_list_contains_v<type_list<Other...>, Type>, type_list<>, type_list<Type>>...>;
- };
- /**
- * @brief Helper type.
- * @tparam List Type lists between which to compute the difference.
- */
- template<typename... List>
- using type_list_diff_t = typename type_list_diff<List...>::type;
- /*! @brief Primary template isn't defined on purpose. */
- template<typename, template<typename...> class>
- struct type_list_transform;
- /**
- * @brief Applies a given _function_ to a type list and generate a new list.
- * @tparam Type Types provided by the type list.
- * @tparam Op Unary operation as template class with a type member named `type`.
- */
- template<typename... Type, template<typename...> class Op>
- struct type_list_transform<type_list<Type...>, Op> {
- /*! @brief Resulting type list after applying the transform function. */
- // NOLINTNEXTLINE(modernize-type-traits)
- using type = type_list<typename Op<Type>::type...>;
- };
- /**
- * @brief Helper type.
- * @tparam List Type list.
- * @tparam Op Unary operation as template class with a type member named `type`.
- */
- template<typename List, template<typename...> class Op>
- using type_list_transform_t = typename type_list_transform<List, Op>::type;
- /**
- * @brief A class to use to push around lists of constant values, nothing more.
- * @tparam Value Values provided by the value list.
- */
- template<auto... Value>
- struct value_list {
- /*! @brief Value list type. */
- using type = value_list;
- /*! @brief Compile-time number of elements in the value list. */
- static constexpr auto size = sizeof...(Value);
- };
- /*! @brief Primary template isn't defined on purpose. */
- template<std::size_t, typename>
- struct value_list_element;
- /**
- * @brief Provides compile-time indexed access to the values of a value list.
- * @tparam Index Index of the value to return.
- * @tparam Value First value provided by the value list.
- * @tparam Other Other values provided by the value list.
- */
- template<std::size_t Index, auto Value, auto... Other>
- struct value_list_element<Index, value_list<Value, Other...>>
- : value_list_element<Index - 1u, value_list<Other...>> {};
- /**
- * @brief Provides compile-time indexed access to the types of a type list.
- * @tparam Value First value provided by the value list.
- * @tparam Other Other values provided by the value list.
- */
- template<auto Value, auto... Other>
- struct value_list_element<0u, value_list<Value, Other...>> {
- /*! @brief Searched type. */
- using type = decltype(Value);
- /*! @brief Searched value. */
- static constexpr auto value = Value;
- };
- /**
- * @brief Helper type.
- * @tparam Index Index of the type to return.
- * @tparam List Value list to search into.
- */
- template<std::size_t Index, typename List>
- using value_list_element_t = typename value_list_element<Index, List>::type;
- /**
- * @brief Helper type.
- * @tparam Index Index of the value to return.
- * @tparam List Value list to search into.
- */
- template<std::size_t Index, typename List>
- inline constexpr auto value_list_element_v = value_list_element<Index, List>::value;
- /*! @brief Primary template isn't defined on purpose. */
- template<auto, typename>
- struct value_list_index;
- /**
- * @brief Provides compile-time type access to the values of a value list.
- * @tparam Value Value to look for and for which to return the index.
- * @tparam First First value provided by the value list.
- * @tparam Other Other values provided by the value list.
- */
- template<auto Value, auto First, auto... Other>
- struct value_list_index<Value, value_list<First, Other...>> {
- /*! @brief Unsigned integer type. */
- using value_type = std::size_t;
- /*! @brief Compile-time position of the given value in the sublist. */
- static constexpr value_type value = 1u + value_list_index<Value, value_list<Other...>>::value;
- };
- /**
- * @brief Provides compile-time type access to the values of a value list.
- * @tparam Value Value to look for and for which to return the index.
- * @tparam Other Other values provided by the value list.
- */
- template<auto Value, auto... Other>
- struct value_list_index<Value, value_list<Value, Other...>> {
- static_assert(value_list_index<Value, value_list<Other...>>::value == sizeof...(Other), "Non-unique type");
- /*! @brief Unsigned integer type. */
- using value_type = std::size_t;
- /*! @brief Compile-time position of the given value in the sublist. */
- static constexpr value_type value = 0u;
- };
- /**
- * @brief Provides compile-time type access to the values of a value list.
- * @tparam Value Value to look for and for which to return the index.
- */
- template<auto Value>
- struct value_list_index<Value, value_list<>> {
- /*! @brief Unsigned integer type. */
- using value_type = std::size_t;
- /*! @brief Compile-time position of the given type in the sublist. */
- static constexpr value_type value = 0u;
- };
- /**
- * @brief Helper variable template.
- * @tparam List Value list.
- * @tparam Value Value to look for and for which to return the index.
- */
- template<auto Value, typename List>
- inline constexpr std::size_t value_list_index_v = value_list_index<Value, List>::value;
- /**
- * @brief Concatenates multiple value lists.
- * @tparam Value Values provided by the first value list.
- * @tparam Other Values provided by the second value list.
- * @return A value list composed by the values of both the value lists.
- */
- template<auto... Value, auto... Other>
- constexpr value_list<Value..., Other...> operator+(value_list<Value...>, value_list<Other...>) {
- return {};
- }
- /*! @brief Primary template isn't defined on purpose. */
- template<typename...>
- struct value_list_cat;
- /*! @brief Concatenates multiple value lists. */
- template<>
- struct value_list_cat<> {
- /*! @brief A value list composed by the values of all the value lists. */
- using type = value_list<>;
- };
- /**
- * @brief Concatenates multiple value lists.
- * @tparam Value Values provided by the first value list.
- * @tparam Other Values provided by the second value list.
- * @tparam List Other value lists, if any.
- */
- template<auto... Value, auto... Other, typename... List>
- struct value_list_cat<value_list<Value...>, value_list<Other...>, List...> {
- /*! @brief A value list composed by the values of all the value lists. */
- using type = typename value_list_cat<value_list<Value..., Other...>, List...>::type;
- };
- /**
- * @brief Concatenates multiple value lists.
- * @tparam Value Values provided by the value list.
- */
- template<auto... Value>
- struct value_list_cat<value_list<Value...>> {
- /*! @brief A value list composed by the values of all the value lists. */
- using type = value_list<Value...>;
- };
- /**
- * @brief Helper type.
- * @tparam List Value lists to concatenate.
- */
- template<typename... List>
- using value_list_cat_t = typename value_list_cat<List...>::type;
- /*! @brief Primary template isn't defined on purpose. */
- template<typename>
- struct value_list_unique;
- /**
- * @brief Removes duplicates values from a value list.
- * @tparam Value One of the values provided by the given value list.
- * @tparam Other The other values provided by the given value list.
- */
- template<auto Value, auto... Other>
- struct value_list_unique<value_list<Value, Other...>> {
- /*! @brief A value list without duplicate types. */
- using type = std::conditional_t<
- ((Value == Other) || ...),
- typename value_list_unique<value_list<Other...>>::type,
- value_list_cat_t<value_list<Value>, typename value_list_unique<value_list<Other...>>::type>>;
- };
- /*! @brief Removes duplicates values from a value list. */
- template<>
- struct value_list_unique<value_list<>> {
- /*! @brief A value list without duplicate types. */
- using type = value_list<>;
- };
- /**
- * @brief Helper type.
- * @tparam Type A value list.
- */
- template<typename Type>
- using value_list_unique_t = typename value_list_unique<Type>::type;
- /**
- * @brief Provides the member constant `value` to true if a value list contains
- * a given value, false otherwise.
- * @tparam List Value list.
- * @tparam Value Value to look for.
- */
- template<typename List, auto Value>
- struct value_list_contains;
- /**
- * @copybrief value_list_contains
- * @tparam Value Values provided by the value list.
- * @tparam Other Value to look for.
- */
- template<auto... Value, auto Other>
- struct value_list_contains<value_list<Value...>, Other>
- : std::bool_constant<((Value == Other) || ...)> {};
- /**
- * @brief Helper variable template.
- * @tparam List Value list.
- * @tparam Value Value to look for.
- */
- template<typename List, auto Value>
- inline constexpr bool value_list_contains_v = value_list_contains<List, Value>::value;
- /*! @brief Primary template isn't defined on purpose. */
- template<typename...>
- struct value_list_diff;
- /**
- * @brief Computes the difference between two value lists.
- * @tparam Value Values provided by the first value list.
- * @tparam Other Values provided by the second value list.
- */
- template<auto... Value, auto... Other>
- struct value_list_diff<value_list<Value...>, value_list<Other...>> {
- /*! @brief A value list that is the difference between the two value lists. */
- using type = value_list_cat_t<std::conditional_t<value_list_contains_v<value_list<Other...>, Value>, value_list<>, value_list<Value>>...>;
- };
- /**
- * @brief Helper type.
- * @tparam List Value lists between which to compute the difference.
- */
- template<typename... List>
- using value_list_diff_t = typename value_list_diff<List...>::type;
- /*! @brief Same as std::is_invocable, but with tuples. */
- template<typename, typename>
- struct is_applicable: std::false_type {};
- /**
- * @copybrief is_applicable
- * @tparam Func A valid function type.
- * @tparam Tuple Tuple-like type.
- * @tparam Args The list of arguments to use to probe the function type.
- */
- template<typename Func, template<typename...> class Tuple, typename... Args>
- struct is_applicable<Func, Tuple<Args...>>: std::is_invocable<Func, Args...> {};
- /**
- * @copybrief is_applicable
- * @tparam Func A valid function type.
- * @tparam Tuple Tuple-like type.
- * @tparam Args The list of arguments to use to probe the function type.
- */
- template<typename Func, template<typename...> class Tuple, typename... Args>
- struct is_applicable<Func, const Tuple<Args...>>: std::is_invocable<Func, Args...> {};
- /**
- * @brief Helper variable template.
- * @tparam Func A valid function type.
- * @tparam Args The list of arguments to use to probe the function type.
- */
- template<typename Func, typename Args>
- inline constexpr bool is_applicable_v = is_applicable<Func, Args>::value;
- /*! @brief Same as std::is_invocable_r, but with tuples for arguments. */
- template<typename, typename, typename>
- struct is_applicable_r: std::false_type {};
- /**
- * @copybrief is_applicable_r
- * @tparam Ret The type to which the return type of the function should be
- * convertible.
- * @tparam Func A valid function type.
- * @tparam Args The list of arguments to use to probe the function type.
- */
- template<typename Ret, typename Func, typename... Args>
- struct is_applicable_r<Ret, Func, std::tuple<Args...>>: std::is_invocable_r<Ret, Func, Args...> {};
- /**
- * @brief Helper variable template.
- * @tparam Ret The type to which the return type of the function should be
- * convertible.
- * @tparam Func A valid function type.
- * @tparam Args The list of arguments to use to probe the function type.
- */
- template<typename Ret, typename Func, typename Args>
- inline constexpr bool is_applicable_r_v = is_applicable_r<Ret, Func, Args>::value;
- /**
- * @brief Provides the member constant `value` to true if a given type is
- * complete, false otherwise.
- * @tparam Type The type to test.
- */
- template<typename Type, typename = void>
- struct is_complete: std::false_type {};
- /*! @copydoc is_complete */
- template<typename Type>
- struct is_complete<Type, std::void_t<decltype(sizeof(Type))>>: std::true_type {};
- /**
- * @brief Helper variable template.
- * @tparam Type The type to test.
- */
- template<typename Type>
- inline constexpr bool is_complete_v = is_complete<Type>::value;
- /**
- * @brief Provides the member constant `value` to true if a given type is an
- * iterator, false otherwise.
- * @tparam Type The type to test.
- */
- template<typename Type, typename = void>
- struct is_iterator: std::false_type {};
- /*! @cond TURN_OFF_DOXYGEN */
- namespace internal {
- template<typename, typename = void>
- struct has_iterator_category: std::false_type {};
- template<typename Type>
- struct has_iterator_category<Type, std::void_t<typename std::iterator_traits<Type>::iterator_category>>: std::true_type {};
- } // namespace internal
- /*! @endcond */
- /*! @copydoc is_iterator */
- template<typename Type>
- struct is_iterator<Type, std::enable_if_t<!std::is_void_v<std::remove_const_t<std::remove_pointer_t<Type>>>>>
- : internal::has_iterator_category<Type> {};
- /**
- * @brief Helper variable template.
- * @tparam Type The type to test.
- */
- template<typename Type>
- inline constexpr bool is_iterator_v = is_iterator<Type>::value;
- /**
- * @brief Provides the member constant `value` to true if a given type is both
- * an empty and non-final class, false otherwise.
- * @tparam Type The type to test
- */
- template<typename Type>
- struct is_ebco_eligible
- : std::bool_constant<std::is_empty_v<Type> && !std::is_final_v<Type>> {};
- /**
- * @brief Helper variable template.
- * @tparam Type The type to test.
- */
- template<typename Type>
- inline constexpr bool is_ebco_eligible_v = is_ebco_eligible<Type>::value;
- /**
- * @brief Provides the member constant `value` to true if `Type::is_transparent`
- * is valid and denotes a type, false otherwise.
- * @tparam Type The type to test.
- */
- template<typename Type, typename = void>
- struct is_transparent: std::false_type {};
- /*! @copydoc is_transparent */
- template<typename Type>
- struct is_transparent<Type, std::void_t<typename Type::is_transparent>>: std::true_type {};
- /**
- * @brief Helper variable template.
- * @tparam Type The type to test.
- */
- template<typename Type>
- inline constexpr bool is_transparent_v = is_transparent<Type>::value;
- /*! @cond TURN_OFF_DOXYGEN */
- namespace internal {
- template<typename, typename = void>
- struct has_tuple_size_value: std::false_type {};
- template<typename Type>
- struct has_tuple_size_value<Type, std::void_t<decltype(std::tuple_size<const Type>::value)>>: std::true_type {};
- template<typename, typename = void>
- struct has_value_type: std::false_type {};
- template<typename Type>
- struct has_value_type<Type, std::void_t<typename Type::value_type>>: std::true_type {};
- template<typename>
- [[nodiscard]] constexpr bool dispatch_is_equality_comparable();
- template<typename Type, std::size_t... Index>
- [[nodiscard]] constexpr bool unpack_maybe_equality_comparable(std::index_sequence<Index...>) {
- return (dispatch_is_equality_comparable<std::tuple_element_t<Index, Type>>() && ...);
- }
- template<typename>
- [[nodiscard]] constexpr bool maybe_equality_comparable(char) {
- return false;
- }
- template<typename Type>
- [[nodiscard]] constexpr auto maybe_equality_comparable(int) -> decltype(std::declval<Type>() == std::declval<Type>()) {
- return true;
- }
- template<typename Type>
- [[nodiscard]] constexpr bool dispatch_is_equality_comparable() {
- // NOLINTBEGIN(modernize-use-transparent-functors)
- if constexpr(std::is_array_v<Type>) {
- return false;
- } else if constexpr(is_complete_v<std::tuple_size<std::remove_const_t<Type>>>) {
- if constexpr(has_tuple_size_value<Type>::value) {
- return maybe_equality_comparable<Type>(0) && unpack_maybe_equality_comparable<Type>(std::make_index_sequence<std::tuple_size<Type>::value>{});
- } else {
- return maybe_equality_comparable<Type>(0);
- }
- } else if constexpr(has_value_type<Type>::value) {
- if constexpr(is_iterator_v<Type> || std::is_same_v<typename Type::value_type, Type> || dispatch_is_equality_comparable<typename Type::value_type>()) {
- return maybe_equality_comparable<Type>(0);
- } else {
- return false;
- }
- } else {
- return maybe_equality_comparable<Type>(0);
- }
- // NOLINTEND(modernize-use-transparent-functors)
- }
- } // namespace internal
- /*! @endcond */
- /**
- * @brief Provides the member constant `value` to true if a given type is
- * equality comparable, false otherwise.
- * @tparam Type The type to test.
- */
- template<typename Type>
- struct is_equality_comparable: std::bool_constant<internal::dispatch_is_equality_comparable<Type>()> {};
- /*! @copydoc is_equality_comparable */
- template<typename Type>
- struct is_equality_comparable<const Type>: is_equality_comparable<Type> {};
- /**
- * @brief Helper variable template.
- * @tparam Type The type to test.
- */
- template<typename Type>
- inline constexpr bool is_equality_comparable_v = is_equality_comparable<Type>::value;
- /**
- * @brief Transcribes the constness of a type to another type.
- * @tparam To The type to which to transcribe the constness.
- * @tparam From The type from which to transcribe the constness.
- */
- template<typename To, typename From>
- struct constness_as {
- /*! @brief The type resulting from the transcription of the constness. */
- using type = std::remove_const_t<To>;
- };
- /*! @copydoc constness_as */
- template<typename To, typename From>
- struct constness_as<To, const From> {
- /*! @brief The type resulting from the transcription of the constness. */
- using type = const To;
- };
- /**
- * @brief Alias template to facilitate the transcription of the constness.
- * @tparam To The type to which to transcribe the constness.
- * @tparam From The type from which to transcribe the constness.
- */
- template<typename To, typename From>
- using constness_as_t = typename constness_as<To, From>::type;
- /**
- * @brief Extracts the class of a non-static member object or function.
- * @tparam Member A pointer to a non-static member object or function.
- */
- template<typename Member>
- class member_class {
- static_assert(std::is_member_pointer_v<Member>, "Invalid pointer type to non-static member object or function");
- template<typename Class, typename Ret, typename... Args>
- static Class *clazz(Ret (Class::*)(Args...));
- template<typename Class, typename Ret, typename... Args>
- static Class *clazz(Ret (Class::*)(Args...) const);
- template<typename Class, typename Type>
- static Class *clazz(Type Class::*);
- public:
- /*! @brief The class of the given non-static member object or function. */
- using type = std::remove_pointer_t<decltype(clazz(std::declval<Member>()))>;
- };
- /**
- * @brief Helper type.
- * @tparam Member A pointer to a non-static member object or function.
- */
- template<typename Member>
- using member_class_t = typename member_class<Member>::type;
- /**
- * @brief Extracts the n-th argument of a _callable_ type.
- * @tparam Index The index of the argument to extract.
- * @tparam Candidate A valid _callable_ type.
- */
- template<std::size_t Index, typename Candidate>
- class nth_argument {
- template<typename Ret, typename... Args>
- static constexpr type_list<Args...> pick_up(Ret (*)(Args...));
- template<typename Ret, typename Class, typename... Args>
- static constexpr type_list<Args...> pick_up(Ret (Class ::*)(Args...));
- template<typename Ret, typename Class, typename... Args>
- static constexpr type_list<Args...> pick_up(Ret (Class ::*)(Args...) const);
- template<typename Type, typename Class>
- static constexpr type_list<Type> pick_up(Type Class ::*);
- template<typename Type>
- static constexpr decltype(pick_up(&Type::operator())) pick_up(Type &&);
- public:
- /*! @brief N-th argument of the _callable_ type. */
- using type = type_list_element_t<Index, decltype(pick_up(std::declval<Candidate>()))>;
- };
- /**
- * @brief Helper type.
- * @tparam Index The index of the argument to extract.
- * @tparam Candidate A valid function, member function or data member type.
- */
- template<std::size_t Index, typename Candidate>
- using nth_argument_t = typename nth_argument<Index, Candidate>::type;
- } // namespace entt
- template<typename... Type>
- struct std::tuple_size<entt::type_list<Type...>>: std::integral_constant<std::size_t, entt::type_list<Type...>::size> {};
- template<std::size_t Index, typename... Type>
- struct std::tuple_element<Index, entt::type_list<Type...>>: entt::type_list_element<Index, entt::type_list<Type...>> {};
- template<auto... Value>
- struct std::tuple_size<entt::value_list<Value...>>: std::integral_constant<std::size_t, entt::value_list<Value...>::size> {};
- template<std::size_t Index, auto... Value>
- struct std::tuple_element<Index, entt::value_list<Value...>>: entt::value_list_element<Index, entt::value_list<Value...>> {};
- #endif
- namespace entt {
- /*! @cond TURN_OFF_DOXYGEN */
- namespace internal {
- template<typename Type, std::size_t, typename = void>
- struct compressed_pair_element {
- using reference = Type &;
- using const_reference = const Type &;
- template<typename Dummy = Type, typename = std::enable_if_t<std::is_default_constructible_v<Dummy>>>
- // NOLINTNEXTLINE(modernize-use-equals-default)
- constexpr compressed_pair_element() noexcept(std::is_nothrow_default_constructible_v<Type>) {}
- template<typename Arg, typename = std::enable_if_t<!std::is_same_v<std::remove_const_t<std::remove_reference_t<Arg>>, compressed_pair_element>>>
- constexpr compressed_pair_element(Arg &&arg) noexcept(std::is_nothrow_constructible_v<Type, Arg>)
- : value{std::forward<Arg>(arg)} {}
- template<typename... Args, std::size_t... Index>
- constexpr compressed_pair_element(std::tuple<Args...> args, std::index_sequence<Index...>) noexcept(std::is_nothrow_constructible_v<Type, Args...>)
- : value{std::forward<Args>(std::get<Index>(args))...} {}
- [[nodiscard]] constexpr reference get() noexcept {
- return value;
- }
- [[nodiscard]] constexpr const_reference get() const noexcept {
- return value;
- }
- private:
- Type value{};
- };
- template<typename Type, std::size_t Tag>
- struct compressed_pair_element<Type, Tag, std::enable_if_t<is_ebco_eligible_v<Type>>>: Type {
- using reference = Type &;
- using const_reference = const Type &;
- using base_type = Type;
- template<typename Dummy = Type, typename = std::enable_if_t<std::is_default_constructible_v<Dummy>>>
- constexpr compressed_pair_element() noexcept(std::is_nothrow_default_constructible_v<base_type>)
- : base_type{} {}
- template<typename Arg, typename = std::enable_if_t<!std::is_same_v<std::remove_const_t<std::remove_reference_t<Arg>>, compressed_pair_element>>>
- constexpr compressed_pair_element(Arg &&arg) noexcept(std::is_nothrow_constructible_v<base_type, Arg>)
- : base_type{std::forward<Arg>(arg)} {}
- template<typename... Args, std::size_t... Index>
- constexpr compressed_pair_element(std::tuple<Args...> args, std::index_sequence<Index...>) noexcept(std::is_nothrow_constructible_v<base_type, Args...>)
- : base_type{std::forward<Args>(std::get<Index>(args))...} {}
- [[nodiscard]] constexpr reference get() noexcept {
- return *this;
- }
- [[nodiscard]] constexpr const_reference get() const noexcept {
- return *this;
- }
- };
- } // namespace internal
- /*! @endcond */
- /**
- * @brief A compressed pair.
- *
- * A pair that exploits the _Empty Base Class Optimization_ (or _EBCO_) to
- * reduce its final size to a minimum.
- *
- * @tparam First The type of the first element that the pair stores.
- * @tparam Second The type of the second element that the pair stores.
- */
- template<typename First, typename Second>
- class compressed_pair final
- : internal::compressed_pair_element<First, 0u>,
- internal::compressed_pair_element<Second, 1u> {
- using first_base = internal::compressed_pair_element<First, 0u>;
- using second_base = internal::compressed_pair_element<Second, 1u>;
- public:
- /*! @brief The type of the first element that the pair stores. */
- using first_type = First;
- /*! @brief The type of the second element that the pair stores. */
- using second_type = Second;
- /**
- * @brief Default constructor, conditionally enabled.
- *
- * This constructor is only available when the types that the pair stores
- * are both at least default constructible.
- *
- * @tparam Dummy Dummy template parameter used for internal purposes.
- */
- template<bool Dummy = true, typename = std::enable_if_t<Dummy && std::is_default_constructible_v<first_type> && std::is_default_constructible_v<second_type>>>
- constexpr compressed_pair() noexcept(std::is_nothrow_default_constructible_v<first_base> && std::is_nothrow_default_constructible_v<second_base>)
- : first_base{},
- second_base{} {}
- /**
- * @brief Copy constructor.
- * @param other The instance to copy from.
- */
- constexpr compressed_pair(const compressed_pair &other) = default;
- /**
- * @brief Move constructor.
- * @param other The instance to move from.
- */
- constexpr compressed_pair(compressed_pair &&other) noexcept = default;
- /**
- * @brief Constructs a pair from its values.
- * @tparam Arg Type of value to use to initialize the first element.
- * @tparam Other Type of value to use to initialize the second element.
- * @param arg Value to use to initialize the first element.
- * @param other Value to use to initialize the second element.
- */
- template<typename Arg, typename Other>
- constexpr compressed_pair(Arg &&arg, Other &&other) noexcept(std::is_nothrow_constructible_v<first_base, Arg> && std::is_nothrow_constructible_v<second_base, Other>)
- : first_base{std::forward<Arg>(arg)},
- second_base{std::forward<Other>(other)} {}
- /**
- * @brief Constructs a pair by forwarding the arguments to its parts.
- * @tparam Args Types of arguments to use to initialize the first element.
- * @tparam Other Types of arguments to use to initialize the second element.
- * @param args Arguments to use to initialize the first element.
- * @param other Arguments to use to initialize the second element.
- */
- template<typename... Args, typename... Other>
- constexpr compressed_pair(std::piecewise_construct_t, std::tuple<Args...> args, std::tuple<Other...> other) noexcept(std::is_nothrow_constructible_v<first_base, Args...> && std::is_nothrow_constructible_v<second_base, Other...>)
- : first_base{std::move(args), std::index_sequence_for<Args...>{}},
- second_base{std::move(other), std::index_sequence_for<Other...>{}} {}
- /*! @brief Default destructor. */
- ~compressed_pair() = default;
- /**
- * @brief Copy assignment operator.
- * @param other The instance to copy from.
- * @return This compressed pair object.
- */
- constexpr compressed_pair &operator=(const compressed_pair &other) = default;
- /**
- * @brief Move assignment operator.
- * @param other The instance to move from.
- * @return This compressed pair object.
- */
- constexpr compressed_pair &operator=(compressed_pair &&other) noexcept = default;
- /**
- * @brief Returns the first element that a pair stores.
- * @return The first element that a pair stores.
- */
- [[nodiscard]] constexpr first_type &first() noexcept {
- return static_cast<first_base &>(*this).get();
- }
- /*! @copydoc first */
- [[nodiscard]] constexpr const first_type &first() const noexcept {
- return static_cast<const first_base &>(*this).get();
- }
- /**
- * @brief Returns the second element that a pair stores.
- * @return The second element that a pair stores.
- */
- [[nodiscard]] constexpr second_type &second() noexcept {
- return static_cast<second_base &>(*this).get();
- }
- /*! @copydoc second */
- [[nodiscard]] constexpr const second_type &second() const noexcept {
- return static_cast<const second_base &>(*this).get();
- }
- /**
- * @brief Swaps two compressed pair objects.
- * @param other The compressed pair to swap with.
- */
- constexpr void swap(compressed_pair &other) noexcept {
- using std::swap;
- swap(first(), other.first());
- swap(second(), other.second());
- }
- /**
- * @brief Extracts an element from the compressed pair.
- * @tparam Index An integer value that is either 0 or 1.
- * @return Returns a reference to the first element if `Index` is 0 and a
- * reference to the second element if `Index` is 1.
- */
- template<std::size_t Index>
- [[nodiscard]] constexpr decltype(auto) get() noexcept {
- if constexpr(Index == 0u) {
- return first();
- } else {
- static_assert(Index == 1u, "Index out of bounds");
- return second();
- }
- }
- /*! @copydoc get */
- template<std::size_t Index>
- [[nodiscard]] constexpr decltype(auto) get() const noexcept {
- if constexpr(Index == 0u) {
- return first();
- } else {
- static_assert(Index == 1u, "Index out of bounds");
- return second();
- }
- }
- };
- /**
- * @brief Deduction guide.
- * @tparam Type Type of value to use to initialize the first element.
- * @tparam Other Type of value to use to initialize the second element.
- */
- template<typename Type, typename Other>
- compressed_pair(Type &&, Other &&) -> compressed_pair<std::decay_t<Type>, std::decay_t<Other>>;
- /**
- * @brief Swaps two compressed pair objects.
- * @tparam First The type of the first element that the pairs store.
- * @tparam Second The type of the second element that the pairs store.
- * @param lhs A valid compressed pair object.
- * @param rhs A valid compressed pair object.
- */
- template<typename First, typename Second>
- constexpr void swap(compressed_pair<First, Second> &lhs, compressed_pair<First, Second> &rhs) noexcept {
- lhs.swap(rhs);
- }
- } // namespace entt
- namespace std {
- /**
- * @brief `std::tuple_size` specialization for `compressed_pair`s.
- * @tparam First The type of the first element that the pair stores.
- * @tparam Second The type of the second element that the pair stores.
- */
- template<typename First, typename Second>
- struct tuple_size<entt::compressed_pair<First, Second>>: integral_constant<size_t, 2u> {};
- /**
- * @brief `std::tuple_element` specialization for `compressed_pair`s.
- * @tparam Index The index of the type to return.
- * @tparam First The type of the first element that the pair stores.
- * @tparam Second The type of the second element that the pair stores.
- */
- template<size_t Index, typename First, typename Second>
- struct tuple_element<Index, entt::compressed_pair<First, Second>>: conditional<Index == 0u, First, Second> {
- static_assert(Index < 2u, "Index out of bounds");
- };
- } // namespace std
- #endif
- // #include "../core/fwd.hpp"
- #ifndef ENTT_CORE_FWD_HPP
- #define ENTT_CORE_FWD_HPP
- #include <cstddef>
- #include <cstdint>
- // #include "../config/config.h"
- namespace entt {
- /*! @brief Possible modes of an any object. */
- enum class any_policy : std::uint8_t {
- /*! @brief Default mode, no element available. */
- empty,
- /*! @brief Owning mode, dynamically allocated element. */
- dynamic,
- /*! @brief Owning mode, embedded element. */
- embedded,
- /*! @brief Aliasing mode, non-const reference. */
- ref,
- /*! @brief Const aliasing mode, const reference. */
- cref
- };
- // NOLINTNEXTLINE(cppcoreguidelines-avoid-c-arrays, modernize-avoid-c-arrays)
- template<std::size_t Len = sizeof(double[2]), std::size_t = alignof(double[2])>
- class basic_any;
- /*! @brief Alias declaration for type identifiers. */
- using id_type = ENTT_ID_TYPE;
- /*! @brief Alias declaration for the most common use case. */
- using any = basic_any<>;
- template<typename, typename>
- class compressed_pair;
- template<typename>
- class basic_hashed_string;
- /*! @brief Aliases for common character types. */
- using hashed_string = basic_hashed_string<char>;
- /*! @brief Aliases for common character types. */
- using hashed_wstring = basic_hashed_string<wchar_t>;
- // NOLINTNEXTLINE(bugprone-forward-declaration-namespace)
- struct type_info;
- } // namespace entt
- #endif
- // #include "../core/iterator.hpp"
- #ifndef ENTT_CORE_ITERATOR_HPP
- #define ENTT_CORE_ITERATOR_HPP
- #include <iterator>
- #include <memory>
- #include <type_traits>
- #include <utility>
- namespace entt {
- /**
- * @brief Helper type to use as pointer with input iterators.
- * @tparam Type of wrapped value.
- */
- template<typename Type>
- struct input_iterator_pointer final {
- /*! @brief Value type. */
- using value_type = Type;
- /*! @brief Pointer type. */
- using pointer = Type *;
- /*! @brief Reference type. */
- using reference = Type &;
- /**
- * @brief Constructs a proxy object by move.
- * @param val Value to use to initialize the proxy object.
- */
- constexpr input_iterator_pointer(value_type &&val) noexcept(std::is_nothrow_move_constructible_v<value_type>)
- : value{std::move(val)} {}
- /**
- * @brief Access operator for accessing wrapped values.
- * @return A pointer to the wrapped value.
- */
- [[nodiscard]] constexpr pointer operator->() noexcept {
- return std::addressof(value);
- }
- /**
- * @brief Dereference operator for accessing wrapped values.
- * @return A reference to the wrapped value.
- */
- [[nodiscard]] constexpr reference operator*() noexcept {
- return value;
- }
- private:
- Type value;
- };
- /**
- * @brief Plain iota iterator (waiting for C++20).
- * @tparam Type Value type.
- */
- template<typename Type>
- class iota_iterator final {
- static_assert(std::is_integral_v<Type>, "Not an integral type");
- public:
- /*! @brief Value type, likely an integral one. */
- using value_type = Type;
- /*! @brief Invalid pointer type. */
- using pointer = void;
- /*! @brief Non-reference type, same as value type. */
- using reference = value_type;
- /*! @brief Difference type. */
- using difference_type = std::ptrdiff_t;
- /*! @brief Iterator category. */
- using iterator_category = std::input_iterator_tag;
- /*! @brief Default constructor. */
- constexpr iota_iterator() noexcept
- : current{} {}
- /**
- * @brief Constructs an iota iterator from a given value.
- * @param init The initial value assigned to the iota iterator.
- */
- constexpr iota_iterator(const value_type init) noexcept
- : current{init} {}
- /**
- * @brief Pre-increment operator.
- * @return This iota iterator.
- */
- constexpr iota_iterator &operator++() noexcept {
- return ++current, *this;
- }
- /**
- * @brief Post-increment operator.
- * @return This iota iterator.
- */
- constexpr iota_iterator operator++(int) noexcept {
- const iota_iterator orig = *this;
- return ++(*this), orig;
- }
- /**
- * @brief Dereference operator.
- * @return The underlying value.
- */
- [[nodiscard]] constexpr reference operator*() const noexcept {
- return current;
- }
- private:
- value_type current;
- };
- /**
- * @brief Comparison operator.
- * @tparam Type Value type of the iota iterator.
- * @param lhs A properly initialized iota iterator.
- * @param rhs A properly initialized iota iterator.
- * @return True if the two iterators are identical, false otherwise.
- */
- template<typename Type>
- [[nodiscard]] constexpr bool operator==(const iota_iterator<Type> &lhs, const iota_iterator<Type> &rhs) noexcept {
- return *lhs == *rhs;
- }
- /**
- * @brief Comparison operator.
- * @tparam Type Value type of the iota iterator.
- * @param lhs A properly initialized iota iterator.
- * @param rhs A properly initialized iota iterator.
- * @return True if the two iterators differ, false otherwise.
- */
- template<typename Type>
- [[nodiscard]] constexpr bool operator!=(const iota_iterator<Type> &lhs, const iota_iterator<Type> &rhs) noexcept {
- return !(lhs == rhs);
- }
- /**
- * @brief Utility class to create an iterable object from a pair of iterators.
- * @tparam It Type of iterator.
- * @tparam Sentinel Type of sentinel.
- */
- template<typename It, typename Sentinel = It>
- struct iterable_adaptor final {
- /*! @brief Value type. */
- using value_type = typename std::iterator_traits<It>::value_type;
- /*! @brief Iterator type. */
- using iterator = It;
- /*! @brief Sentinel type. */
- using sentinel = Sentinel;
- /*! @brief Default constructor. */
- constexpr iterable_adaptor() noexcept(std::is_nothrow_default_constructible_v<iterator> && std::is_nothrow_default_constructible_v<sentinel>)
- : first{},
- last{} {}
- /**
- * @brief Creates an iterable object from a pair of iterators.
- * @param from Begin iterator.
- * @param to End iterator.
- */
- constexpr iterable_adaptor(iterator from, sentinel to) noexcept(std::is_nothrow_move_constructible_v<iterator> && std::is_nothrow_move_constructible_v<sentinel>)
- : first{std::move(from)},
- last{std::move(to)} {}
- /**
- * @brief Returns an iterator to the beginning.
- * @return An iterator to the first element of the range.
- */
- [[nodiscard]] constexpr iterator begin() const noexcept {
- return first;
- }
- /**
- * @brief Returns an iterator to the end.
- * @return An iterator to the element following the last element of the
- * range.
- */
- [[nodiscard]] constexpr sentinel end() const noexcept {
- return last;
- }
- /*! @copydoc begin */
- [[nodiscard]] constexpr iterator cbegin() const noexcept {
- return begin();
- }
- /*! @copydoc end */
- [[nodiscard]] constexpr sentinel cend() const noexcept {
- return end();
- }
- private:
- It first;
- Sentinel last;
- };
- } // namespace entt
- #endif
- // #include "../core/utility.hpp"
- #ifndef ENTT_CORE_UTILITY_HPP
- #define ENTT_CORE_UTILITY_HPP
- #include <type_traits>
- #include <utility>
- namespace entt {
- /*! @brief Identity function object (waiting for C++20). */
- struct identity {
- /*! @brief Indicates that this is a transparent function object. */
- using is_transparent = void;
- /**
- * @brief Returns its argument unchanged.
- * @tparam Type Type of the argument.
- * @param value The actual argument.
- * @return The submitted value as-is.
- */
- template<typename Type>
- [[nodiscard]] constexpr Type &&operator()(Type &&value) const noexcept {
- return std::forward<Type>(value);
- }
- };
- /**
- * @brief Constant utility to disambiguate overloaded members of a class.
- * @tparam Type Type of the desired overload.
- * @tparam Class Type of class to which the member belongs.
- * @param member A valid pointer to a member.
- * @return Pointer to the member.
- */
- template<typename Type, typename Class>
- [[nodiscard]] constexpr auto overload(Type Class::*member) noexcept {
- return member;
- }
- /**
- * @brief Constant utility to disambiguate overloaded functions.
- * @tparam Func Function type of the desired overload.
- * @param func A valid pointer to a function.
- * @return Pointer to the function.
- */
- template<typename Func>
- [[nodiscard]] constexpr auto overload(Func *func) noexcept {
- return func;
- }
- /**
- * @brief Helper type for visitors.
- * @tparam Func Types of function objects.
- */
- template<typename... Func>
- struct overloaded: Func... {
- using Func::operator()...;
- };
- /**
- * @brief Deduction guide.
- * @tparam Func Types of function objects.
- */
- template<typename... Func>
- overloaded(Func...) -> overloaded<Func...>;
- /**
- * @brief Basic implementation of a y-combinator.
- * @tparam Func Type of a potentially recursive function.
- */
- template<typename Func>
- struct y_combinator {
- /**
- * @brief Constructs a y-combinator from a given function.
- * @param recursive A potentially recursive function.
- */
- constexpr y_combinator(Func recursive) noexcept(std::is_nothrow_move_constructible_v<Func>)
- : func{std::move(recursive)} {}
- /**
- * @brief Invokes a y-combinator and therefore its underlying function.
- * @tparam Args Types of arguments to use to invoke the underlying function.
- * @param args Parameters to use to invoke the underlying function.
- * @return Return value of the underlying function, if any.
- */
- template<typename... Args>
- constexpr decltype(auto) operator()(Args &&...args) const noexcept(std::is_nothrow_invocable_v<Func, const y_combinator &, Args...>) {
- return func(*this, std::forward<Args>(args)...);
- }
- /*! @copydoc operator()() */
- template<typename... Args>
- constexpr decltype(auto) operator()(Args &&...args) noexcept(std::is_nothrow_invocable_v<Func, y_combinator &, Args...>) {
- return func(*this, std::forward<Args>(args)...);
- }
- private:
- Func func;
- };
- } // namespace entt
- #endif
- // #include "fwd.hpp"
- #ifndef ENTT_RESOURCE_FWD_HPP
- #define ENTT_RESOURCE_FWD_HPP
- #include <memory>
- namespace entt {
- template<typename>
- struct resource_loader;
- template<typename Type, typename = resource_loader<Type>, typename = std::allocator<Type>>
- class resource_cache;
- template<typename>
- class resource;
- } // namespace entt
- #endif
- // #include "loader.hpp"
- #ifndef ENTT_RESOURCE_LOADER_HPP
- #define ENTT_RESOURCE_LOADER_HPP
- #include <memory>
- #include <utility>
- // #include "fwd.hpp"
- namespace entt {
- /**
- * @brief Transparent loader for shared resources.
- * @tparam Type Type of resources created by the loader.
- */
- template<typename Type>
- struct resource_loader {
- /*! @brief Result type. */
- using result_type = std::shared_ptr<Type>;
- /**
- * @brief Constructs a shared pointer to a resource from its arguments.
- * @tparam Args Types of arguments to use to construct the resource.
- * @param args Parameters to use to construct the resource.
- * @return A shared pointer to a resource of the given type.
- */
- template<typename... Args>
- result_type operator()(Args &&...args) const {
- return std::make_shared<Type>(std::forward<Args>(args)...);
- }
- };
- } // namespace entt
- #endif
- // #include "resource.hpp"
- #ifndef ENTT_RESOURCE_RESOURCE_HPP
- #define ENTT_RESOURCE_RESOURCE_HPP
- #include <memory>
- #include <type_traits>
- #include <utility>
- // #include "fwd.hpp"
- namespace entt {
- /**
- * @brief Basic resource handle.
- *
- * A handle wraps a resource and extends its lifetime. It also shares the same
- * resource with all other handles constructed from the same element.<br/>
- * As a rule of thumb, resources should never be copied nor moved. Handles are
- * the way to go to push references around.
- *
- * @tparam Type Type of resource managed by a handle.
- */
- template<typename Type>
- class resource {
- template<typename>
- friend class resource;
- template<typename Other>
- static constexpr bool is_acceptable = !std::is_same_v<Type, Other> && std::is_constructible_v<Type &, Other &>;
- public:
- /*! @brief Resource type. */
- using element_type = Type;
- /*! @brief Handle type. */
- using handle_type = std::shared_ptr<element_type>;
- /*! @brief Default constructor. */
- resource() noexcept
- : value{} {}
- /**
- * @brief Creates a new resource handle.
- * @param res A handle to a resource.
- */
- explicit resource(handle_type res) noexcept
- : value{std::move(res)} {}
- /*! @brief Default copy constructor. */
- resource(const resource &) noexcept = default;
- /*! @brief Default move constructor. */
- resource(resource &&) noexcept = default;
- /**
- * @brief Aliasing constructor.
- * @tparam Other Type of resource managed by the received handle.
- * @param other The handle with which to share ownership information.
- * @param res Unrelated and unmanaged resources.
- */
- template<typename Other>
- resource(const resource<Other> &other, element_type &res) noexcept
- : value{other.value, std::addressof(res)} {}
- /**
- * @brief Copy constructs a handle which shares ownership of the resource.
- * @tparam Other Type of resource managed by the received handle.
- * @param other The handle to copy from.
- */
- template<typename Other, typename = std::enable_if_t<is_acceptable<Other>>>
- resource(const resource<Other> &other) noexcept
- : value{other.value} {}
- /**
- * @brief Move constructs a handle which takes ownership of the resource.
- * @tparam Other Type of resource managed by the received handle.
- * @param other The handle to move from.
- */
- template<typename Other, typename = std::enable_if_t<is_acceptable<Other>>>
- resource(resource<Other> &&other) noexcept
- : value{std::move(other.value)} {}
- /*! @brief Default destructor. */
- ~resource() = default;
- /**
- * @brief Default copy assignment operator.
- * @return This resource handle.
- */
- resource &operator=(const resource &) noexcept = default;
- /**
- * @brief Default move assignment operator.
- * @return This resource handle.
- */
- resource &operator=(resource &&) noexcept = default;
- /**
- * @brief Copy assignment operator from foreign handle.
- * @tparam Other Type of resource managed by the received handle.
- * @param other The handle to copy from.
- * @return This resource handle.
- */
- template<typename Other, typename = std::enable_if_t<is_acceptable<Other>>>
- resource &operator=(const resource<Other> &other) noexcept {
- value = other.value;
- return *this;
- }
- /**
- * @brief Move assignment operator from foreign handle.
- * @tparam Other Type of resource managed by the received handle.
- * @param other The handle to move from.
- * @return This resource handle.
- */
- template<typename Other, typename = std::enable_if_t<is_acceptable<Other>>>
- resource &operator=(resource<Other> &&other) noexcept {
- value = std::move(other.value);
- return *this;
- }
- /**
- * @brief Exchanges the content with that of a given resource.
- * @param other Resource to exchange the content with.
- */
- void swap(resource &other) noexcept {
- using std::swap;
- swap(value, other.value);
- }
- /**
- * @brief Returns a reference to the managed resource.
- *
- * @warning
- * The behavior is undefined if the handle doesn't contain a resource.
- *
- * @return A reference to the managed resource.
- */
- [[nodiscard]] element_type &operator*() const noexcept {
- return *value;
- }
- /*! @copydoc operator* */
- [[nodiscard]] operator element_type &() const noexcept {
- return *value;
- }
- /**
- * @brief Returns a pointer to the managed resource.
- * @return A pointer to the managed resource.
- */
- [[nodiscard]] element_type *operator->() const noexcept {
- return value.get();
- }
- /**
- * @brief Returns true if a handle contains a resource, false otherwise.
- * @return True if the handle contains a resource, false otherwise.
- */
- [[nodiscard]] explicit operator bool() const noexcept {
- return static_cast<bool>(value);
- }
- /*! @brief Releases the ownership of the managed resource. */
- void reset() {
- value.reset();
- }
- /**
- * @brief Replaces the managed resource.
- * @param other A handle to a resource.
- */
- void reset(handle_type other) {
- value = std::move(other);
- }
- /**
- * @brief Returns the underlying resource handle.
- * @return The underlying resource handle.
- */
- [[nodiscard]] handle_type handle() const noexcept {
- return value;
- }
- private:
- handle_type value;
- };
- /**
- * @brief Compares two handles.
- * @tparam Lhs Type of resource managed by the first handle.
- * @tparam Rhs Type of resource managed by the second handle.
- * @param lhs A valid handle.
- * @param rhs A valid handle.
- * @return True if both handles refer to the same resource, false otherwise.
- */
- template<typename Lhs, typename Rhs>
- [[nodiscard]] bool operator==(const resource<Lhs> &lhs, const resource<Rhs> &rhs) noexcept {
- return (std::addressof(*lhs) == std::addressof(*rhs));
- }
- /**
- * @brief Compares two handles.
- * @tparam Lhs Type of resource managed by the first handle.
- * @tparam Rhs Type of resource managed by the second handle.
- * @param lhs A valid handle.
- * @param rhs A valid handle.
- * @return False if both handles refer to the same resource, true otherwise.
- */
- template<typename Lhs, typename Rhs>
- [[nodiscard]] bool operator!=(const resource<Lhs> &lhs, const resource<Rhs> &rhs) noexcept {
- return !(lhs == rhs);
- }
- /**
- * @brief Compares two handles.
- * @tparam Lhs Type of resource managed by the first handle.
- * @tparam Rhs Type of resource managed by the second handle.
- * @param lhs A valid handle.
- * @param rhs A valid handle.
- * @return True if the first handle is less than the second, false otherwise.
- */
- template<typename Lhs, typename Rhs>
- [[nodiscard]] bool operator<(const resource<Lhs> &lhs, const resource<Rhs> &rhs) noexcept {
- return (std::addressof(*lhs) < std::addressof(*rhs));
- }
- /**
- * @brief Compares two handles.
- * @tparam Lhs Type of resource managed by the first handle.
- * @tparam Rhs Type of resource managed by the second handle.
- * @param lhs A valid handle.
- * @param rhs A valid handle.
- * @return True if the first handle is greater than the second, false otherwise.
- */
- template<typename Lhs, typename Rhs>
- [[nodiscard]] bool operator>(const resource<Lhs> &lhs, const resource<Rhs> &rhs) noexcept {
- return rhs < lhs;
- }
- /**
- * @brief Compares two handles.
- * @tparam Lhs Type of resource managed by the first handle.
- * @tparam Rhs Type of resource managed by the second handle.
- * @param lhs A valid handle.
- * @param rhs A valid handle.
- * @return True if the first handle is less than or equal to the second, false
- * otherwise.
- */
- template<typename Lhs, typename Rhs>
- [[nodiscard]] bool operator<=(const resource<Lhs> &lhs, const resource<Rhs> &rhs) noexcept {
- return !(lhs > rhs);
- }
- /**
- * @brief Compares two handles.
- * @tparam Lhs Type of resource managed by the first handle.
- * @tparam Rhs Type of resource managed by the second handle.
- * @param lhs A valid handle.
- * @param rhs A valid handle.
- * @return True if the first handle is greater than or equal to the second,
- * false otherwise.
- */
- template<typename Lhs, typename Rhs>
- [[nodiscard]] bool operator>=(const resource<Lhs> &lhs, const resource<Rhs> &rhs) noexcept {
- return !(lhs < rhs);
- }
- } // namespace entt
- #endif
- namespace entt {
- /*! @cond TURN_OFF_DOXYGEN */
- namespace internal {
- template<typename Type, typename It>
- class resource_cache_iterator final {
- template<typename, typename>
- friend class resource_cache_iterator;
- public:
- using value_type = std::pair<id_type, resource<Type>>;
- using pointer = input_iterator_pointer<value_type>;
- using reference = value_type;
- using difference_type = std::ptrdiff_t;
- using iterator_category = std::input_iterator_tag;
- using iterator_concept = std::random_access_iterator_tag;
- constexpr resource_cache_iterator() noexcept = default;
- constexpr resource_cache_iterator(const It iter) noexcept
- : it{iter} {}
- template<typename Other, typename = std::enable_if_t<!std::is_same_v<It, Other> && std::is_constructible_v<It, Other>>>
- constexpr resource_cache_iterator(const resource_cache_iterator<std::remove_const_t<Type>, Other> &other) noexcept
- : it{other.it} {}
- constexpr resource_cache_iterator &operator++() noexcept {
- return ++it, *this;
- }
- constexpr resource_cache_iterator operator++(int) noexcept {
- const resource_cache_iterator orig = *this;
- return ++(*this), orig;
- }
- constexpr resource_cache_iterator &operator--() noexcept {
- return --it, *this;
- }
- constexpr resource_cache_iterator operator--(int) noexcept {
- const resource_cache_iterator orig = *this;
- return operator--(), orig;
- }
- constexpr resource_cache_iterator &operator+=(const difference_type value) noexcept {
- it += value;
- return *this;
- }
- constexpr resource_cache_iterator operator+(const difference_type value) const noexcept {
- resource_cache_iterator copy = *this;
- return (copy += value);
- }
- constexpr resource_cache_iterator &operator-=(const difference_type value) noexcept {
- return (*this += -value);
- }
- constexpr resource_cache_iterator operator-(const difference_type value) const noexcept {
- return (*this + -value);
- }
- [[nodiscard]] constexpr reference operator[](const difference_type value) const noexcept {
- return {it[value].first, resource<Type>{it[value].second}};
- }
- [[nodiscard]] constexpr reference operator*() const noexcept {
- return operator[](0);
- }
- [[nodiscard]] constexpr pointer operator->() const noexcept {
- return operator*();
- }
- template<typename... Lhs, typename... Rhs>
- friend constexpr std::ptrdiff_t operator-(const resource_cache_iterator<Lhs...> &, const resource_cache_iterator<Rhs...> &) noexcept;
- template<typename... Lhs, typename... Rhs>
- friend constexpr bool operator==(const resource_cache_iterator<Lhs...> &, const resource_cache_iterator<Rhs...> &) noexcept;
- template<typename... Lhs, typename... Rhs>
- friend constexpr bool operator<(const resource_cache_iterator<Lhs...> &, const resource_cache_iterator<Rhs...> &) noexcept;
- private:
- It it;
- };
- template<typename... Lhs, typename... Rhs>
- [[nodiscard]] constexpr std::ptrdiff_t operator-(const resource_cache_iterator<Lhs...> &lhs, const resource_cache_iterator<Rhs...> &rhs) noexcept {
- return lhs.it - rhs.it;
- }
- template<typename... Lhs, typename... Rhs>
- [[nodiscard]] constexpr bool operator==(const resource_cache_iterator<Lhs...> &lhs, const resource_cache_iterator<Rhs...> &rhs) noexcept {
- return lhs.it == rhs.it;
- }
- template<typename... Lhs, typename... Rhs>
- [[nodiscard]] constexpr bool operator!=(const resource_cache_iterator<Lhs...> &lhs, const resource_cache_iterator<Rhs...> &rhs) noexcept {
- return !(lhs == rhs);
- }
- template<typename... Lhs, typename... Rhs>
- [[nodiscard]] constexpr bool operator<(const resource_cache_iterator<Lhs...> &lhs, const resource_cache_iterator<Rhs...> &rhs) noexcept {
- return lhs.it < rhs.it;
- }
- template<typename... Lhs, typename... Rhs>
- [[nodiscard]] constexpr bool operator>(const resource_cache_iterator<Lhs...> &lhs, const resource_cache_iterator<Rhs...> &rhs) noexcept {
- return rhs < lhs;
- }
- template<typename... Lhs, typename... Rhs>
- [[nodiscard]] constexpr bool operator<=(const resource_cache_iterator<Lhs...> &lhs, const resource_cache_iterator<Rhs...> &rhs) noexcept {
- return !(lhs > rhs);
- }
- template<typename... Lhs, typename... Rhs>
- [[nodiscard]] constexpr bool operator>=(const resource_cache_iterator<Lhs...> &lhs, const resource_cache_iterator<Rhs...> &rhs) noexcept {
- return !(lhs < rhs);
- }
- } // namespace internal
- /*! @endcond */
- /**
- * @brief Basic cache for resources of any type.
- * @tparam Type Type of resources managed by a cache.
- * @tparam Loader Type of loader used to create the resources.
- * @tparam Allocator Type of allocator used to manage memory and elements.
- */
- template<typename Type, typename Loader, typename Allocator>
- class resource_cache {
- using alloc_traits = std::allocator_traits<Allocator>;
- static_assert(std::is_same_v<typename alloc_traits::value_type, Type>, "Invalid value type");
- using container_allocator = typename alloc_traits::template rebind_alloc<std::pair<const id_type, typename Loader::result_type>>;
- using container_type = dense_map<id_type, typename Loader::result_type, identity, std::equal_to<>, container_allocator>;
- public:
- /*! @brief Allocator type. */
- using allocator_type = Allocator;
- /*! @brief Resource type. */
- using value_type = Type;
- /*! @brief Unsigned integer type. */
- using size_type = std::size_t;
- /*! @brief Loader type. */
- using loader_type = Loader;
- /*! @brief Input iterator type. */
- using iterator = internal::resource_cache_iterator<Type, typename container_type::iterator>;
- /*! @brief Constant input iterator type. */
- using const_iterator = internal::resource_cache_iterator<const Type, typename container_type::const_iterator>;
- /*! @brief Default constructor. */
- resource_cache()
- : resource_cache{loader_type{}} {}
- /**
- * @brief Constructs an empty cache with a given allocator.
- * @param allocator The allocator to use.
- */
- explicit resource_cache(const allocator_type &allocator)
- : resource_cache{loader_type{}, allocator} {}
- /**
- * @brief Constructs an empty cache with a given allocator and loader.
- * @param callable The loader to use.
- * @param allocator The allocator to use.
- */
- explicit resource_cache(const loader_type &callable, const allocator_type &allocator = allocator_type{})
- : pool{container_type{allocator}, callable} {}
- /*! @brief Default copy constructor. */
- resource_cache(const resource_cache &) = default;
- /**
- * @brief Allocator-extended copy constructor.
- * @param other The instance to copy from.
- * @param allocator The allocator to use.
- */
- resource_cache(const resource_cache &other, const allocator_type &allocator)
- : pool{std::piecewise_construct, std::forward_as_tuple(other.pool.first(), allocator), std::forward_as_tuple(other.pool.second())} {}
- /*! @brief Default move constructor. */
- resource_cache(resource_cache &&) noexcept = default;
- /**
- * @brief Allocator-extended move constructor.
- * @param other The instance to move from.
- * @param allocator The allocator to use.
- */
- resource_cache(resource_cache &&other, const allocator_type &allocator)
- : pool{std::piecewise_construct, std::forward_as_tuple(std::move(other.pool.first()), allocator), std::forward_as_tuple(std::move(other.pool.second()))} {}
- /*! @brief Default destructor. */
- ~resource_cache() = default;
- /**
- * @brief Default copy assignment operator.
- * @return This cache.
- */
- resource_cache &operator=(const resource_cache &) = default;
- /**
- * @brief Default move assignment operator.
- * @return This cache.
- */
- resource_cache &operator=(resource_cache &&) noexcept = default;
- /**
- * @brief Returns the associated allocator.
- * @return The associated allocator.
- */
- [[nodiscard]] constexpr allocator_type get_allocator() const noexcept {
- return pool.first().get_allocator();
- }
- /**
- * @brief Returns an iterator to the beginning.
- *
- * If the cache is empty, the returned iterator will be equal to `end()`.
- *
- * @return An iterator to the first instance of the internal cache.
- */
- [[nodiscard]] const_iterator cbegin() const noexcept {
- return pool.first().begin();
- }
- /*! @copydoc cbegin */
- [[nodiscard]] const_iterator begin() const noexcept {
- return cbegin();
- }
- /*! @copydoc begin */
- [[nodiscard]] iterator begin() noexcept {
- return pool.first().begin();
- }
- /**
- * @brief Returns an iterator to the end.
- * @return An iterator to the element following the last instance of the
- * internal cache.
- */
- [[nodiscard]] const_iterator cend() const noexcept {
- return pool.first().end();
- }
- /*! @copydoc cend */
- [[nodiscard]] const_iterator end() const noexcept {
- return cend();
- }
- /*! @copydoc end */
- [[nodiscard]] iterator end() noexcept {
- return pool.first().end();
- }
- /**
- * @brief Returns true if a cache contains no resources, false otherwise.
- * @return True if the cache contains no resources, false otherwise.
- */
- [[nodiscard]] bool empty() const noexcept {
- return pool.first().empty();
- }
- /**
- * @brief Number of resources managed by a cache.
- * @return Number of resources currently stored.
- */
- [[nodiscard]] size_type size() const noexcept {
- return pool.first().size();
- }
- /*! @brief Clears a cache. */
- void clear() noexcept {
- pool.first().clear();
- }
- /**
- * @brief Loads a resource, if its identifier does not exist.
- *
- * Arguments are forwarded directly to the loader and _consumed_ only if the
- * resource doesn't already exist.
- *
- * @warning
- * If the resource isn't loaded correctly, the returned handle could be
- * invalid and any use of it will result in undefined behavior.
- *
- * @tparam Args Types of arguments to use to load the resource if required.
- * @param id Unique resource identifier.
- * @param args Arguments to use to load the resource if required.
- * @return A pair consisting of an iterator to the inserted element (or to
- * the element that prevented the insertion) and a bool denoting whether the
- * insertion took place.
- */
- template<typename... Args>
- std::pair<iterator, bool> load(const id_type id, Args &&...args) {
- if(auto it = pool.first().find(id); it != pool.first().end()) {
- return {it, false};
- }
- return pool.first().emplace(id, pool.second()(std::forward<Args>(args)...));
- }
- /**
- * @brief Force loads a resource, if its identifier does not exist.
- * @copydetails load
- */
- template<typename... Args>
- std::pair<iterator, bool> force_load(const id_type id, Args &&...args) {
- return {pool.first().insert_or_assign(id, pool.second()(std::forward<Args>(args)...)).first, true};
- }
- /**
- * @brief Returns a handle for a given resource identifier.
- *
- * @warning
- * There is no guarantee that the returned handle is valid.<br/>
- * If it is not, any use will result in indefinite behavior.
- *
- * @param id Unique resource identifier.
- * @return A handle for the given resource.
- */
- [[nodiscard]] resource<const value_type> operator[](const id_type id) const {
- if(auto it = pool.first().find(id); it != pool.first().cend()) {
- return resource<const value_type>{it->second};
- }
- return {};
- }
- /*! @copydoc operator[] */
- [[nodiscard]] resource<value_type> operator[](const id_type id) {
- if(auto it = pool.first().find(id); it != pool.first().end()) {
- return resource<value_type>{it->second};
- }
- return {};
- }
- /**
- * @brief Checks if a cache contains a given identifier.
- * @param id Unique resource identifier.
- * @return True if the cache contains the resource, false otherwise.
- */
- [[nodiscard]] bool contains(const id_type id) const {
- return pool.first().contains(id);
- }
- /**
- * @brief Removes an element from a given position.
- * @param pos An iterator to the element to remove.
- * @return An iterator following the removed element.
- */
- iterator erase(const_iterator pos) {
- const auto it = pool.first().begin();
- return pool.first().erase(it + (pos - const_iterator{it}));
- }
- /**
- * @brief Removes the given elements from a cache.
- * @param first An iterator to the first element of the range of elements.
- * @param last An iterator past the last element of the range of elements.
- * @return An iterator following the last removed element.
- */
- iterator erase(const_iterator first, const_iterator last) {
- const auto it = pool.first().begin();
- return pool.first().erase(it + (first - const_iterator{it}), it + (last - const_iterator{it}));
- }
- /**
- * @brief Removes the given elements from a cache.
- * @param id Unique resource identifier.
- * @return Number of resources erased (either 0 or 1).
- */
- size_type erase(const id_type id) {
- return pool.first().erase(id);
- }
- /**
- * @brief Returns the loader used to create resources.
- * @return The loader used to create resources.
- */
- [[nodiscard]] loader_type loader() const {
- return pool.second();
- }
- private:
- compressed_pair<container_type, loader_type> pool;
- };
- } // namespace entt
- #endif
- // #include "resource/loader.hpp"
- #ifndef ENTT_RESOURCE_LOADER_HPP
- #define ENTT_RESOURCE_LOADER_HPP
- #include <memory>
- #include <utility>
- // #include "fwd.hpp"
- namespace entt {
- /**
- * @brief Transparent loader for shared resources.
- * @tparam Type Type of resources created by the loader.
- */
- template<typename Type>
- struct resource_loader {
- /*! @brief Result type. */
- using result_type = std::shared_ptr<Type>;
- /**
- * @brief Constructs a shared pointer to a resource from its arguments.
- * @tparam Args Types of arguments to use to construct the resource.
- * @param args Parameters to use to construct the resource.
- * @return A shared pointer to a resource of the given type.
- */
- template<typename... Args>
- result_type operator()(Args &&...args) const {
- return std::make_shared<Type>(std::forward<Args>(args)...);
- }
- };
- } // namespace entt
- #endif
- // #include "resource/resource.hpp"
- #ifndef ENTT_RESOURCE_RESOURCE_HPP
- #define ENTT_RESOURCE_RESOURCE_HPP
- #include <memory>
- #include <type_traits>
- #include <utility>
- // #include "fwd.hpp"
- namespace entt {
- /**
- * @brief Basic resource handle.
- *
- * A handle wraps a resource and extends its lifetime. It also shares the same
- * resource with all other handles constructed from the same element.<br/>
- * As a rule of thumb, resources should never be copied nor moved. Handles are
- * the way to go to push references around.
- *
- * @tparam Type Type of resource managed by a handle.
- */
- template<typename Type>
- class resource {
- template<typename>
- friend class resource;
- template<typename Other>
- static constexpr bool is_acceptable = !std::is_same_v<Type, Other> && std::is_constructible_v<Type &, Other &>;
- public:
- /*! @brief Resource type. */
- using element_type = Type;
- /*! @brief Handle type. */
- using handle_type = std::shared_ptr<element_type>;
- /*! @brief Default constructor. */
- resource() noexcept
- : value{} {}
- /**
- * @brief Creates a new resource handle.
- * @param res A handle to a resource.
- */
- explicit resource(handle_type res) noexcept
- : value{std::move(res)} {}
- /*! @brief Default copy constructor. */
- resource(const resource &) noexcept = default;
- /*! @brief Default move constructor. */
- resource(resource &&) noexcept = default;
- /**
- * @brief Aliasing constructor.
- * @tparam Other Type of resource managed by the received handle.
- * @param other The handle with which to share ownership information.
- * @param res Unrelated and unmanaged resources.
- */
- template<typename Other>
- resource(const resource<Other> &other, element_type &res) noexcept
- : value{other.value, std::addressof(res)} {}
- /**
- * @brief Copy constructs a handle which shares ownership of the resource.
- * @tparam Other Type of resource managed by the received handle.
- * @param other The handle to copy from.
- */
- template<typename Other, typename = std::enable_if_t<is_acceptable<Other>>>
- resource(const resource<Other> &other) noexcept
- : value{other.value} {}
- /**
- * @brief Move constructs a handle which takes ownership of the resource.
- * @tparam Other Type of resource managed by the received handle.
- * @param other The handle to move from.
- */
- template<typename Other, typename = std::enable_if_t<is_acceptable<Other>>>
- resource(resource<Other> &&other) noexcept
- : value{std::move(other.value)} {}
- /*! @brief Default destructor. */
- ~resource() = default;
- /**
- * @brief Default copy assignment operator.
- * @return This resource handle.
- */
- resource &operator=(const resource &) noexcept = default;
- /**
- * @brief Default move assignment operator.
- * @return This resource handle.
- */
- resource &operator=(resource &&) noexcept = default;
- /**
- * @brief Copy assignment operator from foreign handle.
- * @tparam Other Type of resource managed by the received handle.
- * @param other The handle to copy from.
- * @return This resource handle.
- */
- template<typename Other, typename = std::enable_if_t<is_acceptable<Other>>>
- resource &operator=(const resource<Other> &other) noexcept {
- value = other.value;
- return *this;
- }
- /**
- * @brief Move assignment operator from foreign handle.
- * @tparam Other Type of resource managed by the received handle.
- * @param other The handle to move from.
- * @return This resource handle.
- */
- template<typename Other, typename = std::enable_if_t<is_acceptable<Other>>>
- resource &operator=(resource<Other> &&other) noexcept {
- value = std::move(other.value);
- return *this;
- }
- /**
- * @brief Exchanges the content with that of a given resource.
- * @param other Resource to exchange the content with.
- */
- void swap(resource &other) noexcept {
- using std::swap;
- swap(value, other.value);
- }
- /**
- * @brief Returns a reference to the managed resource.
- *
- * @warning
- * The behavior is undefined if the handle doesn't contain a resource.
- *
- * @return A reference to the managed resource.
- */
- [[nodiscard]] element_type &operator*() const noexcept {
- return *value;
- }
- /*! @copydoc operator* */
- [[nodiscard]] operator element_type &() const noexcept {
- return *value;
- }
- /**
- * @brief Returns a pointer to the managed resource.
- * @return A pointer to the managed resource.
- */
- [[nodiscard]] element_type *operator->() const noexcept {
- return value.get();
- }
- /**
- * @brief Returns true if a handle contains a resource, false otherwise.
- * @return True if the handle contains a resource, false otherwise.
- */
- [[nodiscard]] explicit operator bool() const noexcept {
- return static_cast<bool>(value);
- }
- /*! @brief Releases the ownership of the managed resource. */
- void reset() {
- value.reset();
- }
- /**
- * @brief Replaces the managed resource.
- * @param other A handle to a resource.
- */
- void reset(handle_type other) {
- value = std::move(other);
- }
- /**
- * @brief Returns the underlying resource handle.
- * @return The underlying resource handle.
- */
- [[nodiscard]] handle_type handle() const noexcept {
- return value;
- }
- private:
- handle_type value;
- };
- /**
- * @brief Compares two handles.
- * @tparam Lhs Type of resource managed by the first handle.
- * @tparam Rhs Type of resource managed by the second handle.
- * @param lhs A valid handle.
- * @param rhs A valid handle.
- * @return True if both handles refer to the same resource, false otherwise.
- */
- template<typename Lhs, typename Rhs>
- [[nodiscard]] bool operator==(const resource<Lhs> &lhs, const resource<Rhs> &rhs) noexcept {
- return (std::addressof(*lhs) == std::addressof(*rhs));
- }
- /**
- * @brief Compares two handles.
- * @tparam Lhs Type of resource managed by the first handle.
- * @tparam Rhs Type of resource managed by the second handle.
- * @param lhs A valid handle.
- * @param rhs A valid handle.
- * @return False if both handles refer to the same resource, true otherwise.
- */
- template<typename Lhs, typename Rhs>
- [[nodiscard]] bool operator!=(const resource<Lhs> &lhs, const resource<Rhs> &rhs) noexcept {
- return !(lhs == rhs);
- }
- /**
- * @brief Compares two handles.
- * @tparam Lhs Type of resource managed by the first handle.
- * @tparam Rhs Type of resource managed by the second handle.
- * @param lhs A valid handle.
- * @param rhs A valid handle.
- * @return True if the first handle is less than the second, false otherwise.
- */
- template<typename Lhs, typename Rhs>
- [[nodiscard]] bool operator<(const resource<Lhs> &lhs, const resource<Rhs> &rhs) noexcept {
- return (std::addressof(*lhs) < std::addressof(*rhs));
- }
- /**
- * @brief Compares two handles.
- * @tparam Lhs Type of resource managed by the first handle.
- * @tparam Rhs Type of resource managed by the second handle.
- * @param lhs A valid handle.
- * @param rhs A valid handle.
- * @return True if the first handle is greater than the second, false otherwise.
- */
- template<typename Lhs, typename Rhs>
- [[nodiscard]] bool operator>(const resource<Lhs> &lhs, const resource<Rhs> &rhs) noexcept {
- return rhs < lhs;
- }
- /**
- * @brief Compares two handles.
- * @tparam Lhs Type of resource managed by the first handle.
- * @tparam Rhs Type of resource managed by the second handle.
- * @param lhs A valid handle.
- * @param rhs A valid handle.
- * @return True if the first handle is less than or equal to the second, false
- * otherwise.
- */
- template<typename Lhs, typename Rhs>
- [[nodiscard]] bool operator<=(const resource<Lhs> &lhs, const resource<Rhs> &rhs) noexcept {
- return !(lhs > rhs);
- }
- /**
- * @brief Compares two handles.
- * @tparam Lhs Type of resource managed by the first handle.
- * @tparam Rhs Type of resource managed by the second handle.
- * @param lhs A valid handle.
- * @param rhs A valid handle.
- * @return True if the first handle is greater than or equal to the second,
- * false otherwise.
- */
- template<typename Lhs, typename Rhs>
- [[nodiscard]] bool operator>=(const resource<Lhs> &lhs, const resource<Rhs> &rhs) noexcept {
- return !(lhs < rhs);
- }
- } // namespace entt
- #endif
- // #include "signal/delegate.hpp"
- #ifndef ENTT_SIGNAL_DELEGATE_HPP
- #define ENTT_SIGNAL_DELEGATE_HPP
- #include <cstddef>
- #include <functional>
- #include <tuple>
- #include <type_traits>
- #include <utility>
- // #include "../config/config.h"
- #ifndef ENTT_CONFIG_CONFIG_H
- #define ENTT_CONFIG_CONFIG_H
- // #include "version.h"
- #ifndef ENTT_CONFIG_VERSION_H
- #define ENTT_CONFIG_VERSION_H
- // #include "macro.h"
- #ifndef ENTT_CONFIG_MACRO_H
- #define ENTT_CONFIG_MACRO_H
- // NOLINTBEGIN(cppcoreguidelines-macro-usage)
- #define ENTT_STR(arg) #arg
- #define ENTT_XSTR(arg) ENTT_STR(arg)
- // NOLINTEND(cppcoreguidelines-macro-usage)
- #endif
- // NOLINTBEGIN(cppcoreguidelines-macro-*,modernize-macro-*)
- #define ENTT_VERSION_MAJOR 3
- #define ENTT_VERSION_MINOR 16
- #define ENTT_VERSION_PATCH 0
- #define ENTT_VERSION \
- ENTT_XSTR(ENTT_VERSION_MAJOR) \
- "." ENTT_XSTR(ENTT_VERSION_MINOR) "." ENTT_XSTR(ENTT_VERSION_PATCH)
- // NOLINTEND(cppcoreguidelines-macro-*,modernize-macro-*)
- #endif
- // NOLINTBEGIN(cppcoreguidelines-macro-usage)
- #if defined(__cpp_exceptions) && !defined(ENTT_NOEXCEPTION)
- # define ENTT_CONSTEXPR
- # define ENTT_THROW throw
- # define ENTT_TRY try
- # define ENTT_CATCH catch(...)
- #else
- # define ENTT_CONSTEXPR constexpr // use only with throwing functions (waiting for C++20)
- # define ENTT_THROW
- # define ENTT_TRY if(true)
- # define ENTT_CATCH if(false)
- #endif
- #if __has_include(<version>)
- # include <version>
- #
- # if defined(__cpp_consteval)
- # define ENTT_CONSTEVAL consteval
- # endif
- #endif
- #ifndef ENTT_CONSTEVAL
- # define ENTT_CONSTEVAL constexpr
- #endif
- #ifdef ENTT_USE_ATOMIC
- # include <atomic>
- # define ENTT_MAYBE_ATOMIC(Type) std::atomic<Type>
- #else
- # define ENTT_MAYBE_ATOMIC(Type) Type
- #endif
- #ifndef ENTT_ID_TYPE
- # include <cstdint>
- # define ENTT_ID_TYPE std::uint32_t
- #else
- # include <cstdint> // provides coverage for types in the std namespace
- #endif
- #ifndef ENTT_SPARSE_PAGE
- # define ENTT_SPARSE_PAGE 4096
- #endif
- #ifndef ENTT_PACKED_PAGE
- # define ENTT_PACKED_PAGE 1024
- #endif
- #ifdef ENTT_DISABLE_ASSERT
- # undef ENTT_ASSERT
- # define ENTT_ASSERT(condition, msg) (void(0))
- #elif !defined ENTT_ASSERT
- # include <cassert>
- # define ENTT_ASSERT(condition, msg) assert(((condition) && (msg)))
- #endif
- #ifdef ENTT_DISABLE_ASSERT
- # undef ENTT_ASSERT_CONSTEXPR
- # define ENTT_ASSERT_CONSTEXPR(condition, msg) (void(0))
- #elif !defined ENTT_ASSERT_CONSTEXPR
- # define ENTT_ASSERT_CONSTEXPR(condition, msg) ENTT_ASSERT(condition, msg)
- #endif
- #define ENTT_FAIL(msg) ENTT_ASSERT(false, msg);
- #ifdef ENTT_NO_ETO
- # define ENTT_ETO_TYPE(Type) void
- #else
- # define ENTT_ETO_TYPE(Type) Type
- #endif
- #ifdef ENTT_NO_MIXIN
- # define ENTT_STORAGE(Mixin, ...) __VA_ARGS__
- #else
- # define ENTT_STORAGE(Mixin, ...) Mixin<__VA_ARGS__>
- #endif
- #ifdef ENTT_STANDARD_CPP
- # define ENTT_NONSTD false
- #else
- # define ENTT_NONSTD true
- # if defined __clang__ || defined __GNUC__
- # define ENTT_PRETTY_FUNCTION __PRETTY_FUNCTION__
- # define ENTT_PRETTY_FUNCTION_PREFIX '='
- # define ENTT_PRETTY_FUNCTION_SUFFIX ']'
- # elif defined _MSC_VER
- # define ENTT_PRETTY_FUNCTION __FUNCSIG__
- # define ENTT_PRETTY_FUNCTION_PREFIX '<'
- # define ENTT_PRETTY_FUNCTION_SUFFIX '>'
- # endif
- #endif
- #ifndef ENTT_EXPORT
- # if defined _WIN32 || defined __CYGWIN__ || defined _MSC_VER
- # define ENTT_EXPORT __declspec(dllexport)
- # define ENTT_IMPORT __declspec(dllimport)
- # define ENTT_HIDDEN
- # elif defined __GNUC__ && __GNUC__ >= 4
- # define ENTT_EXPORT __attribute__((visibility("default")))
- # define ENTT_IMPORT __attribute__((visibility("default")))
- # define ENTT_HIDDEN __attribute__((visibility("hidden")))
- # else /* Unsupported compiler */
- # define ENTT_EXPORT
- # define ENTT_IMPORT
- # define ENTT_HIDDEN
- # endif
- #endif
- #ifndef ENTT_API
- # if defined ENTT_API_EXPORT
- # define ENTT_API ENTT_EXPORT
- # elif defined ENTT_API_IMPORT
- # define ENTT_API ENTT_IMPORT
- # else /* No API */
- # define ENTT_API
- # endif
- #endif
- #if defined _MSC_VER
- # pragma detect_mismatch("entt.version", ENTT_VERSION)
- # pragma detect_mismatch("entt.noexcept", ENTT_XSTR(ENTT_TRY))
- # pragma detect_mismatch("entt.id", ENTT_XSTR(ENTT_ID_TYPE))
- # pragma detect_mismatch("entt.nonstd", ENTT_XSTR(ENTT_NONSTD))
- #endif
- // NOLINTEND(cppcoreguidelines-macro-usage)
- #endif
- // #include "../core/type_traits.hpp"
- #ifndef ENTT_CORE_TYPE_TRAITS_HPP
- #define ENTT_CORE_TYPE_TRAITS_HPP
- #include <cstddef>
- #include <iterator>
- #include <tuple>
- #include <type_traits>
- #include <utility>
- // #include "../config/config.h"
- #ifndef ENTT_CONFIG_CONFIG_H
- #define ENTT_CONFIG_CONFIG_H
- // #include "version.h"
- #ifndef ENTT_CONFIG_VERSION_H
- #define ENTT_CONFIG_VERSION_H
- // #include "macro.h"
- #ifndef ENTT_CONFIG_MACRO_H
- #define ENTT_CONFIG_MACRO_H
- // NOLINTBEGIN(cppcoreguidelines-macro-usage)
- #define ENTT_STR(arg) #arg
- #define ENTT_XSTR(arg) ENTT_STR(arg)
- // NOLINTEND(cppcoreguidelines-macro-usage)
- #endif
- // NOLINTBEGIN(cppcoreguidelines-macro-*,modernize-macro-*)
- #define ENTT_VERSION_MAJOR 3
- #define ENTT_VERSION_MINOR 16
- #define ENTT_VERSION_PATCH 0
- #define ENTT_VERSION \
- ENTT_XSTR(ENTT_VERSION_MAJOR) \
- "." ENTT_XSTR(ENTT_VERSION_MINOR) "." ENTT_XSTR(ENTT_VERSION_PATCH)
- // NOLINTEND(cppcoreguidelines-macro-*,modernize-macro-*)
- #endif
- // NOLINTBEGIN(cppcoreguidelines-macro-usage)
- #if defined(__cpp_exceptions) && !defined(ENTT_NOEXCEPTION)
- # define ENTT_CONSTEXPR
- # define ENTT_THROW throw
- # define ENTT_TRY try
- # define ENTT_CATCH catch(...)
- #else
- # define ENTT_CONSTEXPR constexpr // use only with throwing functions (waiting for C++20)
- # define ENTT_THROW
- # define ENTT_TRY if(true)
- # define ENTT_CATCH if(false)
- #endif
- #if __has_include(<version>)
- # include <version>
- #
- # if defined(__cpp_consteval)
- # define ENTT_CONSTEVAL consteval
- # endif
- #endif
- #ifndef ENTT_CONSTEVAL
- # define ENTT_CONSTEVAL constexpr
- #endif
- #ifdef ENTT_USE_ATOMIC
- # include <atomic>
- # define ENTT_MAYBE_ATOMIC(Type) std::atomic<Type>
- #else
- # define ENTT_MAYBE_ATOMIC(Type) Type
- #endif
- #ifndef ENTT_ID_TYPE
- # include <cstdint>
- # define ENTT_ID_TYPE std::uint32_t
- #else
- # include <cstdint> // provides coverage for types in the std namespace
- #endif
- #ifndef ENTT_SPARSE_PAGE
- # define ENTT_SPARSE_PAGE 4096
- #endif
- #ifndef ENTT_PACKED_PAGE
- # define ENTT_PACKED_PAGE 1024
- #endif
- #ifdef ENTT_DISABLE_ASSERT
- # undef ENTT_ASSERT
- # define ENTT_ASSERT(condition, msg) (void(0))
- #elif !defined ENTT_ASSERT
- # include <cassert>
- # define ENTT_ASSERT(condition, msg) assert(((condition) && (msg)))
- #endif
- #ifdef ENTT_DISABLE_ASSERT
- # undef ENTT_ASSERT_CONSTEXPR
- # define ENTT_ASSERT_CONSTEXPR(condition, msg) (void(0))
- #elif !defined ENTT_ASSERT_CONSTEXPR
- # define ENTT_ASSERT_CONSTEXPR(condition, msg) ENTT_ASSERT(condition, msg)
- #endif
- #define ENTT_FAIL(msg) ENTT_ASSERT(false, msg);
- #ifdef ENTT_NO_ETO
- # define ENTT_ETO_TYPE(Type) void
- #else
- # define ENTT_ETO_TYPE(Type) Type
- #endif
- #ifdef ENTT_NO_MIXIN
- # define ENTT_STORAGE(Mixin, ...) __VA_ARGS__
- #else
- # define ENTT_STORAGE(Mixin, ...) Mixin<__VA_ARGS__>
- #endif
- #ifdef ENTT_STANDARD_CPP
- # define ENTT_NONSTD false
- #else
- # define ENTT_NONSTD true
- # if defined __clang__ || defined __GNUC__
- # define ENTT_PRETTY_FUNCTION __PRETTY_FUNCTION__
- # define ENTT_PRETTY_FUNCTION_PREFIX '='
- # define ENTT_PRETTY_FUNCTION_SUFFIX ']'
- # elif defined _MSC_VER
- # define ENTT_PRETTY_FUNCTION __FUNCSIG__
- # define ENTT_PRETTY_FUNCTION_PREFIX '<'
- # define ENTT_PRETTY_FUNCTION_SUFFIX '>'
- # endif
- #endif
- #ifndef ENTT_EXPORT
- # if defined _WIN32 || defined __CYGWIN__ || defined _MSC_VER
- # define ENTT_EXPORT __declspec(dllexport)
- # define ENTT_IMPORT __declspec(dllimport)
- # define ENTT_HIDDEN
- # elif defined __GNUC__ && __GNUC__ >= 4
- # define ENTT_EXPORT __attribute__((visibility("default")))
- # define ENTT_IMPORT __attribute__((visibility("default")))
- # define ENTT_HIDDEN __attribute__((visibility("hidden")))
- # else /* Unsupported compiler */
- # define ENTT_EXPORT
- # define ENTT_IMPORT
- # define ENTT_HIDDEN
- # endif
- #endif
- #ifndef ENTT_API
- # if defined ENTT_API_EXPORT
- # define ENTT_API ENTT_EXPORT
- # elif defined ENTT_API_IMPORT
- # define ENTT_API ENTT_IMPORT
- # else /* No API */
- # define ENTT_API
- # endif
- #endif
- #if defined _MSC_VER
- # pragma detect_mismatch("entt.version", ENTT_VERSION)
- # pragma detect_mismatch("entt.noexcept", ENTT_XSTR(ENTT_TRY))
- # pragma detect_mismatch("entt.id", ENTT_XSTR(ENTT_ID_TYPE))
- # pragma detect_mismatch("entt.nonstd", ENTT_XSTR(ENTT_NONSTD))
- #endif
- // NOLINTEND(cppcoreguidelines-macro-usage)
- #endif
- // #include "fwd.hpp"
- #ifndef ENTT_CORE_FWD_HPP
- #define ENTT_CORE_FWD_HPP
- #include <cstddef>
- #include <cstdint>
- // #include "../config/config.h"
- namespace entt {
- /*! @brief Possible modes of an any object. */
- enum class any_policy : std::uint8_t {
- /*! @brief Default mode, no element available. */
- empty,
- /*! @brief Owning mode, dynamically allocated element. */
- dynamic,
- /*! @brief Owning mode, embedded element. */
- embedded,
- /*! @brief Aliasing mode, non-const reference. */
- ref,
- /*! @brief Const aliasing mode, const reference. */
- cref
- };
- // NOLINTNEXTLINE(cppcoreguidelines-avoid-c-arrays, modernize-avoid-c-arrays)
- template<std::size_t Len = sizeof(double[2]), std::size_t = alignof(double[2])>
- class basic_any;
- /*! @brief Alias declaration for type identifiers. */
- using id_type = ENTT_ID_TYPE;
- /*! @brief Alias declaration for the most common use case. */
- using any = basic_any<>;
- template<typename, typename>
- class compressed_pair;
- template<typename>
- class basic_hashed_string;
- /*! @brief Aliases for common character types. */
- using hashed_string = basic_hashed_string<char>;
- /*! @brief Aliases for common character types. */
- using hashed_wstring = basic_hashed_string<wchar_t>;
- // NOLINTNEXTLINE(bugprone-forward-declaration-namespace)
- struct type_info;
- } // namespace entt
- #endif
- namespace entt {
- /**
- * @brief Utility class to disambiguate overloaded functions.
- * @tparam N Number of choices available.
- */
- template<std::size_t N>
- struct choice_t
- // unfortunately, doxygen cannot parse such a construct
- : /*! @cond TURN_OFF_DOXYGEN */ choice_t<N - 1> /*! @endcond */
- {};
- /*! @copybrief choice_t */
- template<>
- struct choice_t<0> {};
- /**
- * @brief Variable template for the choice trick.
- * @tparam N Number of choices available.
- */
- template<std::size_t N>
- inline constexpr choice_t<N> choice{};
- /**
- * @brief Identity type trait.
- *
- * Useful to establish non-deduced contexts in template argument deduction
- * (waiting for C++20) or to provide types through function arguments.
- *
- * @tparam Type A type.
- */
- template<typename Type>
- struct type_identity {
- /*! @brief Identity type. */
- using type = Type;
- };
- /**
- * @brief Helper type.
- * @tparam Type A type.
- */
- template<typename Type>
- using type_identity_t = typename type_identity<Type>::type;
- /**
- * @brief A type-only `sizeof` wrapper that returns 0 where `sizeof` complains.
- * @tparam Type The type of which to return the size.
- */
- template<typename Type, typename = void>
- struct size_of: std::integral_constant<std::size_t, 0u> {};
- /*! @copydoc size_of */
- template<typename Type>
- struct size_of<Type, std::void_t<decltype(sizeof(Type))>>
- // NOLINTNEXTLINE(bugprone-sizeof-expression)
- : std::integral_constant<std::size_t, sizeof(Type)> {};
- /**
- * @brief Helper variable template.
- * @tparam Type The type of which to return the size.
- */
- template<typename Type>
- inline constexpr std::size_t size_of_v = size_of<Type>::value;
- /**
- * @brief Using declaration to be used to _repeat_ the same type a number of
- * times equal to the size of a given parameter pack.
- * @tparam Type A type to repeat.
- */
- template<typename Type, typename>
- using unpack_as_type = Type;
- /**
- * @brief Helper variable template to be used to _repeat_ the same value a
- * number of times equal to the size of a given parameter pack.
- * @tparam Value A value to repeat.
- */
- template<auto Value, typename>
- inline constexpr auto unpack_as_value = Value;
- /**
- * @brief Wraps a static constant.
- * @tparam Value A static constant.
- */
- template<auto Value>
- using integral_constant = std::integral_constant<decltype(Value), Value>;
- /**
- * @brief Alias template to facilitate the creation of named values.
- * @tparam Value A constant value at least convertible to `id_type`.
- */
- template<id_type Value>
- using tag = integral_constant<Value>;
- /**
- * @brief A class to use to push around lists of types, nothing more.
- * @tparam Type Types provided by the type list.
- */
- template<typename... Type>
- struct type_list {
- /*! @brief Type list type. */
- using type = type_list;
- /*! @brief Compile-time number of elements in the type list. */
- static constexpr auto size = sizeof...(Type);
- };
- /*! @brief Primary template isn't defined on purpose. */
- template<std::size_t, typename>
- struct type_list_element;
- /**
- * @brief Provides compile-time indexed access to the types of a type list.
- * @tparam Index Index of the type to return.
- * @tparam First First type provided by the type list.
- * @tparam Other Other types provided by the type list.
- */
- template<std::size_t Index, typename First, typename... Other>
- struct type_list_element<Index, type_list<First, Other...>>
- : type_list_element<Index - 1u, type_list<Other...>> {};
- /**
- * @brief Provides compile-time indexed access to the types of a type list.
- * @tparam First First type provided by the type list.
- * @tparam Other Other types provided by the type list.
- */
- template<typename First, typename... Other>
- struct type_list_element<0u, type_list<First, Other...>> {
- /*! @brief Searched type. */
- using type = First;
- };
- /**
- * @brief Helper type.
- * @tparam Index Index of the type to return.
- * @tparam List Type list to search into.
- */
- template<std::size_t Index, typename List>
- using type_list_element_t = typename type_list_element<Index, List>::type;
- /*! @brief Primary template isn't defined on purpose. */
- template<typename, typename>
- struct type_list_index;
- /**
- * @brief Provides compile-time type access to the types of a type list.
- * @tparam Type Type to look for and for which to return the index.
- * @tparam First First type provided by the type list.
- * @tparam Other Other types provided by the type list.
- */
- template<typename Type, typename First, typename... Other>
- struct type_list_index<Type, type_list<First, Other...>> {
- /*! @brief Unsigned integer type. */
- using value_type = std::size_t;
- /*! @brief Compile-time position of the given type in the sublist. */
- static constexpr value_type value = 1u + type_list_index<Type, type_list<Other...>>::value;
- };
- /**
- * @brief Provides compile-time type access to the types of a type list.
- * @tparam Type Type to look for and for which to return the index.
- * @tparam Other Other types provided by the type list.
- */
- template<typename Type, typename... Other>
- struct type_list_index<Type, type_list<Type, Other...>> {
- static_assert(type_list_index<Type, type_list<Other...>>::value == sizeof...(Other), "Non-unique type");
- /*! @brief Unsigned integer type. */
- using value_type = std::size_t;
- /*! @brief Compile-time position of the given type in the sublist. */
- static constexpr value_type value = 0u;
- };
- /**
- * @brief Provides compile-time type access to the types of a type list.
- * @tparam Type Type to look for and for which to return the index.
- */
- template<typename Type>
- struct type_list_index<Type, type_list<>> {
- /*! @brief Unsigned integer type. */
- using value_type = std::size_t;
- /*! @brief Compile-time position of the given type in the sublist. */
- static constexpr value_type value = 0u;
- };
- /**
- * @brief Helper variable template.
- * @tparam List Type list.
- * @tparam Type Type to look for and for which to return the index.
- */
- template<typename Type, typename List>
- inline constexpr std::size_t type_list_index_v = type_list_index<Type, List>::value;
- /**
- * @brief Concatenates multiple type lists.
- * @tparam Type Types provided by the first type list.
- * @tparam Other Types provided by the second type list.
- * @return A type list composed by the types of both the type lists.
- */
- template<typename... Type, typename... Other>
- constexpr type_list<Type..., Other...> operator+(type_list<Type...>, type_list<Other...>) {
- return {};
- }
- /*! @brief Primary template isn't defined on purpose. */
- template<typename...>
- struct type_list_cat;
- /*! @brief Concatenates multiple type lists. */
- template<>
- struct type_list_cat<> {
- /*! @brief A type list composed by the types of all the type lists. */
- using type = type_list<>;
- };
- /**
- * @brief Concatenates multiple type lists.
- * @tparam Type Types provided by the first type list.
- * @tparam Other Types provided by the second type list.
- * @tparam List Other type lists, if any.
- */
- template<typename... Type, typename... Other, typename... List>
- struct type_list_cat<type_list<Type...>, type_list<Other...>, List...> {
- /*! @brief A type list composed by the types of all the type lists. */
- using type = typename type_list_cat<type_list<Type..., Other...>, List...>::type;
- };
- /**
- * @brief Concatenates multiple type lists.
- * @tparam Type Types provided by the type list.
- */
- template<typename... Type>
- struct type_list_cat<type_list<Type...>> {
- /*! @brief A type list composed by the types of all the type lists. */
- using type = type_list<Type...>;
- };
- /**
- * @brief Helper type.
- * @tparam List Type lists to concatenate.
- */
- template<typename... List>
- using type_list_cat_t = typename type_list_cat<List...>::type;
- /*! @cond TURN_OFF_DOXYGEN */
- namespace internal {
- template<typename...>
- struct type_list_unique;
- template<typename First, typename... Other, typename... Type>
- struct type_list_unique<type_list<First, Other...>, Type...>
- : std::conditional_t<(std::is_same_v<First, Type> || ...), type_list_unique<type_list<Other...>, Type...>, type_list_unique<type_list<Other...>, Type..., First>> {};
- template<typename... Type>
- struct type_list_unique<type_list<>, Type...> {
- using type = type_list<Type...>;
- };
- } // namespace internal
- /*! @endcond */
- /**
- * @brief Removes duplicates types from a type list.
- * @tparam List Type list.
- */
- template<typename List>
- struct type_list_unique {
- /*! @brief A type list without duplicate types. */
- using type = typename internal::type_list_unique<List>::type;
- };
- /**
- * @brief Helper type.
- * @tparam List Type list.
- */
- template<typename List>
- using type_list_unique_t = typename type_list_unique<List>::type;
- /**
- * @brief Provides the member constant `value` to true if a type list contains a
- * given type, false otherwise.
- * @tparam List Type list.
- * @tparam Type Type to look for.
- */
- template<typename List, typename Type>
- struct type_list_contains;
- /**
- * @copybrief type_list_contains
- * @tparam Type Types provided by the type list.
- * @tparam Other Type to look for.
- */
- template<typename... Type, typename Other>
- struct type_list_contains<type_list<Type...>, Other>
- : std::bool_constant<(std::is_same_v<Type, Other> || ...)> {};
- /**
- * @brief Helper variable template.
- * @tparam List Type list.
- * @tparam Type Type to look for.
- */
- template<typename List, typename Type>
- inline constexpr bool type_list_contains_v = type_list_contains<List, Type>::value;
- /*! @brief Primary template isn't defined on purpose. */
- template<typename...>
- struct type_list_diff;
- /**
- * @brief Computes the difference between two type lists.
- * @tparam Type Types provided by the first type list.
- * @tparam Other Types provided by the second type list.
- */
- template<typename... Type, typename... Other>
- struct type_list_diff<type_list<Type...>, type_list<Other...>> {
- /*! @brief A type list that is the difference between the two type lists. */
- using type = type_list_cat_t<std::conditional_t<type_list_contains_v<type_list<Other...>, Type>, type_list<>, type_list<Type>>...>;
- };
- /**
- * @brief Helper type.
- * @tparam List Type lists between which to compute the difference.
- */
- template<typename... List>
- using type_list_diff_t = typename type_list_diff<List...>::type;
- /*! @brief Primary template isn't defined on purpose. */
- template<typename, template<typename...> class>
- struct type_list_transform;
- /**
- * @brief Applies a given _function_ to a type list and generate a new list.
- * @tparam Type Types provided by the type list.
- * @tparam Op Unary operation as template class with a type member named `type`.
- */
- template<typename... Type, template<typename...> class Op>
- struct type_list_transform<type_list<Type...>, Op> {
- /*! @brief Resulting type list after applying the transform function. */
- // NOLINTNEXTLINE(modernize-type-traits)
- using type = type_list<typename Op<Type>::type...>;
- };
- /**
- * @brief Helper type.
- * @tparam List Type list.
- * @tparam Op Unary operation as template class with a type member named `type`.
- */
- template<typename List, template<typename...> class Op>
- using type_list_transform_t = typename type_list_transform<List, Op>::type;
- /**
- * @brief A class to use to push around lists of constant values, nothing more.
- * @tparam Value Values provided by the value list.
- */
- template<auto... Value>
- struct value_list {
- /*! @brief Value list type. */
- using type = value_list;
- /*! @brief Compile-time number of elements in the value list. */
- static constexpr auto size = sizeof...(Value);
- };
- /*! @brief Primary template isn't defined on purpose. */
- template<std::size_t, typename>
- struct value_list_element;
- /**
- * @brief Provides compile-time indexed access to the values of a value list.
- * @tparam Index Index of the value to return.
- * @tparam Value First value provided by the value list.
- * @tparam Other Other values provided by the value list.
- */
- template<std::size_t Index, auto Value, auto... Other>
- struct value_list_element<Index, value_list<Value, Other...>>
- : value_list_element<Index - 1u, value_list<Other...>> {};
- /**
- * @brief Provides compile-time indexed access to the types of a type list.
- * @tparam Value First value provided by the value list.
- * @tparam Other Other values provided by the value list.
- */
- template<auto Value, auto... Other>
- struct value_list_element<0u, value_list<Value, Other...>> {
- /*! @brief Searched type. */
- using type = decltype(Value);
- /*! @brief Searched value. */
- static constexpr auto value = Value;
- };
- /**
- * @brief Helper type.
- * @tparam Index Index of the type to return.
- * @tparam List Value list to search into.
- */
- template<std::size_t Index, typename List>
- using value_list_element_t = typename value_list_element<Index, List>::type;
- /**
- * @brief Helper type.
- * @tparam Index Index of the value to return.
- * @tparam List Value list to search into.
- */
- template<std::size_t Index, typename List>
- inline constexpr auto value_list_element_v = value_list_element<Index, List>::value;
- /*! @brief Primary template isn't defined on purpose. */
- template<auto, typename>
- struct value_list_index;
- /**
- * @brief Provides compile-time type access to the values of a value list.
- * @tparam Value Value to look for and for which to return the index.
- * @tparam First First value provided by the value list.
- * @tparam Other Other values provided by the value list.
- */
- template<auto Value, auto First, auto... Other>
- struct value_list_index<Value, value_list<First, Other...>> {
- /*! @brief Unsigned integer type. */
- using value_type = std::size_t;
- /*! @brief Compile-time position of the given value in the sublist. */
- static constexpr value_type value = 1u + value_list_index<Value, value_list<Other...>>::value;
- };
- /**
- * @brief Provides compile-time type access to the values of a value list.
- * @tparam Value Value to look for and for which to return the index.
- * @tparam Other Other values provided by the value list.
- */
- template<auto Value, auto... Other>
- struct value_list_index<Value, value_list<Value, Other...>> {
- static_assert(value_list_index<Value, value_list<Other...>>::value == sizeof...(Other), "Non-unique type");
- /*! @brief Unsigned integer type. */
- using value_type = std::size_t;
- /*! @brief Compile-time position of the given value in the sublist. */
- static constexpr value_type value = 0u;
- };
- /**
- * @brief Provides compile-time type access to the values of a value list.
- * @tparam Value Value to look for and for which to return the index.
- */
- template<auto Value>
- struct value_list_index<Value, value_list<>> {
- /*! @brief Unsigned integer type. */
- using value_type = std::size_t;
- /*! @brief Compile-time position of the given type in the sublist. */
- static constexpr value_type value = 0u;
- };
- /**
- * @brief Helper variable template.
- * @tparam List Value list.
- * @tparam Value Value to look for and for which to return the index.
- */
- template<auto Value, typename List>
- inline constexpr std::size_t value_list_index_v = value_list_index<Value, List>::value;
- /**
- * @brief Concatenates multiple value lists.
- * @tparam Value Values provided by the first value list.
- * @tparam Other Values provided by the second value list.
- * @return A value list composed by the values of both the value lists.
- */
- template<auto... Value, auto... Other>
- constexpr value_list<Value..., Other...> operator+(value_list<Value...>, value_list<Other...>) {
- return {};
- }
- /*! @brief Primary template isn't defined on purpose. */
- template<typename...>
- struct value_list_cat;
- /*! @brief Concatenates multiple value lists. */
- template<>
- struct value_list_cat<> {
- /*! @brief A value list composed by the values of all the value lists. */
- using type = value_list<>;
- };
- /**
- * @brief Concatenates multiple value lists.
- * @tparam Value Values provided by the first value list.
- * @tparam Other Values provided by the second value list.
- * @tparam List Other value lists, if any.
- */
- template<auto... Value, auto... Other, typename... List>
- struct value_list_cat<value_list<Value...>, value_list<Other...>, List...> {
- /*! @brief A value list composed by the values of all the value lists. */
- using type = typename value_list_cat<value_list<Value..., Other...>, List...>::type;
- };
- /**
- * @brief Concatenates multiple value lists.
- * @tparam Value Values provided by the value list.
- */
- template<auto... Value>
- struct value_list_cat<value_list<Value...>> {
- /*! @brief A value list composed by the values of all the value lists. */
- using type = value_list<Value...>;
- };
- /**
- * @brief Helper type.
- * @tparam List Value lists to concatenate.
- */
- template<typename... List>
- using value_list_cat_t = typename value_list_cat<List...>::type;
- /*! @brief Primary template isn't defined on purpose. */
- template<typename>
- struct value_list_unique;
- /**
- * @brief Removes duplicates values from a value list.
- * @tparam Value One of the values provided by the given value list.
- * @tparam Other The other values provided by the given value list.
- */
- template<auto Value, auto... Other>
- struct value_list_unique<value_list<Value, Other...>> {
- /*! @brief A value list without duplicate types. */
- using type = std::conditional_t<
- ((Value == Other) || ...),
- typename value_list_unique<value_list<Other...>>::type,
- value_list_cat_t<value_list<Value>, typename value_list_unique<value_list<Other...>>::type>>;
- };
- /*! @brief Removes duplicates values from a value list. */
- template<>
- struct value_list_unique<value_list<>> {
- /*! @brief A value list without duplicate types. */
- using type = value_list<>;
- };
- /**
- * @brief Helper type.
- * @tparam Type A value list.
- */
- template<typename Type>
- using value_list_unique_t = typename value_list_unique<Type>::type;
- /**
- * @brief Provides the member constant `value` to true if a value list contains
- * a given value, false otherwise.
- * @tparam List Value list.
- * @tparam Value Value to look for.
- */
- template<typename List, auto Value>
- struct value_list_contains;
- /**
- * @copybrief value_list_contains
- * @tparam Value Values provided by the value list.
- * @tparam Other Value to look for.
- */
- template<auto... Value, auto Other>
- struct value_list_contains<value_list<Value...>, Other>
- : std::bool_constant<((Value == Other) || ...)> {};
- /**
- * @brief Helper variable template.
- * @tparam List Value list.
- * @tparam Value Value to look for.
- */
- template<typename List, auto Value>
- inline constexpr bool value_list_contains_v = value_list_contains<List, Value>::value;
- /*! @brief Primary template isn't defined on purpose. */
- template<typename...>
- struct value_list_diff;
- /**
- * @brief Computes the difference between two value lists.
- * @tparam Value Values provided by the first value list.
- * @tparam Other Values provided by the second value list.
- */
- template<auto... Value, auto... Other>
- struct value_list_diff<value_list<Value...>, value_list<Other...>> {
- /*! @brief A value list that is the difference between the two value lists. */
- using type = value_list_cat_t<std::conditional_t<value_list_contains_v<value_list<Other...>, Value>, value_list<>, value_list<Value>>...>;
- };
- /**
- * @brief Helper type.
- * @tparam List Value lists between which to compute the difference.
- */
- template<typename... List>
- using value_list_diff_t = typename value_list_diff<List...>::type;
- /*! @brief Same as std::is_invocable, but with tuples. */
- template<typename, typename>
- struct is_applicable: std::false_type {};
- /**
- * @copybrief is_applicable
- * @tparam Func A valid function type.
- * @tparam Tuple Tuple-like type.
- * @tparam Args The list of arguments to use to probe the function type.
- */
- template<typename Func, template<typename...> class Tuple, typename... Args>
- struct is_applicable<Func, Tuple<Args...>>: std::is_invocable<Func, Args...> {};
- /**
- * @copybrief is_applicable
- * @tparam Func A valid function type.
- * @tparam Tuple Tuple-like type.
- * @tparam Args The list of arguments to use to probe the function type.
- */
- template<typename Func, template<typename...> class Tuple, typename... Args>
- struct is_applicable<Func, const Tuple<Args...>>: std::is_invocable<Func, Args...> {};
- /**
- * @brief Helper variable template.
- * @tparam Func A valid function type.
- * @tparam Args The list of arguments to use to probe the function type.
- */
- template<typename Func, typename Args>
- inline constexpr bool is_applicable_v = is_applicable<Func, Args>::value;
- /*! @brief Same as std::is_invocable_r, but with tuples for arguments. */
- template<typename, typename, typename>
- struct is_applicable_r: std::false_type {};
- /**
- * @copybrief is_applicable_r
- * @tparam Ret The type to which the return type of the function should be
- * convertible.
- * @tparam Func A valid function type.
- * @tparam Args The list of arguments to use to probe the function type.
- */
- template<typename Ret, typename Func, typename... Args>
- struct is_applicable_r<Ret, Func, std::tuple<Args...>>: std::is_invocable_r<Ret, Func, Args...> {};
- /**
- * @brief Helper variable template.
- * @tparam Ret The type to which the return type of the function should be
- * convertible.
- * @tparam Func A valid function type.
- * @tparam Args The list of arguments to use to probe the function type.
- */
- template<typename Ret, typename Func, typename Args>
- inline constexpr bool is_applicable_r_v = is_applicable_r<Ret, Func, Args>::value;
- /**
- * @brief Provides the member constant `value` to true if a given type is
- * complete, false otherwise.
- * @tparam Type The type to test.
- */
- template<typename Type, typename = void>
- struct is_complete: std::false_type {};
- /*! @copydoc is_complete */
- template<typename Type>
- struct is_complete<Type, std::void_t<decltype(sizeof(Type))>>: std::true_type {};
- /**
- * @brief Helper variable template.
- * @tparam Type The type to test.
- */
- template<typename Type>
- inline constexpr bool is_complete_v = is_complete<Type>::value;
- /**
- * @brief Provides the member constant `value` to true if a given type is an
- * iterator, false otherwise.
- * @tparam Type The type to test.
- */
- template<typename Type, typename = void>
- struct is_iterator: std::false_type {};
- /*! @cond TURN_OFF_DOXYGEN */
- namespace internal {
- template<typename, typename = void>
- struct has_iterator_category: std::false_type {};
- template<typename Type>
- struct has_iterator_category<Type, std::void_t<typename std::iterator_traits<Type>::iterator_category>>: std::true_type {};
- } // namespace internal
- /*! @endcond */
- /*! @copydoc is_iterator */
- template<typename Type>
- struct is_iterator<Type, std::enable_if_t<!std::is_void_v<std::remove_const_t<std::remove_pointer_t<Type>>>>>
- : internal::has_iterator_category<Type> {};
- /**
- * @brief Helper variable template.
- * @tparam Type The type to test.
- */
- template<typename Type>
- inline constexpr bool is_iterator_v = is_iterator<Type>::value;
- /**
- * @brief Provides the member constant `value` to true if a given type is both
- * an empty and non-final class, false otherwise.
- * @tparam Type The type to test
- */
- template<typename Type>
- struct is_ebco_eligible
- : std::bool_constant<std::is_empty_v<Type> && !std::is_final_v<Type>> {};
- /**
- * @brief Helper variable template.
- * @tparam Type The type to test.
- */
- template<typename Type>
- inline constexpr bool is_ebco_eligible_v = is_ebco_eligible<Type>::value;
- /**
- * @brief Provides the member constant `value` to true if `Type::is_transparent`
- * is valid and denotes a type, false otherwise.
- * @tparam Type The type to test.
- */
- template<typename Type, typename = void>
- struct is_transparent: std::false_type {};
- /*! @copydoc is_transparent */
- template<typename Type>
- struct is_transparent<Type, std::void_t<typename Type::is_transparent>>: std::true_type {};
- /**
- * @brief Helper variable template.
- * @tparam Type The type to test.
- */
- template<typename Type>
- inline constexpr bool is_transparent_v = is_transparent<Type>::value;
- /*! @cond TURN_OFF_DOXYGEN */
- namespace internal {
- template<typename, typename = void>
- struct has_tuple_size_value: std::false_type {};
- template<typename Type>
- struct has_tuple_size_value<Type, std::void_t<decltype(std::tuple_size<const Type>::value)>>: std::true_type {};
- template<typename, typename = void>
- struct has_value_type: std::false_type {};
- template<typename Type>
- struct has_value_type<Type, std::void_t<typename Type::value_type>>: std::true_type {};
- template<typename>
- [[nodiscard]] constexpr bool dispatch_is_equality_comparable();
- template<typename Type, std::size_t... Index>
- [[nodiscard]] constexpr bool unpack_maybe_equality_comparable(std::index_sequence<Index...>) {
- return (dispatch_is_equality_comparable<std::tuple_element_t<Index, Type>>() && ...);
- }
- template<typename>
- [[nodiscard]] constexpr bool maybe_equality_comparable(char) {
- return false;
- }
- template<typename Type>
- [[nodiscard]] constexpr auto maybe_equality_comparable(int) -> decltype(std::declval<Type>() == std::declval<Type>()) {
- return true;
- }
- template<typename Type>
- [[nodiscard]] constexpr bool dispatch_is_equality_comparable() {
- // NOLINTBEGIN(modernize-use-transparent-functors)
- if constexpr(std::is_array_v<Type>) {
- return false;
- } else if constexpr(is_complete_v<std::tuple_size<std::remove_const_t<Type>>>) {
- if constexpr(has_tuple_size_value<Type>::value) {
- return maybe_equality_comparable<Type>(0) && unpack_maybe_equality_comparable<Type>(std::make_index_sequence<std::tuple_size<Type>::value>{});
- } else {
- return maybe_equality_comparable<Type>(0);
- }
- } else if constexpr(has_value_type<Type>::value) {
- if constexpr(is_iterator_v<Type> || std::is_same_v<typename Type::value_type, Type> || dispatch_is_equality_comparable<typename Type::value_type>()) {
- return maybe_equality_comparable<Type>(0);
- } else {
- return false;
- }
- } else {
- return maybe_equality_comparable<Type>(0);
- }
- // NOLINTEND(modernize-use-transparent-functors)
- }
- } // namespace internal
- /*! @endcond */
- /**
- * @brief Provides the member constant `value` to true if a given type is
- * equality comparable, false otherwise.
- * @tparam Type The type to test.
- */
- template<typename Type>
- struct is_equality_comparable: std::bool_constant<internal::dispatch_is_equality_comparable<Type>()> {};
- /*! @copydoc is_equality_comparable */
- template<typename Type>
- struct is_equality_comparable<const Type>: is_equality_comparable<Type> {};
- /**
- * @brief Helper variable template.
- * @tparam Type The type to test.
- */
- template<typename Type>
- inline constexpr bool is_equality_comparable_v = is_equality_comparable<Type>::value;
- /**
- * @brief Transcribes the constness of a type to another type.
- * @tparam To The type to which to transcribe the constness.
- * @tparam From The type from which to transcribe the constness.
- */
- template<typename To, typename From>
- struct constness_as {
- /*! @brief The type resulting from the transcription of the constness. */
- using type = std::remove_const_t<To>;
- };
- /*! @copydoc constness_as */
- template<typename To, typename From>
- struct constness_as<To, const From> {
- /*! @brief The type resulting from the transcription of the constness. */
- using type = const To;
- };
- /**
- * @brief Alias template to facilitate the transcription of the constness.
- * @tparam To The type to which to transcribe the constness.
- * @tparam From The type from which to transcribe the constness.
- */
- template<typename To, typename From>
- using constness_as_t = typename constness_as<To, From>::type;
- /**
- * @brief Extracts the class of a non-static member object or function.
- * @tparam Member A pointer to a non-static member object or function.
- */
- template<typename Member>
- class member_class {
- static_assert(std::is_member_pointer_v<Member>, "Invalid pointer type to non-static member object or function");
- template<typename Class, typename Ret, typename... Args>
- static Class *clazz(Ret (Class::*)(Args...));
- template<typename Class, typename Ret, typename... Args>
- static Class *clazz(Ret (Class::*)(Args...) const);
- template<typename Class, typename Type>
- static Class *clazz(Type Class::*);
- public:
- /*! @brief The class of the given non-static member object or function. */
- using type = std::remove_pointer_t<decltype(clazz(std::declval<Member>()))>;
- };
- /**
- * @brief Helper type.
- * @tparam Member A pointer to a non-static member object or function.
- */
- template<typename Member>
- using member_class_t = typename member_class<Member>::type;
- /**
- * @brief Extracts the n-th argument of a _callable_ type.
- * @tparam Index The index of the argument to extract.
- * @tparam Candidate A valid _callable_ type.
- */
- template<std::size_t Index, typename Candidate>
- class nth_argument {
- template<typename Ret, typename... Args>
- static constexpr type_list<Args...> pick_up(Ret (*)(Args...));
- template<typename Ret, typename Class, typename... Args>
- static constexpr type_list<Args...> pick_up(Ret (Class ::*)(Args...));
- template<typename Ret, typename Class, typename... Args>
- static constexpr type_list<Args...> pick_up(Ret (Class ::*)(Args...) const);
- template<typename Type, typename Class>
- static constexpr type_list<Type> pick_up(Type Class ::*);
- template<typename Type>
- static constexpr decltype(pick_up(&Type::operator())) pick_up(Type &&);
- public:
- /*! @brief N-th argument of the _callable_ type. */
- using type = type_list_element_t<Index, decltype(pick_up(std::declval<Candidate>()))>;
- };
- /**
- * @brief Helper type.
- * @tparam Index The index of the argument to extract.
- * @tparam Candidate A valid function, member function or data member type.
- */
- template<std::size_t Index, typename Candidate>
- using nth_argument_t = typename nth_argument<Index, Candidate>::type;
- } // namespace entt
- template<typename... Type>
- struct std::tuple_size<entt::type_list<Type...>>: std::integral_constant<std::size_t, entt::type_list<Type...>::size> {};
- template<std::size_t Index, typename... Type>
- struct std::tuple_element<Index, entt::type_list<Type...>>: entt::type_list_element<Index, entt::type_list<Type...>> {};
- template<auto... Value>
- struct std::tuple_size<entt::value_list<Value...>>: std::integral_constant<std::size_t, entt::value_list<Value...>::size> {};
- template<std::size_t Index, auto... Value>
- struct std::tuple_element<Index, entt::value_list<Value...>>: entt::value_list_element<Index, entt::value_list<Value...>> {};
- #endif
- // #include "fwd.hpp"
- #ifndef ENTT_SIGNAL_FWD_HPP
- #define ENTT_SIGNAL_FWD_HPP
- #include <memory>
- namespace entt {
- template<typename>
- class delegate;
- template<typename = std::allocator<void>>
- class basic_dispatcher;
- template<typename, typename = std::allocator<void>>
- class emitter;
- class connection;
- struct scoped_connection;
- template<typename>
- class sink;
- template<typename Type, typename = std::allocator<void>>
- class sigh;
- /*! @brief Alias declaration for the most common use case. */
- using dispatcher = basic_dispatcher<>;
- /*! @brief Disambiguation tag for constructors and the like. */
- template<auto>
- struct connect_arg_t {
- /*! @brief Default constructor. */
- explicit connect_arg_t() = default;
- };
- /**
- * @brief Constant of type connect_arg_t used to disambiguate calls.
- * @tparam Candidate Element to connect (likely a free or member function).
- */
- template<auto Candidate>
- inline constexpr connect_arg_t<Candidate> connect_arg{};
- } // namespace entt
- #endif
- namespace entt {
- /*! @cond TURN_OFF_DOXYGEN */
- namespace internal {
- template<typename Ret, typename... Args>
- constexpr auto function_pointer(Ret (*)(Args...)) -> Ret (*)(Args...);
- template<typename Ret, typename Type, typename... Args, typename Other>
- constexpr auto function_pointer(Ret (*)(Type, Args...), Other &&) -> Ret (*)(Args...);
- template<typename Class, typename Ret, typename... Args, typename... Other>
- constexpr auto function_pointer(Ret (Class::*)(Args...), Other &&...) -> Ret (*)(Args...);
- template<typename Class, typename Ret, typename... Args, typename... Other>
- constexpr auto function_pointer(Ret (Class::*)(Args...) const, Other &&...) -> Ret (*)(Args...);
- template<typename Class, typename Type, typename... Other, typename = std::enable_if_t<std::is_member_object_pointer_v<Type Class::*>>>
- constexpr auto function_pointer(Type Class::*, Other &&...) -> Type (*)();
- template<typename... Type>
- using function_pointer_t = decltype(function_pointer(std::declval<Type>()...));
- template<typename... Class, typename Ret, typename... Args>
- [[nodiscard]] constexpr auto index_sequence_for(Ret (*)(Args...)) {
- return std::index_sequence_for<Class..., Args...>{};
- }
- } // namespace internal
- /*! @endcond */
- /**
- * @brief Basic delegate implementation.
- *
- * Primary template isn't defined on purpose. All the specializations give a
- * compile-time error unless the template parameter is a function type.
- */
- template<typename>
- class delegate;
- /**
- * @brief Utility class to use to send around functions and members.
- *
- * Unmanaged delegate for function pointers and members. Users of this class are
- * in charge of disconnecting instances before deleting them.
- *
- * A delegate can be used as a general purpose invoker without memory overhead
- * for free functions possibly with payloads and bound or unbound members.
- *
- * @tparam Ret Return type of a function type.
- * @tparam Args Types of arguments of a function type.
- */
- template<typename Ret, typename... Args>
- class delegate<Ret(Args...)> {
- using return_type = std::remove_const_t<Ret>;
- using delegate_type = return_type(const void *, Args...);
- template<auto Candidate, std::size_t... Index>
- [[nodiscard]] auto wrap(std::index_sequence<Index...>) noexcept {
- return [](const void *, Args... args) -> return_type {
- [[maybe_unused]] const auto arguments = std::forward_as_tuple(std::forward<Args>(args)...);
- [[maybe_unused]] constexpr auto offset = !std::is_invocable_r_v<Ret, decltype(Candidate), type_list_element_t<Index, type_list<Args...>>...> * (sizeof...(Args) - sizeof...(Index));
- return static_cast<Ret>(std::invoke(Candidate, std::forward<type_list_element_t<Index + offset, type_list<Args...>>>(std::get<Index + offset>(arguments))...));
- };
- }
- template<auto Candidate, typename Type, std::size_t... Index>
- [[nodiscard]] auto wrap(Type &, std::index_sequence<Index...>) noexcept {
- return [](const void *payload, Args... args) -> return_type {
- Type *curr = static_cast<Type *>(const_cast<constness_as_t<void, Type> *>(payload));
- [[maybe_unused]] const auto arguments = std::forward_as_tuple(std::forward<Args>(args)...);
- [[maybe_unused]] constexpr auto offset = !std::is_invocable_r_v<Ret, decltype(Candidate), Type &, type_list_element_t<Index, type_list<Args...>>...> * (sizeof...(Args) - sizeof...(Index));
- return static_cast<Ret>(std::invoke(Candidate, *curr, std::forward<type_list_element_t<Index + offset, type_list<Args...>>>(std::get<Index + offset>(arguments))...));
- };
- }
- template<auto Candidate, typename Type, std::size_t... Index>
- [[nodiscard]] auto wrap(Type *, std::index_sequence<Index...>) noexcept {
- return [](const void *payload, Args... args) -> return_type {
- Type *curr = static_cast<Type *>(const_cast<constness_as_t<void, Type> *>(payload));
- [[maybe_unused]] const auto arguments = std::forward_as_tuple(std::forward<Args>(args)...);
- [[maybe_unused]] constexpr auto offset = !std::is_invocable_r_v<Ret, decltype(Candidate), Type *, type_list_element_t<Index, type_list<Args...>>...> * (sizeof...(Args) - sizeof...(Index));
- return static_cast<Ret>(std::invoke(Candidate, curr, std::forward<type_list_element_t<Index + offset, type_list<Args...>>>(std::get<Index + offset>(arguments))...));
- };
- }
- public:
- /*! @brief Function type of the contained target. */
- using function_type = Ret(const void *, Args...);
- /*! @brief Function type of the delegate. */
- using type = Ret(Args...);
- /*! @brief Return type of the delegate. */
- using result_type = Ret;
- /*! @brief Default constructor. */
- delegate() noexcept = default;
- /**
- * @brief Constructs a delegate with a given object or payload, if any.
- * @tparam Candidate Function or member to connect to the delegate.
- * @tparam Type Type of class or type of payload, if any.
- * @param value_or_instance Optional valid object that fits the purpose.
- */
- template<auto Candidate, typename... Type>
- delegate(connect_arg_t<Candidate>, Type &&...value_or_instance) noexcept {
- connect<Candidate>(std::forward<Type>(value_or_instance)...);
- }
- /**
- * @brief Constructs a delegate and connects an user defined function with
- * optional payload.
- * @param function Function to connect to the delegate.
- * @param payload User defined arbitrary data.
- */
- delegate(function_type *function, const void *payload = nullptr) noexcept {
- connect(function, payload);
- }
- /**
- * @brief Connects a free function or an unbound member to a delegate.
- * @tparam Candidate Function or member to connect to the delegate.
- */
- template<auto Candidate>
- void connect() noexcept {
- instance = nullptr;
- if constexpr(std::is_invocable_r_v<Ret, decltype(Candidate), Args...>) {
- fn = [](const void *, Args... args) -> return_type {
- return Ret(std::invoke(Candidate, std::forward<Args>(args)...));
- };
- } else if constexpr(std::is_member_pointer_v<decltype(Candidate)>) {
- fn = wrap<Candidate>(internal::index_sequence_for<type_list_element_t<0, type_list<Args...>>>(internal::function_pointer_t<decltype(Candidate)>{}));
- } else {
- fn = wrap<Candidate>(internal::index_sequence_for(internal::function_pointer_t<decltype(Candidate)>{}));
- }
- }
- /**
- * @brief Connects a free function with payload or a bound member to a
- * delegate.
- *
- * The delegate isn't responsible for the connected object or the payload.
- * Users must always guarantee that the lifetime of the instance overcomes
- * the one of the delegate.<br/>
- * When used to connect a free function with payload, its signature must be
- * such that the instance is the first argument before the ones used to
- * define the delegate itself.
- *
- * @tparam Candidate Function or member to connect to the delegate.
- * @tparam Type Type of class or type of payload.
- * @param value_or_instance A valid reference that fits the purpose.
- */
- template<auto Candidate, typename Type>
- void connect(Type &value_or_instance) noexcept {
- instance = &value_or_instance;
- if constexpr(std::is_invocable_r_v<Ret, decltype(Candidate), Type &, Args...>) {
- fn = [](const void *payload, Args... args) -> return_type {
- Type *curr = static_cast<Type *>(const_cast<constness_as_t<void, Type> *>(payload));
- return Ret(std::invoke(Candidate, *curr, std::forward<Args>(args)...));
- };
- } else {
- fn = wrap<Candidate>(value_or_instance, internal::index_sequence_for(internal::function_pointer_t<decltype(Candidate), Type>{}));
- }
- }
- /**
- * @brief Connects a free function with payload or a bound member to a
- * delegate.
- *
- * @sa connect(Type &)
- *
- * @tparam Candidate Function or member to connect to the delegate.
- * @tparam Type Type of class or type of payload.
- * @param value_or_instance A valid pointer that fits the purpose.
- */
- template<auto Candidate, typename Type>
- void connect(Type *value_or_instance) noexcept {
- instance = value_or_instance;
- if constexpr(std::is_invocable_r_v<Ret, decltype(Candidate), Type *, Args...>) {
- fn = [](const void *payload, Args... args) -> return_type {
- Type *curr = static_cast<Type *>(const_cast<constness_as_t<void, Type> *>(payload));
- return Ret(std::invoke(Candidate, curr, std::forward<Args>(args)...));
- };
- } else {
- fn = wrap<Candidate>(value_or_instance, internal::index_sequence_for(internal::function_pointer_t<decltype(Candidate), Type>{}));
- }
- }
- /**
- * @brief Connects an user defined function with optional payload to a
- * delegate.
- *
- * The delegate isn't responsible for the connected object or the payload.
- * Users must always guarantee that the lifetime of an instance overcomes
- * the one of the delegate.<br/>
- * The payload is returned as the first argument to the target function in
- * all cases.
- *
- * @param function Function to connect to the delegate.
- * @param payload User defined arbitrary data.
- */
- void connect(function_type *function, const void *payload = nullptr) noexcept {
- ENTT_ASSERT(function != nullptr, "Uninitialized function pointer");
- instance = payload;
- fn = function;
- }
- /**
- * @brief Resets a delegate.
- *
- * After a reset, a delegate cannot be invoked anymore.
- */
- void reset() noexcept {
- instance = nullptr;
- fn = nullptr;
- }
- /**
- * @brief Returns a pointer to the stored callable function target, if any.
- * @return An opaque pointer to the stored callable function target.
- */
- [[nodiscard]] function_type *target() const noexcept {
- return fn;
- }
- /**
- * @brief Returns the instance or the payload linked to a delegate, if any.
- * @return An opaque pointer to the underlying data.
- */
- [[nodiscard]] const void *data() const noexcept {
- return instance;
- }
- /**
- * @brief Triggers a delegate.
- *
- * The delegate invokes the underlying function and returns the result.
- *
- * @warning
- * Attempting to trigger an invalid delegate results in undefined
- * behavior.
- *
- * @param args Arguments to use to invoke the underlying function.
- * @return The value returned by the underlying function.
- */
- Ret operator()(Args... args) const {
- ENTT_ASSERT(static_cast<bool>(*this), "Uninitialized delegate");
- return fn(instance, std::forward<Args>(args)...);
- }
- /**
- * @brief Checks whether a delegate actually stores a listener.
- * @return False if the delegate is empty, true otherwise.
- */
- [[nodiscard]] explicit operator bool() const noexcept {
- // no need to also test instance
- return !(fn == nullptr);
- }
- /**
- * @brief Compares the contents of two delegates.
- * @param other Delegate with which to compare.
- * @return False if the two contents differ, true otherwise.
- */
- [[nodiscard]] bool operator==(const delegate<Ret(Args...)> &other) const noexcept {
- return fn == other.fn && instance == other.instance;
- }
- private:
- const void *instance{};
- delegate_type *fn{};
- };
- /**
- * @brief Compares the contents of two delegates.
- * @tparam Ret Return type of a function type.
- * @tparam Args Types of arguments of a function type.
- * @param lhs A valid delegate object.
- * @param rhs A valid delegate object.
- * @return True if the two contents differ, false otherwise.
- */
- template<typename Ret, typename... Args>
- [[nodiscard]] bool operator!=(const delegate<Ret(Args...)> &lhs, const delegate<Ret(Args...)> &rhs) noexcept {
- return !(lhs == rhs);
- }
- /**
- * @brief Deduction guide.
- * @tparam Candidate Function or member to connect to the delegate.
- */
- template<auto Candidate>
- delegate(connect_arg_t<Candidate>) -> delegate<std::remove_pointer_t<internal::function_pointer_t<decltype(Candidate)>>>;
- /**
- * @brief Deduction guide.
- * @tparam Candidate Function or member to connect to the delegate.
- * @tparam Type Type of class or type of payload.
- */
- template<auto Candidate, typename Type>
- delegate(connect_arg_t<Candidate>, Type &&) -> delegate<std::remove_pointer_t<internal::function_pointer_t<decltype(Candidate), Type>>>;
- /**
- * @brief Deduction guide.
- * @tparam Ret Return type of a function type.
- * @tparam Args Types of arguments of a function type.
- */
- template<typename Ret, typename... Args>
- delegate(Ret (*)(const void *, Args...), const void * = nullptr) -> delegate<Ret(Args...)>;
- } // namespace entt
- #endif
- // #include "signal/dispatcher.hpp"
- #ifndef ENTT_SIGNAL_DISPATCHER_HPP
- #define ENTT_SIGNAL_DISPATCHER_HPP
- #include <cstddef>
- #include <functional>
- #include <memory>
- #include <type_traits>
- #include <utility>
- #include <vector>
- // #include "../container/dense_map.hpp"
- #ifndef ENTT_CONTAINER_DENSE_MAP_HPP
- #define ENTT_CONTAINER_DENSE_MAP_HPP
- #include <cmath>
- #include <cstddef>
- #include <functional>
- #include <iterator>
- #include <limits>
- #include <memory>
- #include <tuple>
- #include <type_traits>
- #include <utility>
- #include <vector>
- // #include "../config/config.h"
- #ifndef ENTT_CONFIG_CONFIG_H
- #define ENTT_CONFIG_CONFIG_H
- // #include "version.h"
- #ifndef ENTT_CONFIG_VERSION_H
- #define ENTT_CONFIG_VERSION_H
- // #include "macro.h"
- #ifndef ENTT_CONFIG_MACRO_H
- #define ENTT_CONFIG_MACRO_H
- // NOLINTBEGIN(cppcoreguidelines-macro-usage)
- #define ENTT_STR(arg) #arg
- #define ENTT_XSTR(arg) ENTT_STR(arg)
- // NOLINTEND(cppcoreguidelines-macro-usage)
- #endif
- // NOLINTBEGIN(cppcoreguidelines-macro-*,modernize-macro-*)
- #define ENTT_VERSION_MAJOR 3
- #define ENTT_VERSION_MINOR 16
- #define ENTT_VERSION_PATCH 0
- #define ENTT_VERSION \
- ENTT_XSTR(ENTT_VERSION_MAJOR) \
- "." ENTT_XSTR(ENTT_VERSION_MINOR) "." ENTT_XSTR(ENTT_VERSION_PATCH)
- // NOLINTEND(cppcoreguidelines-macro-*,modernize-macro-*)
- #endif
- // NOLINTBEGIN(cppcoreguidelines-macro-usage)
- #if defined(__cpp_exceptions) && !defined(ENTT_NOEXCEPTION)
- # define ENTT_CONSTEXPR
- # define ENTT_THROW throw
- # define ENTT_TRY try
- # define ENTT_CATCH catch(...)
- #else
- # define ENTT_CONSTEXPR constexpr // use only with throwing functions (waiting for C++20)
- # define ENTT_THROW
- # define ENTT_TRY if(true)
- # define ENTT_CATCH if(false)
- #endif
- #if __has_include(<version>)
- # include <version>
- #
- # if defined(__cpp_consteval)
- # define ENTT_CONSTEVAL consteval
- # endif
- #endif
- #ifndef ENTT_CONSTEVAL
- # define ENTT_CONSTEVAL constexpr
- #endif
- #ifdef ENTT_USE_ATOMIC
- # include <atomic>
- # define ENTT_MAYBE_ATOMIC(Type) std::atomic<Type>
- #else
- # define ENTT_MAYBE_ATOMIC(Type) Type
- #endif
- #ifndef ENTT_ID_TYPE
- # include <cstdint>
- # define ENTT_ID_TYPE std::uint32_t
- #else
- # include <cstdint> // provides coverage for types in the std namespace
- #endif
- #ifndef ENTT_SPARSE_PAGE
- # define ENTT_SPARSE_PAGE 4096
- #endif
- #ifndef ENTT_PACKED_PAGE
- # define ENTT_PACKED_PAGE 1024
- #endif
- #ifdef ENTT_DISABLE_ASSERT
- # undef ENTT_ASSERT
- # define ENTT_ASSERT(condition, msg) (void(0))
- #elif !defined ENTT_ASSERT
- # include <cassert>
- # define ENTT_ASSERT(condition, msg) assert(((condition) && (msg)))
- #endif
- #ifdef ENTT_DISABLE_ASSERT
- # undef ENTT_ASSERT_CONSTEXPR
- # define ENTT_ASSERT_CONSTEXPR(condition, msg) (void(0))
- #elif !defined ENTT_ASSERT_CONSTEXPR
- # define ENTT_ASSERT_CONSTEXPR(condition, msg) ENTT_ASSERT(condition, msg)
- #endif
- #define ENTT_FAIL(msg) ENTT_ASSERT(false, msg);
- #ifdef ENTT_NO_ETO
- # define ENTT_ETO_TYPE(Type) void
- #else
- # define ENTT_ETO_TYPE(Type) Type
- #endif
- #ifdef ENTT_NO_MIXIN
- # define ENTT_STORAGE(Mixin, ...) __VA_ARGS__
- #else
- # define ENTT_STORAGE(Mixin, ...) Mixin<__VA_ARGS__>
- #endif
- #ifdef ENTT_STANDARD_CPP
- # define ENTT_NONSTD false
- #else
- # define ENTT_NONSTD true
- # if defined __clang__ || defined __GNUC__
- # define ENTT_PRETTY_FUNCTION __PRETTY_FUNCTION__
- # define ENTT_PRETTY_FUNCTION_PREFIX '='
- # define ENTT_PRETTY_FUNCTION_SUFFIX ']'
- # elif defined _MSC_VER
- # define ENTT_PRETTY_FUNCTION __FUNCSIG__
- # define ENTT_PRETTY_FUNCTION_PREFIX '<'
- # define ENTT_PRETTY_FUNCTION_SUFFIX '>'
- # endif
- #endif
- #ifndef ENTT_EXPORT
- # if defined _WIN32 || defined __CYGWIN__ || defined _MSC_VER
- # define ENTT_EXPORT __declspec(dllexport)
- # define ENTT_IMPORT __declspec(dllimport)
- # define ENTT_HIDDEN
- # elif defined __GNUC__ && __GNUC__ >= 4
- # define ENTT_EXPORT __attribute__((visibility("default")))
- # define ENTT_IMPORT __attribute__((visibility("default")))
- # define ENTT_HIDDEN __attribute__((visibility("hidden")))
- # else /* Unsupported compiler */
- # define ENTT_EXPORT
- # define ENTT_IMPORT
- # define ENTT_HIDDEN
- # endif
- #endif
- #ifndef ENTT_API
- # if defined ENTT_API_EXPORT
- # define ENTT_API ENTT_EXPORT
- # elif defined ENTT_API_IMPORT
- # define ENTT_API ENTT_IMPORT
- # else /* No API */
- # define ENTT_API
- # endif
- #endif
- #if defined _MSC_VER
- # pragma detect_mismatch("entt.version", ENTT_VERSION)
- # pragma detect_mismatch("entt.noexcept", ENTT_XSTR(ENTT_TRY))
- # pragma detect_mismatch("entt.id", ENTT_XSTR(ENTT_ID_TYPE))
- # pragma detect_mismatch("entt.nonstd", ENTT_XSTR(ENTT_NONSTD))
- #endif
- // NOLINTEND(cppcoreguidelines-macro-usage)
- #endif
- // #include "../core/bit.hpp"
- #ifndef ENTT_CORE_BIT_HPP
- #define ENTT_CORE_BIT_HPP
- #include <cstddef>
- #include <limits>
- #include <type_traits>
- // #include "../config/config.h"
- #ifndef ENTT_CONFIG_CONFIG_H
- #define ENTT_CONFIG_CONFIG_H
- // #include "version.h"
- #ifndef ENTT_CONFIG_VERSION_H
- #define ENTT_CONFIG_VERSION_H
- // #include "macro.h"
- #ifndef ENTT_CONFIG_MACRO_H
- #define ENTT_CONFIG_MACRO_H
- // NOLINTBEGIN(cppcoreguidelines-macro-usage)
- #define ENTT_STR(arg) #arg
- #define ENTT_XSTR(arg) ENTT_STR(arg)
- // NOLINTEND(cppcoreguidelines-macro-usage)
- #endif
- // NOLINTBEGIN(cppcoreguidelines-macro-*,modernize-macro-*)
- #define ENTT_VERSION_MAJOR 3
- #define ENTT_VERSION_MINOR 16
- #define ENTT_VERSION_PATCH 0
- #define ENTT_VERSION \
- ENTT_XSTR(ENTT_VERSION_MAJOR) \
- "." ENTT_XSTR(ENTT_VERSION_MINOR) "." ENTT_XSTR(ENTT_VERSION_PATCH)
- // NOLINTEND(cppcoreguidelines-macro-*,modernize-macro-*)
- #endif
- // NOLINTBEGIN(cppcoreguidelines-macro-usage)
- #if defined(__cpp_exceptions) && !defined(ENTT_NOEXCEPTION)
- # define ENTT_CONSTEXPR
- # define ENTT_THROW throw
- # define ENTT_TRY try
- # define ENTT_CATCH catch(...)
- #else
- # define ENTT_CONSTEXPR constexpr // use only with throwing functions (waiting for C++20)
- # define ENTT_THROW
- # define ENTT_TRY if(true)
- # define ENTT_CATCH if(false)
- #endif
- #if __has_include(<version>)
- # include <version>
- #
- # if defined(__cpp_consteval)
- # define ENTT_CONSTEVAL consteval
- # endif
- #endif
- #ifndef ENTT_CONSTEVAL
- # define ENTT_CONSTEVAL constexpr
- #endif
- #ifdef ENTT_USE_ATOMIC
- # include <atomic>
- # define ENTT_MAYBE_ATOMIC(Type) std::atomic<Type>
- #else
- # define ENTT_MAYBE_ATOMIC(Type) Type
- #endif
- #ifndef ENTT_ID_TYPE
- # include <cstdint>
- # define ENTT_ID_TYPE std::uint32_t
- #else
- # include <cstdint> // provides coverage for types in the std namespace
- #endif
- #ifndef ENTT_SPARSE_PAGE
- # define ENTT_SPARSE_PAGE 4096
- #endif
- #ifndef ENTT_PACKED_PAGE
- # define ENTT_PACKED_PAGE 1024
- #endif
- #ifdef ENTT_DISABLE_ASSERT
- # undef ENTT_ASSERT
- # define ENTT_ASSERT(condition, msg) (void(0))
- #elif !defined ENTT_ASSERT
- # include <cassert>
- # define ENTT_ASSERT(condition, msg) assert(((condition) && (msg)))
- #endif
- #ifdef ENTT_DISABLE_ASSERT
- # undef ENTT_ASSERT_CONSTEXPR
- # define ENTT_ASSERT_CONSTEXPR(condition, msg) (void(0))
- #elif !defined ENTT_ASSERT_CONSTEXPR
- # define ENTT_ASSERT_CONSTEXPR(condition, msg) ENTT_ASSERT(condition, msg)
- #endif
- #define ENTT_FAIL(msg) ENTT_ASSERT(false, msg);
- #ifdef ENTT_NO_ETO
- # define ENTT_ETO_TYPE(Type) void
- #else
- # define ENTT_ETO_TYPE(Type) Type
- #endif
- #ifdef ENTT_NO_MIXIN
- # define ENTT_STORAGE(Mixin, ...) __VA_ARGS__
- #else
- # define ENTT_STORAGE(Mixin, ...) Mixin<__VA_ARGS__>
- #endif
- #ifdef ENTT_STANDARD_CPP
- # define ENTT_NONSTD false
- #else
- # define ENTT_NONSTD true
- # if defined __clang__ || defined __GNUC__
- # define ENTT_PRETTY_FUNCTION __PRETTY_FUNCTION__
- # define ENTT_PRETTY_FUNCTION_PREFIX '='
- # define ENTT_PRETTY_FUNCTION_SUFFIX ']'
- # elif defined _MSC_VER
- # define ENTT_PRETTY_FUNCTION __FUNCSIG__
- # define ENTT_PRETTY_FUNCTION_PREFIX '<'
- # define ENTT_PRETTY_FUNCTION_SUFFIX '>'
- # endif
- #endif
- #ifndef ENTT_EXPORT
- # if defined _WIN32 || defined __CYGWIN__ || defined _MSC_VER
- # define ENTT_EXPORT __declspec(dllexport)
- # define ENTT_IMPORT __declspec(dllimport)
- # define ENTT_HIDDEN
- # elif defined __GNUC__ && __GNUC__ >= 4
- # define ENTT_EXPORT __attribute__((visibility("default")))
- # define ENTT_IMPORT __attribute__((visibility("default")))
- # define ENTT_HIDDEN __attribute__((visibility("hidden")))
- # else /* Unsupported compiler */
- # define ENTT_EXPORT
- # define ENTT_IMPORT
- # define ENTT_HIDDEN
- # endif
- #endif
- #ifndef ENTT_API
- # if defined ENTT_API_EXPORT
- # define ENTT_API ENTT_EXPORT
- # elif defined ENTT_API_IMPORT
- # define ENTT_API ENTT_IMPORT
- # else /* No API */
- # define ENTT_API
- # endif
- #endif
- #if defined _MSC_VER
- # pragma detect_mismatch("entt.version", ENTT_VERSION)
- # pragma detect_mismatch("entt.noexcept", ENTT_XSTR(ENTT_TRY))
- # pragma detect_mismatch("entt.id", ENTT_XSTR(ENTT_ID_TYPE))
- # pragma detect_mismatch("entt.nonstd", ENTT_XSTR(ENTT_NONSTD))
- #endif
- // NOLINTEND(cppcoreguidelines-macro-usage)
- #endif
- namespace entt {
- /**
- * @brief Returns the number of set bits in a value (waiting for C++20 and
- * `std::popcount`).
- * @tparam Type Unsigned integer type.
- * @param value A value of unsigned integer type.
- * @return The number of set bits in the value.
- */
- template<typename Type>
- [[nodiscard]] constexpr std::enable_if_t<std::is_unsigned_v<Type>, int> popcount(const Type value) noexcept {
- return value ? (int(value & 1) + popcount(static_cast<Type>(value >> 1))) : 0;
- }
- /**
- * @brief Checks whether a value is a power of two or not (waiting for C++20 and
- * `std::has_single_bit`).
- * @tparam Type Unsigned integer type.
- * @param value A value of unsigned integer type.
- * @return True if the value is a power of two, false otherwise.
- */
- template<typename Type>
- [[nodiscard]] constexpr std::enable_if_t<std::is_unsigned_v<Type>, bool> has_single_bit(const Type value) noexcept {
- return value && ((value & (value - 1)) == 0);
- }
- /**
- * @brief Computes the smallest power of two greater than or equal to a value
- * (waiting for C++20 and `std::bit_ceil`).
- * @tparam Type Unsigned integer type.
- * @param value A value of unsigned integer type.
- * @return The smallest power of two greater than or equal to the given value.
- */
- template<typename Type>
- [[nodiscard]] constexpr std::enable_if_t<std::is_unsigned_v<Type>, Type> next_power_of_two(const Type value) noexcept {
- // NOLINTNEXTLINE(bugprone-assert-side-effect)
- ENTT_ASSERT_CONSTEXPR(value < (Type{1u} << (std::numeric_limits<Type>::digits - 1)), "Numeric limits exceeded");
- Type curr = value - (value != 0u);
- for(int next = 1; next < std::numeric_limits<Type>::digits; next = next * 2) {
- curr |= (curr >> next);
- }
- return ++curr;
- }
- /**
- * @brief Fast module utility function (powers of two only).
- * @tparam Type Unsigned integer type.
- * @param value A value of unsigned integer type.
- * @param mod _Modulus_, it must be a power of two.
- * @return The common remainder.
- */
- template<typename Type>
- [[nodiscard]] constexpr std::enable_if_t<std::is_unsigned_v<Type>, Type> fast_mod(const Type value, const std::size_t mod) noexcept {
- ENTT_ASSERT_CONSTEXPR(has_single_bit(mod), "Value must be a power of two");
- return static_cast<Type>(value & (mod - 1u));
- }
- } // namespace entt
- #endif
- // #include "../core/compressed_pair.hpp"
- #ifndef ENTT_CORE_COMPRESSED_PAIR_HPP
- #define ENTT_CORE_COMPRESSED_PAIR_HPP
- #include <cstddef>
- #include <tuple>
- #include <type_traits>
- #include <utility>
- // #include "fwd.hpp"
- #ifndef ENTT_CORE_FWD_HPP
- #define ENTT_CORE_FWD_HPP
- #include <cstddef>
- #include <cstdint>
- // #include "../config/config.h"
- namespace entt {
- /*! @brief Possible modes of an any object. */
- enum class any_policy : std::uint8_t {
- /*! @brief Default mode, no element available. */
- empty,
- /*! @brief Owning mode, dynamically allocated element. */
- dynamic,
- /*! @brief Owning mode, embedded element. */
- embedded,
- /*! @brief Aliasing mode, non-const reference. */
- ref,
- /*! @brief Const aliasing mode, const reference. */
- cref
- };
- // NOLINTNEXTLINE(cppcoreguidelines-avoid-c-arrays, modernize-avoid-c-arrays)
- template<std::size_t Len = sizeof(double[2]), std::size_t = alignof(double[2])>
- class basic_any;
- /*! @brief Alias declaration for type identifiers. */
- using id_type = ENTT_ID_TYPE;
- /*! @brief Alias declaration for the most common use case. */
- using any = basic_any<>;
- template<typename, typename>
- class compressed_pair;
- template<typename>
- class basic_hashed_string;
- /*! @brief Aliases for common character types. */
- using hashed_string = basic_hashed_string<char>;
- /*! @brief Aliases for common character types. */
- using hashed_wstring = basic_hashed_string<wchar_t>;
- // NOLINTNEXTLINE(bugprone-forward-declaration-namespace)
- struct type_info;
- } // namespace entt
- #endif
- // #include "type_traits.hpp"
- #ifndef ENTT_CORE_TYPE_TRAITS_HPP
- #define ENTT_CORE_TYPE_TRAITS_HPP
- #include <cstddef>
- #include <iterator>
- #include <tuple>
- #include <type_traits>
- #include <utility>
- // #include "../config/config.h"
- // #include "fwd.hpp"
- namespace entt {
- /**
- * @brief Utility class to disambiguate overloaded functions.
- * @tparam N Number of choices available.
- */
- template<std::size_t N>
- struct choice_t
- // unfortunately, doxygen cannot parse such a construct
- : /*! @cond TURN_OFF_DOXYGEN */ choice_t<N - 1> /*! @endcond */
- {};
- /*! @copybrief choice_t */
- template<>
- struct choice_t<0> {};
- /**
- * @brief Variable template for the choice trick.
- * @tparam N Number of choices available.
- */
- template<std::size_t N>
- inline constexpr choice_t<N> choice{};
- /**
- * @brief Identity type trait.
- *
- * Useful to establish non-deduced contexts in template argument deduction
- * (waiting for C++20) or to provide types through function arguments.
- *
- * @tparam Type A type.
- */
- template<typename Type>
- struct type_identity {
- /*! @brief Identity type. */
- using type = Type;
- };
- /**
- * @brief Helper type.
- * @tparam Type A type.
- */
- template<typename Type>
- using type_identity_t = typename type_identity<Type>::type;
- /**
- * @brief A type-only `sizeof` wrapper that returns 0 where `sizeof` complains.
- * @tparam Type The type of which to return the size.
- */
- template<typename Type, typename = void>
- struct size_of: std::integral_constant<std::size_t, 0u> {};
- /*! @copydoc size_of */
- template<typename Type>
- struct size_of<Type, std::void_t<decltype(sizeof(Type))>>
- // NOLINTNEXTLINE(bugprone-sizeof-expression)
- : std::integral_constant<std::size_t, sizeof(Type)> {};
- /**
- * @brief Helper variable template.
- * @tparam Type The type of which to return the size.
- */
- template<typename Type>
- inline constexpr std::size_t size_of_v = size_of<Type>::value;
- /**
- * @brief Using declaration to be used to _repeat_ the same type a number of
- * times equal to the size of a given parameter pack.
- * @tparam Type A type to repeat.
- */
- template<typename Type, typename>
- using unpack_as_type = Type;
- /**
- * @brief Helper variable template to be used to _repeat_ the same value a
- * number of times equal to the size of a given parameter pack.
- * @tparam Value A value to repeat.
- */
- template<auto Value, typename>
- inline constexpr auto unpack_as_value = Value;
- /**
- * @brief Wraps a static constant.
- * @tparam Value A static constant.
- */
- template<auto Value>
- using integral_constant = std::integral_constant<decltype(Value), Value>;
- /**
- * @brief Alias template to facilitate the creation of named values.
- * @tparam Value A constant value at least convertible to `id_type`.
- */
- template<id_type Value>
- using tag = integral_constant<Value>;
- /**
- * @brief A class to use to push around lists of types, nothing more.
- * @tparam Type Types provided by the type list.
- */
- template<typename... Type>
- struct type_list {
- /*! @brief Type list type. */
- using type = type_list;
- /*! @brief Compile-time number of elements in the type list. */
- static constexpr auto size = sizeof...(Type);
- };
- /*! @brief Primary template isn't defined on purpose. */
- template<std::size_t, typename>
- struct type_list_element;
- /**
- * @brief Provides compile-time indexed access to the types of a type list.
- * @tparam Index Index of the type to return.
- * @tparam First First type provided by the type list.
- * @tparam Other Other types provided by the type list.
- */
- template<std::size_t Index, typename First, typename... Other>
- struct type_list_element<Index, type_list<First, Other...>>
- : type_list_element<Index - 1u, type_list<Other...>> {};
- /**
- * @brief Provides compile-time indexed access to the types of a type list.
- * @tparam First First type provided by the type list.
- * @tparam Other Other types provided by the type list.
- */
- template<typename First, typename... Other>
- struct type_list_element<0u, type_list<First, Other...>> {
- /*! @brief Searched type. */
- using type = First;
- };
- /**
- * @brief Helper type.
- * @tparam Index Index of the type to return.
- * @tparam List Type list to search into.
- */
- template<std::size_t Index, typename List>
- using type_list_element_t = typename type_list_element<Index, List>::type;
- /*! @brief Primary template isn't defined on purpose. */
- template<typename, typename>
- struct type_list_index;
- /**
- * @brief Provides compile-time type access to the types of a type list.
- * @tparam Type Type to look for and for which to return the index.
- * @tparam First First type provided by the type list.
- * @tparam Other Other types provided by the type list.
- */
- template<typename Type, typename First, typename... Other>
- struct type_list_index<Type, type_list<First, Other...>> {
- /*! @brief Unsigned integer type. */
- using value_type = std::size_t;
- /*! @brief Compile-time position of the given type in the sublist. */
- static constexpr value_type value = 1u + type_list_index<Type, type_list<Other...>>::value;
- };
- /**
- * @brief Provides compile-time type access to the types of a type list.
- * @tparam Type Type to look for and for which to return the index.
- * @tparam Other Other types provided by the type list.
- */
- template<typename Type, typename... Other>
- struct type_list_index<Type, type_list<Type, Other...>> {
- static_assert(type_list_index<Type, type_list<Other...>>::value == sizeof...(Other), "Non-unique type");
- /*! @brief Unsigned integer type. */
- using value_type = std::size_t;
- /*! @brief Compile-time position of the given type in the sublist. */
- static constexpr value_type value = 0u;
- };
- /**
- * @brief Provides compile-time type access to the types of a type list.
- * @tparam Type Type to look for and for which to return the index.
- */
- template<typename Type>
- struct type_list_index<Type, type_list<>> {
- /*! @brief Unsigned integer type. */
- using value_type = std::size_t;
- /*! @brief Compile-time position of the given type in the sublist. */
- static constexpr value_type value = 0u;
- };
- /**
- * @brief Helper variable template.
- * @tparam List Type list.
- * @tparam Type Type to look for and for which to return the index.
- */
- template<typename Type, typename List>
- inline constexpr std::size_t type_list_index_v = type_list_index<Type, List>::value;
- /**
- * @brief Concatenates multiple type lists.
- * @tparam Type Types provided by the first type list.
- * @tparam Other Types provided by the second type list.
- * @return A type list composed by the types of both the type lists.
- */
- template<typename... Type, typename... Other>
- constexpr type_list<Type..., Other...> operator+(type_list<Type...>, type_list<Other...>) {
- return {};
- }
- /*! @brief Primary template isn't defined on purpose. */
- template<typename...>
- struct type_list_cat;
- /*! @brief Concatenates multiple type lists. */
- template<>
- struct type_list_cat<> {
- /*! @brief A type list composed by the types of all the type lists. */
- using type = type_list<>;
- };
- /**
- * @brief Concatenates multiple type lists.
- * @tparam Type Types provided by the first type list.
- * @tparam Other Types provided by the second type list.
- * @tparam List Other type lists, if any.
- */
- template<typename... Type, typename... Other, typename... List>
- struct type_list_cat<type_list<Type...>, type_list<Other...>, List...> {
- /*! @brief A type list composed by the types of all the type lists. */
- using type = typename type_list_cat<type_list<Type..., Other...>, List...>::type;
- };
- /**
- * @brief Concatenates multiple type lists.
- * @tparam Type Types provided by the type list.
- */
- template<typename... Type>
- struct type_list_cat<type_list<Type...>> {
- /*! @brief A type list composed by the types of all the type lists. */
- using type = type_list<Type...>;
- };
- /**
- * @brief Helper type.
- * @tparam List Type lists to concatenate.
- */
- template<typename... List>
- using type_list_cat_t = typename type_list_cat<List...>::type;
- /*! @cond TURN_OFF_DOXYGEN */
- namespace internal {
- template<typename...>
- struct type_list_unique;
- template<typename First, typename... Other, typename... Type>
- struct type_list_unique<type_list<First, Other...>, Type...>
- : std::conditional_t<(std::is_same_v<First, Type> || ...), type_list_unique<type_list<Other...>, Type...>, type_list_unique<type_list<Other...>, Type..., First>> {};
- template<typename... Type>
- struct type_list_unique<type_list<>, Type...> {
- using type = type_list<Type...>;
- };
- } // namespace internal
- /*! @endcond */
- /**
- * @brief Removes duplicates types from a type list.
- * @tparam List Type list.
- */
- template<typename List>
- struct type_list_unique {
- /*! @brief A type list without duplicate types. */
- using type = typename internal::type_list_unique<List>::type;
- };
- /**
- * @brief Helper type.
- * @tparam List Type list.
- */
- template<typename List>
- using type_list_unique_t = typename type_list_unique<List>::type;
- /**
- * @brief Provides the member constant `value` to true if a type list contains a
- * given type, false otherwise.
- * @tparam List Type list.
- * @tparam Type Type to look for.
- */
- template<typename List, typename Type>
- struct type_list_contains;
- /**
- * @copybrief type_list_contains
- * @tparam Type Types provided by the type list.
- * @tparam Other Type to look for.
- */
- template<typename... Type, typename Other>
- struct type_list_contains<type_list<Type...>, Other>
- : std::bool_constant<(std::is_same_v<Type, Other> || ...)> {};
- /**
- * @brief Helper variable template.
- * @tparam List Type list.
- * @tparam Type Type to look for.
- */
- template<typename List, typename Type>
- inline constexpr bool type_list_contains_v = type_list_contains<List, Type>::value;
- /*! @brief Primary template isn't defined on purpose. */
- template<typename...>
- struct type_list_diff;
- /**
- * @brief Computes the difference between two type lists.
- * @tparam Type Types provided by the first type list.
- * @tparam Other Types provided by the second type list.
- */
- template<typename... Type, typename... Other>
- struct type_list_diff<type_list<Type...>, type_list<Other...>> {
- /*! @brief A type list that is the difference between the two type lists. */
- using type = type_list_cat_t<std::conditional_t<type_list_contains_v<type_list<Other...>, Type>, type_list<>, type_list<Type>>...>;
- };
- /**
- * @brief Helper type.
- * @tparam List Type lists between which to compute the difference.
- */
- template<typename... List>
- using type_list_diff_t = typename type_list_diff<List...>::type;
- /*! @brief Primary template isn't defined on purpose. */
- template<typename, template<typename...> class>
- struct type_list_transform;
- /**
- * @brief Applies a given _function_ to a type list and generate a new list.
- * @tparam Type Types provided by the type list.
- * @tparam Op Unary operation as template class with a type member named `type`.
- */
- template<typename... Type, template<typename...> class Op>
- struct type_list_transform<type_list<Type...>, Op> {
- /*! @brief Resulting type list after applying the transform function. */
- // NOLINTNEXTLINE(modernize-type-traits)
- using type = type_list<typename Op<Type>::type...>;
- };
- /**
- * @brief Helper type.
- * @tparam List Type list.
- * @tparam Op Unary operation as template class with a type member named `type`.
- */
- template<typename List, template<typename...> class Op>
- using type_list_transform_t = typename type_list_transform<List, Op>::type;
- /**
- * @brief A class to use to push around lists of constant values, nothing more.
- * @tparam Value Values provided by the value list.
- */
- template<auto... Value>
- struct value_list {
- /*! @brief Value list type. */
- using type = value_list;
- /*! @brief Compile-time number of elements in the value list. */
- static constexpr auto size = sizeof...(Value);
- };
- /*! @brief Primary template isn't defined on purpose. */
- template<std::size_t, typename>
- struct value_list_element;
- /**
- * @brief Provides compile-time indexed access to the values of a value list.
- * @tparam Index Index of the value to return.
- * @tparam Value First value provided by the value list.
- * @tparam Other Other values provided by the value list.
- */
- template<std::size_t Index, auto Value, auto... Other>
- struct value_list_element<Index, value_list<Value, Other...>>
- : value_list_element<Index - 1u, value_list<Other...>> {};
- /**
- * @brief Provides compile-time indexed access to the types of a type list.
- * @tparam Value First value provided by the value list.
- * @tparam Other Other values provided by the value list.
- */
- template<auto Value, auto... Other>
- struct value_list_element<0u, value_list<Value, Other...>> {
- /*! @brief Searched type. */
- using type = decltype(Value);
- /*! @brief Searched value. */
- static constexpr auto value = Value;
- };
- /**
- * @brief Helper type.
- * @tparam Index Index of the type to return.
- * @tparam List Value list to search into.
- */
- template<std::size_t Index, typename List>
- using value_list_element_t = typename value_list_element<Index, List>::type;
- /**
- * @brief Helper type.
- * @tparam Index Index of the value to return.
- * @tparam List Value list to search into.
- */
- template<std::size_t Index, typename List>
- inline constexpr auto value_list_element_v = value_list_element<Index, List>::value;
- /*! @brief Primary template isn't defined on purpose. */
- template<auto, typename>
- struct value_list_index;
- /**
- * @brief Provides compile-time type access to the values of a value list.
- * @tparam Value Value to look for and for which to return the index.
- * @tparam First First value provided by the value list.
- * @tparam Other Other values provided by the value list.
- */
- template<auto Value, auto First, auto... Other>
- struct value_list_index<Value, value_list<First, Other...>> {
- /*! @brief Unsigned integer type. */
- using value_type = std::size_t;
- /*! @brief Compile-time position of the given value in the sublist. */
- static constexpr value_type value = 1u + value_list_index<Value, value_list<Other...>>::value;
- };
- /**
- * @brief Provides compile-time type access to the values of a value list.
- * @tparam Value Value to look for and for which to return the index.
- * @tparam Other Other values provided by the value list.
- */
- template<auto Value, auto... Other>
- struct value_list_index<Value, value_list<Value, Other...>> {
- static_assert(value_list_index<Value, value_list<Other...>>::value == sizeof...(Other), "Non-unique type");
- /*! @brief Unsigned integer type. */
- using value_type = std::size_t;
- /*! @brief Compile-time position of the given value in the sublist. */
- static constexpr value_type value = 0u;
- };
- /**
- * @brief Provides compile-time type access to the values of a value list.
- * @tparam Value Value to look for and for which to return the index.
- */
- template<auto Value>
- struct value_list_index<Value, value_list<>> {
- /*! @brief Unsigned integer type. */
- using value_type = std::size_t;
- /*! @brief Compile-time position of the given type in the sublist. */
- static constexpr value_type value = 0u;
- };
- /**
- * @brief Helper variable template.
- * @tparam List Value list.
- * @tparam Value Value to look for and for which to return the index.
- */
- template<auto Value, typename List>
- inline constexpr std::size_t value_list_index_v = value_list_index<Value, List>::value;
- /**
- * @brief Concatenates multiple value lists.
- * @tparam Value Values provided by the first value list.
- * @tparam Other Values provided by the second value list.
- * @return A value list composed by the values of both the value lists.
- */
- template<auto... Value, auto... Other>
- constexpr value_list<Value..., Other...> operator+(value_list<Value...>, value_list<Other...>) {
- return {};
- }
- /*! @brief Primary template isn't defined on purpose. */
- template<typename...>
- struct value_list_cat;
- /*! @brief Concatenates multiple value lists. */
- template<>
- struct value_list_cat<> {
- /*! @brief A value list composed by the values of all the value lists. */
- using type = value_list<>;
- };
- /**
- * @brief Concatenates multiple value lists.
- * @tparam Value Values provided by the first value list.
- * @tparam Other Values provided by the second value list.
- * @tparam List Other value lists, if any.
- */
- template<auto... Value, auto... Other, typename... List>
- struct value_list_cat<value_list<Value...>, value_list<Other...>, List...> {
- /*! @brief A value list composed by the values of all the value lists. */
- using type = typename value_list_cat<value_list<Value..., Other...>, List...>::type;
- };
- /**
- * @brief Concatenates multiple value lists.
- * @tparam Value Values provided by the value list.
- */
- template<auto... Value>
- struct value_list_cat<value_list<Value...>> {
- /*! @brief A value list composed by the values of all the value lists. */
- using type = value_list<Value...>;
- };
- /**
- * @brief Helper type.
- * @tparam List Value lists to concatenate.
- */
- template<typename... List>
- using value_list_cat_t = typename value_list_cat<List...>::type;
- /*! @brief Primary template isn't defined on purpose. */
- template<typename>
- struct value_list_unique;
- /**
- * @brief Removes duplicates values from a value list.
- * @tparam Value One of the values provided by the given value list.
- * @tparam Other The other values provided by the given value list.
- */
- template<auto Value, auto... Other>
- struct value_list_unique<value_list<Value, Other...>> {
- /*! @brief A value list without duplicate types. */
- using type = std::conditional_t<
- ((Value == Other) || ...),
- typename value_list_unique<value_list<Other...>>::type,
- value_list_cat_t<value_list<Value>, typename value_list_unique<value_list<Other...>>::type>>;
- };
- /*! @brief Removes duplicates values from a value list. */
- template<>
- struct value_list_unique<value_list<>> {
- /*! @brief A value list without duplicate types. */
- using type = value_list<>;
- };
- /**
- * @brief Helper type.
- * @tparam Type A value list.
- */
- template<typename Type>
- using value_list_unique_t = typename value_list_unique<Type>::type;
- /**
- * @brief Provides the member constant `value` to true if a value list contains
- * a given value, false otherwise.
- * @tparam List Value list.
- * @tparam Value Value to look for.
- */
- template<typename List, auto Value>
- struct value_list_contains;
- /**
- * @copybrief value_list_contains
- * @tparam Value Values provided by the value list.
- * @tparam Other Value to look for.
- */
- template<auto... Value, auto Other>
- struct value_list_contains<value_list<Value...>, Other>
- : std::bool_constant<((Value == Other) || ...)> {};
- /**
- * @brief Helper variable template.
- * @tparam List Value list.
- * @tparam Value Value to look for.
- */
- template<typename List, auto Value>
- inline constexpr bool value_list_contains_v = value_list_contains<List, Value>::value;
- /*! @brief Primary template isn't defined on purpose. */
- template<typename...>
- struct value_list_diff;
- /**
- * @brief Computes the difference between two value lists.
- * @tparam Value Values provided by the first value list.
- * @tparam Other Values provided by the second value list.
- */
- template<auto... Value, auto... Other>
- struct value_list_diff<value_list<Value...>, value_list<Other...>> {
- /*! @brief A value list that is the difference between the two value lists. */
- using type = value_list_cat_t<std::conditional_t<value_list_contains_v<value_list<Other...>, Value>, value_list<>, value_list<Value>>...>;
- };
- /**
- * @brief Helper type.
- * @tparam List Value lists between which to compute the difference.
- */
- template<typename... List>
- using value_list_diff_t = typename value_list_diff<List...>::type;
- /*! @brief Same as std::is_invocable, but with tuples. */
- template<typename, typename>
- struct is_applicable: std::false_type {};
- /**
- * @copybrief is_applicable
- * @tparam Func A valid function type.
- * @tparam Tuple Tuple-like type.
- * @tparam Args The list of arguments to use to probe the function type.
- */
- template<typename Func, template<typename...> class Tuple, typename... Args>
- struct is_applicable<Func, Tuple<Args...>>: std::is_invocable<Func, Args...> {};
- /**
- * @copybrief is_applicable
- * @tparam Func A valid function type.
- * @tparam Tuple Tuple-like type.
- * @tparam Args The list of arguments to use to probe the function type.
- */
- template<typename Func, template<typename...> class Tuple, typename... Args>
- struct is_applicable<Func, const Tuple<Args...>>: std::is_invocable<Func, Args...> {};
- /**
- * @brief Helper variable template.
- * @tparam Func A valid function type.
- * @tparam Args The list of arguments to use to probe the function type.
- */
- template<typename Func, typename Args>
- inline constexpr bool is_applicable_v = is_applicable<Func, Args>::value;
- /*! @brief Same as std::is_invocable_r, but with tuples for arguments. */
- template<typename, typename, typename>
- struct is_applicable_r: std::false_type {};
- /**
- * @copybrief is_applicable_r
- * @tparam Ret The type to which the return type of the function should be
- * convertible.
- * @tparam Func A valid function type.
- * @tparam Args The list of arguments to use to probe the function type.
- */
- template<typename Ret, typename Func, typename... Args>
- struct is_applicable_r<Ret, Func, std::tuple<Args...>>: std::is_invocable_r<Ret, Func, Args...> {};
- /**
- * @brief Helper variable template.
- * @tparam Ret The type to which the return type of the function should be
- * convertible.
- * @tparam Func A valid function type.
- * @tparam Args The list of arguments to use to probe the function type.
- */
- template<typename Ret, typename Func, typename Args>
- inline constexpr bool is_applicable_r_v = is_applicable_r<Ret, Func, Args>::value;
- /**
- * @brief Provides the member constant `value` to true if a given type is
- * complete, false otherwise.
- * @tparam Type The type to test.
- */
- template<typename Type, typename = void>
- struct is_complete: std::false_type {};
- /*! @copydoc is_complete */
- template<typename Type>
- struct is_complete<Type, std::void_t<decltype(sizeof(Type))>>: std::true_type {};
- /**
- * @brief Helper variable template.
- * @tparam Type The type to test.
- */
- template<typename Type>
- inline constexpr bool is_complete_v = is_complete<Type>::value;
- /**
- * @brief Provides the member constant `value` to true if a given type is an
- * iterator, false otherwise.
- * @tparam Type The type to test.
- */
- template<typename Type, typename = void>
- struct is_iterator: std::false_type {};
- /*! @cond TURN_OFF_DOXYGEN */
- namespace internal {
- template<typename, typename = void>
- struct has_iterator_category: std::false_type {};
- template<typename Type>
- struct has_iterator_category<Type, std::void_t<typename std::iterator_traits<Type>::iterator_category>>: std::true_type {};
- } // namespace internal
- /*! @endcond */
- /*! @copydoc is_iterator */
- template<typename Type>
- struct is_iterator<Type, std::enable_if_t<!std::is_void_v<std::remove_const_t<std::remove_pointer_t<Type>>>>>
- : internal::has_iterator_category<Type> {};
- /**
- * @brief Helper variable template.
- * @tparam Type The type to test.
- */
- template<typename Type>
- inline constexpr bool is_iterator_v = is_iterator<Type>::value;
- /**
- * @brief Provides the member constant `value` to true if a given type is both
- * an empty and non-final class, false otherwise.
- * @tparam Type The type to test
- */
- template<typename Type>
- struct is_ebco_eligible
- : std::bool_constant<std::is_empty_v<Type> && !std::is_final_v<Type>> {};
- /**
- * @brief Helper variable template.
- * @tparam Type The type to test.
- */
- template<typename Type>
- inline constexpr bool is_ebco_eligible_v = is_ebco_eligible<Type>::value;
- /**
- * @brief Provides the member constant `value` to true if `Type::is_transparent`
- * is valid and denotes a type, false otherwise.
- * @tparam Type The type to test.
- */
- template<typename Type, typename = void>
- struct is_transparent: std::false_type {};
- /*! @copydoc is_transparent */
- template<typename Type>
- struct is_transparent<Type, std::void_t<typename Type::is_transparent>>: std::true_type {};
- /**
- * @brief Helper variable template.
- * @tparam Type The type to test.
- */
- template<typename Type>
- inline constexpr bool is_transparent_v = is_transparent<Type>::value;
- /*! @cond TURN_OFF_DOXYGEN */
- namespace internal {
- template<typename, typename = void>
- struct has_tuple_size_value: std::false_type {};
- template<typename Type>
- struct has_tuple_size_value<Type, std::void_t<decltype(std::tuple_size<const Type>::value)>>: std::true_type {};
- template<typename, typename = void>
- struct has_value_type: std::false_type {};
- template<typename Type>
- struct has_value_type<Type, std::void_t<typename Type::value_type>>: std::true_type {};
- template<typename>
- [[nodiscard]] constexpr bool dispatch_is_equality_comparable();
- template<typename Type, std::size_t... Index>
- [[nodiscard]] constexpr bool unpack_maybe_equality_comparable(std::index_sequence<Index...>) {
- return (dispatch_is_equality_comparable<std::tuple_element_t<Index, Type>>() && ...);
- }
- template<typename>
- [[nodiscard]] constexpr bool maybe_equality_comparable(char) {
- return false;
- }
- template<typename Type>
- [[nodiscard]] constexpr auto maybe_equality_comparable(int) -> decltype(std::declval<Type>() == std::declval<Type>()) {
- return true;
- }
- template<typename Type>
- [[nodiscard]] constexpr bool dispatch_is_equality_comparable() {
- // NOLINTBEGIN(modernize-use-transparent-functors)
- if constexpr(std::is_array_v<Type>) {
- return false;
- } else if constexpr(is_complete_v<std::tuple_size<std::remove_const_t<Type>>>) {
- if constexpr(has_tuple_size_value<Type>::value) {
- return maybe_equality_comparable<Type>(0) && unpack_maybe_equality_comparable<Type>(std::make_index_sequence<std::tuple_size<Type>::value>{});
- } else {
- return maybe_equality_comparable<Type>(0);
- }
- } else if constexpr(has_value_type<Type>::value) {
- if constexpr(is_iterator_v<Type> || std::is_same_v<typename Type::value_type, Type> || dispatch_is_equality_comparable<typename Type::value_type>()) {
- return maybe_equality_comparable<Type>(0);
- } else {
- return false;
- }
- } else {
- return maybe_equality_comparable<Type>(0);
- }
- // NOLINTEND(modernize-use-transparent-functors)
- }
- } // namespace internal
- /*! @endcond */
- /**
- * @brief Provides the member constant `value` to true if a given type is
- * equality comparable, false otherwise.
- * @tparam Type The type to test.
- */
- template<typename Type>
- struct is_equality_comparable: std::bool_constant<internal::dispatch_is_equality_comparable<Type>()> {};
- /*! @copydoc is_equality_comparable */
- template<typename Type>
- struct is_equality_comparable<const Type>: is_equality_comparable<Type> {};
- /**
- * @brief Helper variable template.
- * @tparam Type The type to test.
- */
- template<typename Type>
- inline constexpr bool is_equality_comparable_v = is_equality_comparable<Type>::value;
- /**
- * @brief Transcribes the constness of a type to another type.
- * @tparam To The type to which to transcribe the constness.
- * @tparam From The type from which to transcribe the constness.
- */
- template<typename To, typename From>
- struct constness_as {
- /*! @brief The type resulting from the transcription of the constness. */
- using type = std::remove_const_t<To>;
- };
- /*! @copydoc constness_as */
- template<typename To, typename From>
- struct constness_as<To, const From> {
- /*! @brief The type resulting from the transcription of the constness. */
- using type = const To;
- };
- /**
- * @brief Alias template to facilitate the transcription of the constness.
- * @tparam To The type to which to transcribe the constness.
- * @tparam From The type from which to transcribe the constness.
- */
- template<typename To, typename From>
- using constness_as_t = typename constness_as<To, From>::type;
- /**
- * @brief Extracts the class of a non-static member object or function.
- * @tparam Member A pointer to a non-static member object or function.
- */
- template<typename Member>
- class member_class {
- static_assert(std::is_member_pointer_v<Member>, "Invalid pointer type to non-static member object or function");
- template<typename Class, typename Ret, typename... Args>
- static Class *clazz(Ret (Class::*)(Args...));
- template<typename Class, typename Ret, typename... Args>
- static Class *clazz(Ret (Class::*)(Args...) const);
- template<typename Class, typename Type>
- static Class *clazz(Type Class::*);
- public:
- /*! @brief The class of the given non-static member object or function. */
- using type = std::remove_pointer_t<decltype(clazz(std::declval<Member>()))>;
- };
- /**
- * @brief Helper type.
- * @tparam Member A pointer to a non-static member object or function.
- */
- template<typename Member>
- using member_class_t = typename member_class<Member>::type;
- /**
- * @brief Extracts the n-th argument of a _callable_ type.
- * @tparam Index The index of the argument to extract.
- * @tparam Candidate A valid _callable_ type.
- */
- template<std::size_t Index, typename Candidate>
- class nth_argument {
- template<typename Ret, typename... Args>
- static constexpr type_list<Args...> pick_up(Ret (*)(Args...));
- template<typename Ret, typename Class, typename... Args>
- static constexpr type_list<Args...> pick_up(Ret (Class ::*)(Args...));
- template<typename Ret, typename Class, typename... Args>
- static constexpr type_list<Args...> pick_up(Ret (Class ::*)(Args...) const);
- template<typename Type, typename Class>
- static constexpr type_list<Type> pick_up(Type Class ::*);
- template<typename Type>
- static constexpr decltype(pick_up(&Type::operator())) pick_up(Type &&);
- public:
- /*! @brief N-th argument of the _callable_ type. */
- using type = type_list_element_t<Index, decltype(pick_up(std::declval<Candidate>()))>;
- };
- /**
- * @brief Helper type.
- * @tparam Index The index of the argument to extract.
- * @tparam Candidate A valid function, member function or data member type.
- */
- template<std::size_t Index, typename Candidate>
- using nth_argument_t = typename nth_argument<Index, Candidate>::type;
- } // namespace entt
- template<typename... Type>
- struct std::tuple_size<entt::type_list<Type...>>: std::integral_constant<std::size_t, entt::type_list<Type...>::size> {};
- template<std::size_t Index, typename... Type>
- struct std::tuple_element<Index, entt::type_list<Type...>>: entt::type_list_element<Index, entt::type_list<Type...>> {};
- template<auto... Value>
- struct std::tuple_size<entt::value_list<Value...>>: std::integral_constant<std::size_t, entt::value_list<Value...>::size> {};
- template<std::size_t Index, auto... Value>
- struct std::tuple_element<Index, entt::value_list<Value...>>: entt::value_list_element<Index, entt::value_list<Value...>> {};
- #endif
- namespace entt {
- /*! @cond TURN_OFF_DOXYGEN */
- namespace internal {
- template<typename Type, std::size_t, typename = void>
- struct compressed_pair_element {
- using reference = Type &;
- using const_reference = const Type &;
- template<typename Dummy = Type, typename = std::enable_if_t<std::is_default_constructible_v<Dummy>>>
- // NOLINTNEXTLINE(modernize-use-equals-default)
- constexpr compressed_pair_element() noexcept(std::is_nothrow_default_constructible_v<Type>) {}
- template<typename Arg, typename = std::enable_if_t<!std::is_same_v<std::remove_const_t<std::remove_reference_t<Arg>>, compressed_pair_element>>>
- constexpr compressed_pair_element(Arg &&arg) noexcept(std::is_nothrow_constructible_v<Type, Arg>)
- : value{std::forward<Arg>(arg)} {}
- template<typename... Args, std::size_t... Index>
- constexpr compressed_pair_element(std::tuple<Args...> args, std::index_sequence<Index...>) noexcept(std::is_nothrow_constructible_v<Type, Args...>)
- : value{std::forward<Args>(std::get<Index>(args))...} {}
- [[nodiscard]] constexpr reference get() noexcept {
- return value;
- }
- [[nodiscard]] constexpr const_reference get() const noexcept {
- return value;
- }
- private:
- Type value{};
- };
- template<typename Type, std::size_t Tag>
- struct compressed_pair_element<Type, Tag, std::enable_if_t<is_ebco_eligible_v<Type>>>: Type {
- using reference = Type &;
- using const_reference = const Type &;
- using base_type = Type;
- template<typename Dummy = Type, typename = std::enable_if_t<std::is_default_constructible_v<Dummy>>>
- constexpr compressed_pair_element() noexcept(std::is_nothrow_default_constructible_v<base_type>)
- : base_type{} {}
- template<typename Arg, typename = std::enable_if_t<!std::is_same_v<std::remove_const_t<std::remove_reference_t<Arg>>, compressed_pair_element>>>
- constexpr compressed_pair_element(Arg &&arg) noexcept(std::is_nothrow_constructible_v<base_type, Arg>)
- : base_type{std::forward<Arg>(arg)} {}
- template<typename... Args, std::size_t... Index>
- constexpr compressed_pair_element(std::tuple<Args...> args, std::index_sequence<Index...>) noexcept(std::is_nothrow_constructible_v<base_type, Args...>)
- : base_type{std::forward<Args>(std::get<Index>(args))...} {}
- [[nodiscard]] constexpr reference get() noexcept {
- return *this;
- }
- [[nodiscard]] constexpr const_reference get() const noexcept {
- return *this;
- }
- };
- } // namespace internal
- /*! @endcond */
- /**
- * @brief A compressed pair.
- *
- * A pair that exploits the _Empty Base Class Optimization_ (or _EBCO_) to
- * reduce its final size to a minimum.
- *
- * @tparam First The type of the first element that the pair stores.
- * @tparam Second The type of the second element that the pair stores.
- */
- template<typename First, typename Second>
- class compressed_pair final
- : internal::compressed_pair_element<First, 0u>,
- internal::compressed_pair_element<Second, 1u> {
- using first_base = internal::compressed_pair_element<First, 0u>;
- using second_base = internal::compressed_pair_element<Second, 1u>;
- public:
- /*! @brief The type of the first element that the pair stores. */
- using first_type = First;
- /*! @brief The type of the second element that the pair stores. */
- using second_type = Second;
- /**
- * @brief Default constructor, conditionally enabled.
- *
- * This constructor is only available when the types that the pair stores
- * are both at least default constructible.
- *
- * @tparam Dummy Dummy template parameter used for internal purposes.
- */
- template<bool Dummy = true, typename = std::enable_if_t<Dummy && std::is_default_constructible_v<first_type> && std::is_default_constructible_v<second_type>>>
- constexpr compressed_pair() noexcept(std::is_nothrow_default_constructible_v<first_base> && std::is_nothrow_default_constructible_v<second_base>)
- : first_base{},
- second_base{} {}
- /**
- * @brief Copy constructor.
- * @param other The instance to copy from.
- */
- constexpr compressed_pair(const compressed_pair &other) = default;
- /**
- * @brief Move constructor.
- * @param other The instance to move from.
- */
- constexpr compressed_pair(compressed_pair &&other) noexcept = default;
- /**
- * @brief Constructs a pair from its values.
- * @tparam Arg Type of value to use to initialize the first element.
- * @tparam Other Type of value to use to initialize the second element.
- * @param arg Value to use to initialize the first element.
- * @param other Value to use to initialize the second element.
- */
- template<typename Arg, typename Other>
- constexpr compressed_pair(Arg &&arg, Other &&other) noexcept(std::is_nothrow_constructible_v<first_base, Arg> && std::is_nothrow_constructible_v<second_base, Other>)
- : first_base{std::forward<Arg>(arg)},
- second_base{std::forward<Other>(other)} {}
- /**
- * @brief Constructs a pair by forwarding the arguments to its parts.
- * @tparam Args Types of arguments to use to initialize the first element.
- * @tparam Other Types of arguments to use to initialize the second element.
- * @param args Arguments to use to initialize the first element.
- * @param other Arguments to use to initialize the second element.
- */
- template<typename... Args, typename... Other>
- constexpr compressed_pair(std::piecewise_construct_t, std::tuple<Args...> args, std::tuple<Other...> other) noexcept(std::is_nothrow_constructible_v<first_base, Args...> && std::is_nothrow_constructible_v<second_base, Other...>)
- : first_base{std::move(args), std::index_sequence_for<Args...>{}},
- second_base{std::move(other), std::index_sequence_for<Other...>{}} {}
- /*! @brief Default destructor. */
- ~compressed_pair() = default;
- /**
- * @brief Copy assignment operator.
- * @param other The instance to copy from.
- * @return This compressed pair object.
- */
- constexpr compressed_pair &operator=(const compressed_pair &other) = default;
- /**
- * @brief Move assignment operator.
- * @param other The instance to move from.
- * @return This compressed pair object.
- */
- constexpr compressed_pair &operator=(compressed_pair &&other) noexcept = default;
- /**
- * @brief Returns the first element that a pair stores.
- * @return The first element that a pair stores.
- */
- [[nodiscard]] constexpr first_type &first() noexcept {
- return static_cast<first_base &>(*this).get();
- }
- /*! @copydoc first */
- [[nodiscard]] constexpr const first_type &first() const noexcept {
- return static_cast<const first_base &>(*this).get();
- }
- /**
- * @brief Returns the second element that a pair stores.
- * @return The second element that a pair stores.
- */
- [[nodiscard]] constexpr second_type &second() noexcept {
- return static_cast<second_base &>(*this).get();
- }
- /*! @copydoc second */
- [[nodiscard]] constexpr const second_type &second() const noexcept {
- return static_cast<const second_base &>(*this).get();
- }
- /**
- * @brief Swaps two compressed pair objects.
- * @param other The compressed pair to swap with.
- */
- constexpr void swap(compressed_pair &other) noexcept {
- using std::swap;
- swap(first(), other.first());
- swap(second(), other.second());
- }
- /**
- * @brief Extracts an element from the compressed pair.
- * @tparam Index An integer value that is either 0 or 1.
- * @return Returns a reference to the first element if `Index` is 0 and a
- * reference to the second element if `Index` is 1.
- */
- template<std::size_t Index>
- [[nodiscard]] constexpr decltype(auto) get() noexcept {
- if constexpr(Index == 0u) {
- return first();
- } else {
- static_assert(Index == 1u, "Index out of bounds");
- return second();
- }
- }
- /*! @copydoc get */
- template<std::size_t Index>
- [[nodiscard]] constexpr decltype(auto) get() const noexcept {
- if constexpr(Index == 0u) {
- return first();
- } else {
- static_assert(Index == 1u, "Index out of bounds");
- return second();
- }
- }
- };
- /**
- * @brief Deduction guide.
- * @tparam Type Type of value to use to initialize the first element.
- * @tparam Other Type of value to use to initialize the second element.
- */
- template<typename Type, typename Other>
- compressed_pair(Type &&, Other &&) -> compressed_pair<std::decay_t<Type>, std::decay_t<Other>>;
- /**
- * @brief Swaps two compressed pair objects.
- * @tparam First The type of the first element that the pairs store.
- * @tparam Second The type of the second element that the pairs store.
- * @param lhs A valid compressed pair object.
- * @param rhs A valid compressed pair object.
- */
- template<typename First, typename Second>
- constexpr void swap(compressed_pair<First, Second> &lhs, compressed_pair<First, Second> &rhs) noexcept {
- lhs.swap(rhs);
- }
- } // namespace entt
- namespace std {
- /**
- * @brief `std::tuple_size` specialization for `compressed_pair`s.
- * @tparam First The type of the first element that the pair stores.
- * @tparam Second The type of the second element that the pair stores.
- */
- template<typename First, typename Second>
- struct tuple_size<entt::compressed_pair<First, Second>>: integral_constant<size_t, 2u> {};
- /**
- * @brief `std::tuple_element` specialization for `compressed_pair`s.
- * @tparam Index The index of the type to return.
- * @tparam First The type of the first element that the pair stores.
- * @tparam Second The type of the second element that the pair stores.
- */
- template<size_t Index, typename First, typename Second>
- struct tuple_element<Index, entt::compressed_pair<First, Second>>: conditional<Index == 0u, First, Second> {
- static_assert(Index < 2u, "Index out of bounds");
- };
- } // namespace std
- #endif
- // #include "../core/iterator.hpp"
- #ifndef ENTT_CORE_ITERATOR_HPP
- #define ENTT_CORE_ITERATOR_HPP
- #include <iterator>
- #include <memory>
- #include <type_traits>
- #include <utility>
- namespace entt {
- /**
- * @brief Helper type to use as pointer with input iterators.
- * @tparam Type of wrapped value.
- */
- template<typename Type>
- struct input_iterator_pointer final {
- /*! @brief Value type. */
- using value_type = Type;
- /*! @brief Pointer type. */
- using pointer = Type *;
- /*! @brief Reference type. */
- using reference = Type &;
- /**
- * @brief Constructs a proxy object by move.
- * @param val Value to use to initialize the proxy object.
- */
- constexpr input_iterator_pointer(value_type &&val) noexcept(std::is_nothrow_move_constructible_v<value_type>)
- : value{std::move(val)} {}
- /**
- * @brief Access operator for accessing wrapped values.
- * @return A pointer to the wrapped value.
- */
- [[nodiscard]] constexpr pointer operator->() noexcept {
- return std::addressof(value);
- }
- /**
- * @brief Dereference operator for accessing wrapped values.
- * @return A reference to the wrapped value.
- */
- [[nodiscard]] constexpr reference operator*() noexcept {
- return value;
- }
- private:
- Type value;
- };
- /**
- * @brief Plain iota iterator (waiting for C++20).
- * @tparam Type Value type.
- */
- template<typename Type>
- class iota_iterator final {
- static_assert(std::is_integral_v<Type>, "Not an integral type");
- public:
- /*! @brief Value type, likely an integral one. */
- using value_type = Type;
- /*! @brief Invalid pointer type. */
- using pointer = void;
- /*! @brief Non-reference type, same as value type. */
- using reference = value_type;
- /*! @brief Difference type. */
- using difference_type = std::ptrdiff_t;
- /*! @brief Iterator category. */
- using iterator_category = std::input_iterator_tag;
- /*! @brief Default constructor. */
- constexpr iota_iterator() noexcept
- : current{} {}
- /**
- * @brief Constructs an iota iterator from a given value.
- * @param init The initial value assigned to the iota iterator.
- */
- constexpr iota_iterator(const value_type init) noexcept
- : current{init} {}
- /**
- * @brief Pre-increment operator.
- * @return This iota iterator.
- */
- constexpr iota_iterator &operator++() noexcept {
- return ++current, *this;
- }
- /**
- * @brief Post-increment operator.
- * @return This iota iterator.
- */
- constexpr iota_iterator operator++(int) noexcept {
- const iota_iterator orig = *this;
- return ++(*this), orig;
- }
- /**
- * @brief Dereference operator.
- * @return The underlying value.
- */
- [[nodiscard]] constexpr reference operator*() const noexcept {
- return current;
- }
- private:
- value_type current;
- };
- /**
- * @brief Comparison operator.
- * @tparam Type Value type of the iota iterator.
- * @param lhs A properly initialized iota iterator.
- * @param rhs A properly initialized iota iterator.
- * @return True if the two iterators are identical, false otherwise.
- */
- template<typename Type>
- [[nodiscard]] constexpr bool operator==(const iota_iterator<Type> &lhs, const iota_iterator<Type> &rhs) noexcept {
- return *lhs == *rhs;
- }
- /**
- * @brief Comparison operator.
- * @tparam Type Value type of the iota iterator.
- * @param lhs A properly initialized iota iterator.
- * @param rhs A properly initialized iota iterator.
- * @return True if the two iterators differ, false otherwise.
- */
- template<typename Type>
- [[nodiscard]] constexpr bool operator!=(const iota_iterator<Type> &lhs, const iota_iterator<Type> &rhs) noexcept {
- return !(lhs == rhs);
- }
- /**
- * @brief Utility class to create an iterable object from a pair of iterators.
- * @tparam It Type of iterator.
- * @tparam Sentinel Type of sentinel.
- */
- template<typename It, typename Sentinel = It>
- struct iterable_adaptor final {
- /*! @brief Value type. */
- using value_type = typename std::iterator_traits<It>::value_type;
- /*! @brief Iterator type. */
- using iterator = It;
- /*! @brief Sentinel type. */
- using sentinel = Sentinel;
- /*! @brief Default constructor. */
- constexpr iterable_adaptor() noexcept(std::is_nothrow_default_constructible_v<iterator> && std::is_nothrow_default_constructible_v<sentinel>)
- : first{},
- last{} {}
- /**
- * @brief Creates an iterable object from a pair of iterators.
- * @param from Begin iterator.
- * @param to End iterator.
- */
- constexpr iterable_adaptor(iterator from, sentinel to) noexcept(std::is_nothrow_move_constructible_v<iterator> && std::is_nothrow_move_constructible_v<sentinel>)
- : first{std::move(from)},
- last{std::move(to)} {}
- /**
- * @brief Returns an iterator to the beginning.
- * @return An iterator to the first element of the range.
- */
- [[nodiscard]] constexpr iterator begin() const noexcept {
- return first;
- }
- /**
- * @brief Returns an iterator to the end.
- * @return An iterator to the element following the last element of the
- * range.
- */
- [[nodiscard]] constexpr sentinel end() const noexcept {
- return last;
- }
- /*! @copydoc begin */
- [[nodiscard]] constexpr iterator cbegin() const noexcept {
- return begin();
- }
- /*! @copydoc end */
- [[nodiscard]] constexpr sentinel cend() const noexcept {
- return end();
- }
- private:
- It first;
- Sentinel last;
- };
- } // namespace entt
- #endif
- // #include "../core/memory.hpp"
- #ifndef ENTT_CORE_MEMORY_HPP
- #define ENTT_CORE_MEMORY_HPP
- #include <cstddef>
- #include <memory>
- #include <tuple>
- #include <type_traits>
- #include <utility>
- // #include "../config/config.h"
- namespace entt {
- /**
- * @brief Unwraps fancy pointers, does nothing otherwise (waiting for C++20).
- * @tparam Type Pointer type.
- * @param ptr Fancy or raw pointer.
- * @return A raw pointer that represents the address of the original pointer.
- */
- template<typename Type>
- [[nodiscard]] constexpr auto to_address(Type &&ptr) noexcept {
- if constexpr(std::is_pointer_v<std::decay_t<Type>>) {
- return ptr;
- } else {
- return to_address(std::forward<Type>(ptr).operator->());
- }
- }
- /**
- * @brief Utility function to design allocation-aware containers.
- * @tparam Allocator Type of allocator.
- * @param lhs A valid allocator.
- * @param rhs Another valid allocator.
- */
- template<typename Allocator>
- constexpr void propagate_on_container_copy_assignment([[maybe_unused]] Allocator &lhs, [[maybe_unused]] Allocator &rhs) noexcept {
- if constexpr(std::allocator_traits<Allocator>::propagate_on_container_copy_assignment::value) {
- lhs = rhs;
- }
- }
- /**
- * @brief Utility function to design allocation-aware containers.
- * @tparam Allocator Type of allocator.
- * @param lhs A valid allocator.
- * @param rhs Another valid allocator.
- */
- template<typename Allocator>
- constexpr void propagate_on_container_move_assignment([[maybe_unused]] Allocator &lhs, [[maybe_unused]] Allocator &rhs) noexcept {
- if constexpr(std::allocator_traits<Allocator>::propagate_on_container_move_assignment::value) {
- lhs = std::move(rhs);
- }
- }
- /**
- * @brief Utility function to design allocation-aware containers.
- * @tparam Allocator Type of allocator.
- * @param lhs A valid allocator.
- * @param rhs Another valid allocator.
- */
- template<typename Allocator>
- constexpr void propagate_on_container_swap([[maybe_unused]] Allocator &lhs, [[maybe_unused]] Allocator &rhs) noexcept {
- if constexpr(std::allocator_traits<Allocator>::propagate_on_container_swap::value) {
- using std::swap;
- swap(lhs, rhs);
- } else {
- ENTT_ASSERT_CONSTEXPR(lhs == rhs, "Cannot swap the containers");
- }
- }
- /**
- * @brief Deleter for allocator-aware unique pointers (waiting for C++20).
- * @tparam Allocator Type of allocator used to manage memory and elements.
- */
- template<typename Allocator>
- struct allocation_deleter: private Allocator {
- /*! @brief Allocator type. */
- using allocator_type = Allocator;
- /*! @brief Pointer type. */
- using pointer = typename std::allocator_traits<Allocator>::pointer;
- /**
- * @brief Inherited constructors.
- * @param alloc The allocator to use.
- */
- constexpr allocation_deleter(const allocator_type &alloc) noexcept(std::is_nothrow_copy_constructible_v<allocator_type>)
- : Allocator{alloc} {}
- /**
- * @brief Destroys the pointed object and deallocates its memory.
- * @param ptr A valid pointer to an object of the given type.
- */
- constexpr void operator()(pointer ptr) noexcept(std::is_nothrow_destructible_v<typename allocator_type::value_type>) {
- using alloc_traits = std::allocator_traits<Allocator>;
- alloc_traits::destroy(*this, to_address(ptr));
- alloc_traits::deallocate(*this, ptr, 1u);
- }
- };
- /**
- * @brief Allows `std::unique_ptr` to use allocators (waiting for C++20).
- * @tparam Type Type of object to allocate for and to construct.
- * @tparam Allocator Type of allocator used to manage memory and elements.
- * @tparam Args Types of arguments to use to construct the object.
- * @param allocator The allocator to use.
- * @param args Parameters to use to construct the object.
- * @return A properly initialized unique pointer with a custom deleter.
- */
- template<typename Type, typename Allocator, typename... Args>
- ENTT_CONSTEXPR auto allocate_unique(Allocator &allocator, Args &&...args) {
- static_assert(!std::is_array_v<Type>, "Array types are not supported");
- using alloc_traits = typename std::allocator_traits<Allocator>::template rebind_traits<Type>;
- using allocator_type = typename alloc_traits::allocator_type;
- allocator_type alloc{allocator};
- auto ptr = alloc_traits::allocate(alloc, 1u);
- ENTT_TRY {
- alloc_traits::construct(alloc, to_address(ptr), std::forward<Args>(args)...);
- }
- ENTT_CATCH {
- alloc_traits::deallocate(alloc, ptr, 1u);
- ENTT_THROW;
- }
- return std::unique_ptr<Type, allocation_deleter<allocator_type>>{ptr, alloc};
- }
- /*! @cond TURN_OFF_DOXYGEN */
- namespace internal {
- template<typename Type>
- struct uses_allocator_construction {
- template<typename Allocator, typename... Params>
- static constexpr auto args([[maybe_unused]] const Allocator &allocator, Params &&...params) noexcept {
- if constexpr(!std::uses_allocator_v<Type, Allocator> && std::is_constructible_v<Type, Params...>) {
- return std::forward_as_tuple(std::forward<Params>(params)...);
- } else {
- static_assert(std::uses_allocator_v<Type, Allocator>, "Ill-formed request");
- if constexpr(std::is_constructible_v<Type, std::allocator_arg_t, const Allocator &, Params...>) {
- return std::tuple<std::allocator_arg_t, const Allocator &, Params &&...>{std::allocator_arg, allocator, std::forward<Params>(params)...};
- } else {
- static_assert(std::is_constructible_v<Type, Params..., const Allocator &>, "Ill-formed request");
- return std::forward_as_tuple(std::forward<Params>(params)..., allocator);
- }
- }
- }
- };
- template<typename Type, typename Other>
- struct uses_allocator_construction<std::pair<Type, Other>> {
- using type = std::pair<Type, Other>;
- template<typename Allocator, typename First, typename Second>
- static constexpr auto args(const Allocator &allocator, std::piecewise_construct_t, First &&first, Second &&second) noexcept {
- return std::make_tuple(
- std::piecewise_construct,
- std::apply([&allocator](auto &&...curr) { return uses_allocator_construction<Type>::args(allocator, std::forward<decltype(curr)>(curr)...); }, std::forward<First>(first)),
- std::apply([&allocator](auto &&...curr) { return uses_allocator_construction<Other>::args(allocator, std::forward<decltype(curr)>(curr)...); }, std::forward<Second>(second)));
- }
- template<typename Allocator>
- static constexpr auto args(const Allocator &allocator) noexcept {
- return uses_allocator_construction<type>::args(allocator, std::piecewise_construct, std::tuple<>{}, std::tuple<>{});
- }
- template<typename Allocator, typename First, typename Second>
- static constexpr auto args(const Allocator &allocator, First &&first, Second &&second) noexcept {
- return uses_allocator_construction<type>::args(allocator, std::piecewise_construct, std::forward_as_tuple(std::forward<First>(first)), std::forward_as_tuple(std::forward<Second>(second)));
- }
- template<typename Allocator, typename First, typename Second>
- static constexpr auto args(const Allocator &allocator, const std::pair<First, Second> &value) noexcept {
- return uses_allocator_construction<type>::args(allocator, std::piecewise_construct, std::forward_as_tuple(value.first), std::forward_as_tuple(value.second));
- }
- template<typename Allocator, typename First, typename Second>
- static constexpr auto args(const Allocator &allocator, std::pair<First, Second> &&value) noexcept {
- return uses_allocator_construction<type>::args(allocator, std::piecewise_construct, std::forward_as_tuple(std::move(value.first)), std::forward_as_tuple(std::move(value.second)));
- }
- };
- } // namespace internal
- /*! @endcond */
- /**
- * @brief Uses-allocator construction utility (waiting for C++20).
- *
- * Primarily intended for internal use. Prepares the argument list needed to
- * create an object of a given type by means of uses-allocator construction.
- *
- * @tparam Type Type to return arguments for.
- * @tparam Allocator Type of allocator used to manage memory and elements.
- * @tparam Args Types of arguments to use to construct the object.
- * @param allocator The allocator to use.
- * @param args Parameters to use to construct the object.
- * @return The arguments needed to create an object of the given type.
- */
- template<typename Type, typename Allocator, typename... Args>
- constexpr auto uses_allocator_construction_args(const Allocator &allocator, Args &&...args) noexcept {
- return internal::uses_allocator_construction<Type>::args(allocator, std::forward<Args>(args)...);
- }
- /**
- * @brief Uses-allocator construction utility (waiting for C++20).
- *
- * Primarily intended for internal use. Creates an object of a given type by
- * means of uses-allocator construction.
- *
- * @tparam Type Type of object to create.
- * @tparam Allocator Type of allocator used to manage memory and elements.
- * @tparam Args Types of arguments to use to construct the object.
- * @param allocator The allocator to use.
- * @param args Parameters to use to construct the object.
- * @return A newly created object of the given type.
- */
- template<typename Type, typename Allocator, typename... Args>
- constexpr Type make_obj_using_allocator(const Allocator &allocator, Args &&...args) {
- return std::make_from_tuple<Type>(internal::uses_allocator_construction<Type>::args(allocator, std::forward<Args>(args)...));
- }
- /**
- * @brief Uses-allocator construction utility (waiting for C++20).
- *
- * Primarily intended for internal use. Creates an object of a given type by
- * means of uses-allocator construction at an uninitialized memory location.
- *
- * @tparam Type Type of object to create.
- * @tparam Allocator Type of allocator used to manage memory and elements.
- * @tparam Args Types of arguments to use to construct the object.
- * @param value Memory location in which to place the object.
- * @param allocator The allocator to use.
- * @param args Parameters to use to construct the object.
- * @return A pointer to the newly created object of the given type.
- */
- template<typename Type, typename Allocator, typename... Args>
- constexpr Type *uninitialized_construct_using_allocator(Type *value, const Allocator &allocator, Args &&...args) {
- return std::apply([value](auto &&...curr) { return ::new(value) Type(std::forward<decltype(curr)>(curr)...); }, internal::uses_allocator_construction<Type>::args(allocator, std::forward<Args>(args)...));
- }
- } // namespace entt
- #endif
- // #include "../core/type_traits.hpp"
- #ifndef ENTT_CORE_TYPE_TRAITS_HPP
- #define ENTT_CORE_TYPE_TRAITS_HPP
- #include <cstddef>
- #include <iterator>
- #include <tuple>
- #include <type_traits>
- #include <utility>
- // #include "../config/config.h"
- // #include "fwd.hpp"
- namespace entt {
- /**
- * @brief Utility class to disambiguate overloaded functions.
- * @tparam N Number of choices available.
- */
- template<std::size_t N>
- struct choice_t
- // unfortunately, doxygen cannot parse such a construct
- : /*! @cond TURN_OFF_DOXYGEN */ choice_t<N - 1> /*! @endcond */
- {};
- /*! @copybrief choice_t */
- template<>
- struct choice_t<0> {};
- /**
- * @brief Variable template for the choice trick.
- * @tparam N Number of choices available.
- */
- template<std::size_t N>
- inline constexpr choice_t<N> choice{};
- /**
- * @brief Identity type trait.
- *
- * Useful to establish non-deduced contexts in template argument deduction
- * (waiting for C++20) or to provide types through function arguments.
- *
- * @tparam Type A type.
- */
- template<typename Type>
- struct type_identity {
- /*! @brief Identity type. */
- using type = Type;
- };
- /**
- * @brief Helper type.
- * @tparam Type A type.
- */
- template<typename Type>
- using type_identity_t = typename type_identity<Type>::type;
- /**
- * @brief A type-only `sizeof` wrapper that returns 0 where `sizeof` complains.
- * @tparam Type The type of which to return the size.
- */
- template<typename Type, typename = void>
- struct size_of: std::integral_constant<std::size_t, 0u> {};
- /*! @copydoc size_of */
- template<typename Type>
- struct size_of<Type, std::void_t<decltype(sizeof(Type))>>
- // NOLINTNEXTLINE(bugprone-sizeof-expression)
- : std::integral_constant<std::size_t, sizeof(Type)> {};
- /**
- * @brief Helper variable template.
- * @tparam Type The type of which to return the size.
- */
- template<typename Type>
- inline constexpr std::size_t size_of_v = size_of<Type>::value;
- /**
- * @brief Using declaration to be used to _repeat_ the same type a number of
- * times equal to the size of a given parameter pack.
- * @tparam Type A type to repeat.
- */
- template<typename Type, typename>
- using unpack_as_type = Type;
- /**
- * @brief Helper variable template to be used to _repeat_ the same value a
- * number of times equal to the size of a given parameter pack.
- * @tparam Value A value to repeat.
- */
- template<auto Value, typename>
- inline constexpr auto unpack_as_value = Value;
- /**
- * @brief Wraps a static constant.
- * @tparam Value A static constant.
- */
- template<auto Value>
- using integral_constant = std::integral_constant<decltype(Value), Value>;
- /**
- * @brief Alias template to facilitate the creation of named values.
- * @tparam Value A constant value at least convertible to `id_type`.
- */
- template<id_type Value>
- using tag = integral_constant<Value>;
- /**
- * @brief A class to use to push around lists of types, nothing more.
- * @tparam Type Types provided by the type list.
- */
- template<typename... Type>
- struct type_list {
- /*! @brief Type list type. */
- using type = type_list;
- /*! @brief Compile-time number of elements in the type list. */
- static constexpr auto size = sizeof...(Type);
- };
- /*! @brief Primary template isn't defined on purpose. */
- template<std::size_t, typename>
- struct type_list_element;
- /**
- * @brief Provides compile-time indexed access to the types of a type list.
- * @tparam Index Index of the type to return.
- * @tparam First First type provided by the type list.
- * @tparam Other Other types provided by the type list.
- */
- template<std::size_t Index, typename First, typename... Other>
- struct type_list_element<Index, type_list<First, Other...>>
- : type_list_element<Index - 1u, type_list<Other...>> {};
- /**
- * @brief Provides compile-time indexed access to the types of a type list.
- * @tparam First First type provided by the type list.
- * @tparam Other Other types provided by the type list.
- */
- template<typename First, typename... Other>
- struct type_list_element<0u, type_list<First, Other...>> {
- /*! @brief Searched type. */
- using type = First;
- };
- /**
- * @brief Helper type.
- * @tparam Index Index of the type to return.
- * @tparam List Type list to search into.
- */
- template<std::size_t Index, typename List>
- using type_list_element_t = typename type_list_element<Index, List>::type;
- /*! @brief Primary template isn't defined on purpose. */
- template<typename, typename>
- struct type_list_index;
- /**
- * @brief Provides compile-time type access to the types of a type list.
- * @tparam Type Type to look for and for which to return the index.
- * @tparam First First type provided by the type list.
- * @tparam Other Other types provided by the type list.
- */
- template<typename Type, typename First, typename... Other>
- struct type_list_index<Type, type_list<First, Other...>> {
- /*! @brief Unsigned integer type. */
- using value_type = std::size_t;
- /*! @brief Compile-time position of the given type in the sublist. */
- static constexpr value_type value = 1u + type_list_index<Type, type_list<Other...>>::value;
- };
- /**
- * @brief Provides compile-time type access to the types of a type list.
- * @tparam Type Type to look for and for which to return the index.
- * @tparam Other Other types provided by the type list.
- */
- template<typename Type, typename... Other>
- struct type_list_index<Type, type_list<Type, Other...>> {
- static_assert(type_list_index<Type, type_list<Other...>>::value == sizeof...(Other), "Non-unique type");
- /*! @brief Unsigned integer type. */
- using value_type = std::size_t;
- /*! @brief Compile-time position of the given type in the sublist. */
- static constexpr value_type value = 0u;
- };
- /**
- * @brief Provides compile-time type access to the types of a type list.
- * @tparam Type Type to look for and for which to return the index.
- */
- template<typename Type>
- struct type_list_index<Type, type_list<>> {
- /*! @brief Unsigned integer type. */
- using value_type = std::size_t;
- /*! @brief Compile-time position of the given type in the sublist. */
- static constexpr value_type value = 0u;
- };
- /**
- * @brief Helper variable template.
- * @tparam List Type list.
- * @tparam Type Type to look for and for which to return the index.
- */
- template<typename Type, typename List>
- inline constexpr std::size_t type_list_index_v = type_list_index<Type, List>::value;
- /**
- * @brief Concatenates multiple type lists.
- * @tparam Type Types provided by the first type list.
- * @tparam Other Types provided by the second type list.
- * @return A type list composed by the types of both the type lists.
- */
- template<typename... Type, typename... Other>
- constexpr type_list<Type..., Other...> operator+(type_list<Type...>, type_list<Other...>) {
- return {};
- }
- /*! @brief Primary template isn't defined on purpose. */
- template<typename...>
- struct type_list_cat;
- /*! @brief Concatenates multiple type lists. */
- template<>
- struct type_list_cat<> {
- /*! @brief A type list composed by the types of all the type lists. */
- using type = type_list<>;
- };
- /**
- * @brief Concatenates multiple type lists.
- * @tparam Type Types provided by the first type list.
- * @tparam Other Types provided by the second type list.
- * @tparam List Other type lists, if any.
- */
- template<typename... Type, typename... Other, typename... List>
- struct type_list_cat<type_list<Type...>, type_list<Other...>, List...> {
- /*! @brief A type list composed by the types of all the type lists. */
- using type = typename type_list_cat<type_list<Type..., Other...>, List...>::type;
- };
- /**
- * @brief Concatenates multiple type lists.
- * @tparam Type Types provided by the type list.
- */
- template<typename... Type>
- struct type_list_cat<type_list<Type...>> {
- /*! @brief A type list composed by the types of all the type lists. */
- using type = type_list<Type...>;
- };
- /**
- * @brief Helper type.
- * @tparam List Type lists to concatenate.
- */
- template<typename... List>
- using type_list_cat_t = typename type_list_cat<List...>::type;
- /*! @cond TURN_OFF_DOXYGEN */
- namespace internal {
- template<typename...>
- struct type_list_unique;
- template<typename First, typename... Other, typename... Type>
- struct type_list_unique<type_list<First, Other...>, Type...>
- : std::conditional_t<(std::is_same_v<First, Type> || ...), type_list_unique<type_list<Other...>, Type...>, type_list_unique<type_list<Other...>, Type..., First>> {};
- template<typename... Type>
- struct type_list_unique<type_list<>, Type...> {
- using type = type_list<Type...>;
- };
- } // namespace internal
- /*! @endcond */
- /**
- * @brief Removes duplicates types from a type list.
- * @tparam List Type list.
- */
- template<typename List>
- struct type_list_unique {
- /*! @brief A type list without duplicate types. */
- using type = typename internal::type_list_unique<List>::type;
- };
- /**
- * @brief Helper type.
- * @tparam List Type list.
- */
- template<typename List>
- using type_list_unique_t = typename type_list_unique<List>::type;
- /**
- * @brief Provides the member constant `value` to true if a type list contains a
- * given type, false otherwise.
- * @tparam List Type list.
- * @tparam Type Type to look for.
- */
- template<typename List, typename Type>
- struct type_list_contains;
- /**
- * @copybrief type_list_contains
- * @tparam Type Types provided by the type list.
- * @tparam Other Type to look for.
- */
- template<typename... Type, typename Other>
- struct type_list_contains<type_list<Type...>, Other>
- : std::bool_constant<(std::is_same_v<Type, Other> || ...)> {};
- /**
- * @brief Helper variable template.
- * @tparam List Type list.
- * @tparam Type Type to look for.
- */
- template<typename List, typename Type>
- inline constexpr bool type_list_contains_v = type_list_contains<List, Type>::value;
- /*! @brief Primary template isn't defined on purpose. */
- template<typename...>
- struct type_list_diff;
- /**
- * @brief Computes the difference between two type lists.
- * @tparam Type Types provided by the first type list.
- * @tparam Other Types provided by the second type list.
- */
- template<typename... Type, typename... Other>
- struct type_list_diff<type_list<Type...>, type_list<Other...>> {
- /*! @brief A type list that is the difference between the two type lists. */
- using type = type_list_cat_t<std::conditional_t<type_list_contains_v<type_list<Other...>, Type>, type_list<>, type_list<Type>>...>;
- };
- /**
- * @brief Helper type.
- * @tparam List Type lists between which to compute the difference.
- */
- template<typename... List>
- using type_list_diff_t = typename type_list_diff<List...>::type;
- /*! @brief Primary template isn't defined on purpose. */
- template<typename, template<typename...> class>
- struct type_list_transform;
- /**
- * @brief Applies a given _function_ to a type list and generate a new list.
- * @tparam Type Types provided by the type list.
- * @tparam Op Unary operation as template class with a type member named `type`.
- */
- template<typename... Type, template<typename...> class Op>
- struct type_list_transform<type_list<Type...>, Op> {
- /*! @brief Resulting type list after applying the transform function. */
- // NOLINTNEXTLINE(modernize-type-traits)
- using type = type_list<typename Op<Type>::type...>;
- };
- /**
- * @brief Helper type.
- * @tparam List Type list.
- * @tparam Op Unary operation as template class with a type member named `type`.
- */
- template<typename List, template<typename...> class Op>
- using type_list_transform_t = typename type_list_transform<List, Op>::type;
- /**
- * @brief A class to use to push around lists of constant values, nothing more.
- * @tparam Value Values provided by the value list.
- */
- template<auto... Value>
- struct value_list {
- /*! @brief Value list type. */
- using type = value_list;
- /*! @brief Compile-time number of elements in the value list. */
- static constexpr auto size = sizeof...(Value);
- };
- /*! @brief Primary template isn't defined on purpose. */
- template<std::size_t, typename>
- struct value_list_element;
- /**
- * @brief Provides compile-time indexed access to the values of a value list.
- * @tparam Index Index of the value to return.
- * @tparam Value First value provided by the value list.
- * @tparam Other Other values provided by the value list.
- */
- template<std::size_t Index, auto Value, auto... Other>
- struct value_list_element<Index, value_list<Value, Other...>>
- : value_list_element<Index - 1u, value_list<Other...>> {};
- /**
- * @brief Provides compile-time indexed access to the types of a type list.
- * @tparam Value First value provided by the value list.
- * @tparam Other Other values provided by the value list.
- */
- template<auto Value, auto... Other>
- struct value_list_element<0u, value_list<Value, Other...>> {
- /*! @brief Searched type. */
- using type = decltype(Value);
- /*! @brief Searched value. */
- static constexpr auto value = Value;
- };
- /**
- * @brief Helper type.
- * @tparam Index Index of the type to return.
- * @tparam List Value list to search into.
- */
- template<std::size_t Index, typename List>
- using value_list_element_t = typename value_list_element<Index, List>::type;
- /**
- * @brief Helper type.
- * @tparam Index Index of the value to return.
- * @tparam List Value list to search into.
- */
- template<std::size_t Index, typename List>
- inline constexpr auto value_list_element_v = value_list_element<Index, List>::value;
- /*! @brief Primary template isn't defined on purpose. */
- template<auto, typename>
- struct value_list_index;
- /**
- * @brief Provides compile-time type access to the values of a value list.
- * @tparam Value Value to look for and for which to return the index.
- * @tparam First First value provided by the value list.
- * @tparam Other Other values provided by the value list.
- */
- template<auto Value, auto First, auto... Other>
- struct value_list_index<Value, value_list<First, Other...>> {
- /*! @brief Unsigned integer type. */
- using value_type = std::size_t;
- /*! @brief Compile-time position of the given value in the sublist. */
- static constexpr value_type value = 1u + value_list_index<Value, value_list<Other...>>::value;
- };
- /**
- * @brief Provides compile-time type access to the values of a value list.
- * @tparam Value Value to look for and for which to return the index.
- * @tparam Other Other values provided by the value list.
- */
- template<auto Value, auto... Other>
- struct value_list_index<Value, value_list<Value, Other...>> {
- static_assert(value_list_index<Value, value_list<Other...>>::value == sizeof...(Other), "Non-unique type");
- /*! @brief Unsigned integer type. */
- using value_type = std::size_t;
- /*! @brief Compile-time position of the given value in the sublist. */
- static constexpr value_type value = 0u;
- };
- /**
- * @brief Provides compile-time type access to the values of a value list.
- * @tparam Value Value to look for and for which to return the index.
- */
- template<auto Value>
- struct value_list_index<Value, value_list<>> {
- /*! @brief Unsigned integer type. */
- using value_type = std::size_t;
- /*! @brief Compile-time position of the given type in the sublist. */
- static constexpr value_type value = 0u;
- };
- /**
- * @brief Helper variable template.
- * @tparam List Value list.
- * @tparam Value Value to look for and for which to return the index.
- */
- template<auto Value, typename List>
- inline constexpr std::size_t value_list_index_v = value_list_index<Value, List>::value;
- /**
- * @brief Concatenates multiple value lists.
- * @tparam Value Values provided by the first value list.
- * @tparam Other Values provided by the second value list.
- * @return A value list composed by the values of both the value lists.
- */
- template<auto... Value, auto... Other>
- constexpr value_list<Value..., Other...> operator+(value_list<Value...>, value_list<Other...>) {
- return {};
- }
- /*! @brief Primary template isn't defined on purpose. */
- template<typename...>
- struct value_list_cat;
- /*! @brief Concatenates multiple value lists. */
- template<>
- struct value_list_cat<> {
- /*! @brief A value list composed by the values of all the value lists. */
- using type = value_list<>;
- };
- /**
- * @brief Concatenates multiple value lists.
- * @tparam Value Values provided by the first value list.
- * @tparam Other Values provided by the second value list.
- * @tparam List Other value lists, if any.
- */
- template<auto... Value, auto... Other, typename... List>
- struct value_list_cat<value_list<Value...>, value_list<Other...>, List...> {
- /*! @brief A value list composed by the values of all the value lists. */
- using type = typename value_list_cat<value_list<Value..., Other...>, List...>::type;
- };
- /**
- * @brief Concatenates multiple value lists.
- * @tparam Value Values provided by the value list.
- */
- template<auto... Value>
- struct value_list_cat<value_list<Value...>> {
- /*! @brief A value list composed by the values of all the value lists. */
- using type = value_list<Value...>;
- };
- /**
- * @brief Helper type.
- * @tparam List Value lists to concatenate.
- */
- template<typename... List>
- using value_list_cat_t = typename value_list_cat<List...>::type;
- /*! @brief Primary template isn't defined on purpose. */
- template<typename>
- struct value_list_unique;
- /**
- * @brief Removes duplicates values from a value list.
- * @tparam Value One of the values provided by the given value list.
- * @tparam Other The other values provided by the given value list.
- */
- template<auto Value, auto... Other>
- struct value_list_unique<value_list<Value, Other...>> {
- /*! @brief A value list without duplicate types. */
- using type = std::conditional_t<
- ((Value == Other) || ...),
- typename value_list_unique<value_list<Other...>>::type,
- value_list_cat_t<value_list<Value>, typename value_list_unique<value_list<Other...>>::type>>;
- };
- /*! @brief Removes duplicates values from a value list. */
- template<>
- struct value_list_unique<value_list<>> {
- /*! @brief A value list without duplicate types. */
- using type = value_list<>;
- };
- /**
- * @brief Helper type.
- * @tparam Type A value list.
- */
- template<typename Type>
- using value_list_unique_t = typename value_list_unique<Type>::type;
- /**
- * @brief Provides the member constant `value` to true if a value list contains
- * a given value, false otherwise.
- * @tparam List Value list.
- * @tparam Value Value to look for.
- */
- template<typename List, auto Value>
- struct value_list_contains;
- /**
- * @copybrief value_list_contains
- * @tparam Value Values provided by the value list.
- * @tparam Other Value to look for.
- */
- template<auto... Value, auto Other>
- struct value_list_contains<value_list<Value...>, Other>
- : std::bool_constant<((Value == Other) || ...)> {};
- /**
- * @brief Helper variable template.
- * @tparam List Value list.
- * @tparam Value Value to look for.
- */
- template<typename List, auto Value>
- inline constexpr bool value_list_contains_v = value_list_contains<List, Value>::value;
- /*! @brief Primary template isn't defined on purpose. */
- template<typename...>
- struct value_list_diff;
- /**
- * @brief Computes the difference between two value lists.
- * @tparam Value Values provided by the first value list.
- * @tparam Other Values provided by the second value list.
- */
- template<auto... Value, auto... Other>
- struct value_list_diff<value_list<Value...>, value_list<Other...>> {
- /*! @brief A value list that is the difference between the two value lists. */
- using type = value_list_cat_t<std::conditional_t<value_list_contains_v<value_list<Other...>, Value>, value_list<>, value_list<Value>>...>;
- };
- /**
- * @brief Helper type.
- * @tparam List Value lists between which to compute the difference.
- */
- template<typename... List>
- using value_list_diff_t = typename value_list_diff<List...>::type;
- /*! @brief Same as std::is_invocable, but with tuples. */
- template<typename, typename>
- struct is_applicable: std::false_type {};
- /**
- * @copybrief is_applicable
- * @tparam Func A valid function type.
- * @tparam Tuple Tuple-like type.
- * @tparam Args The list of arguments to use to probe the function type.
- */
- template<typename Func, template<typename...> class Tuple, typename... Args>
- struct is_applicable<Func, Tuple<Args...>>: std::is_invocable<Func, Args...> {};
- /**
- * @copybrief is_applicable
- * @tparam Func A valid function type.
- * @tparam Tuple Tuple-like type.
- * @tparam Args The list of arguments to use to probe the function type.
- */
- template<typename Func, template<typename...> class Tuple, typename... Args>
- struct is_applicable<Func, const Tuple<Args...>>: std::is_invocable<Func, Args...> {};
- /**
- * @brief Helper variable template.
- * @tparam Func A valid function type.
- * @tparam Args The list of arguments to use to probe the function type.
- */
- template<typename Func, typename Args>
- inline constexpr bool is_applicable_v = is_applicable<Func, Args>::value;
- /*! @brief Same as std::is_invocable_r, but with tuples for arguments. */
- template<typename, typename, typename>
- struct is_applicable_r: std::false_type {};
- /**
- * @copybrief is_applicable_r
- * @tparam Ret The type to which the return type of the function should be
- * convertible.
- * @tparam Func A valid function type.
- * @tparam Args The list of arguments to use to probe the function type.
- */
- template<typename Ret, typename Func, typename... Args>
- struct is_applicable_r<Ret, Func, std::tuple<Args...>>: std::is_invocable_r<Ret, Func, Args...> {};
- /**
- * @brief Helper variable template.
- * @tparam Ret The type to which the return type of the function should be
- * convertible.
- * @tparam Func A valid function type.
- * @tparam Args The list of arguments to use to probe the function type.
- */
- template<typename Ret, typename Func, typename Args>
- inline constexpr bool is_applicable_r_v = is_applicable_r<Ret, Func, Args>::value;
- /**
- * @brief Provides the member constant `value` to true if a given type is
- * complete, false otherwise.
- * @tparam Type The type to test.
- */
- template<typename Type, typename = void>
- struct is_complete: std::false_type {};
- /*! @copydoc is_complete */
- template<typename Type>
- struct is_complete<Type, std::void_t<decltype(sizeof(Type))>>: std::true_type {};
- /**
- * @brief Helper variable template.
- * @tparam Type The type to test.
- */
- template<typename Type>
- inline constexpr bool is_complete_v = is_complete<Type>::value;
- /**
- * @brief Provides the member constant `value` to true if a given type is an
- * iterator, false otherwise.
- * @tparam Type The type to test.
- */
- template<typename Type, typename = void>
- struct is_iterator: std::false_type {};
- /*! @cond TURN_OFF_DOXYGEN */
- namespace internal {
- template<typename, typename = void>
- struct has_iterator_category: std::false_type {};
- template<typename Type>
- struct has_iterator_category<Type, std::void_t<typename std::iterator_traits<Type>::iterator_category>>: std::true_type {};
- } // namespace internal
- /*! @endcond */
- /*! @copydoc is_iterator */
- template<typename Type>
- struct is_iterator<Type, std::enable_if_t<!std::is_void_v<std::remove_const_t<std::remove_pointer_t<Type>>>>>
- : internal::has_iterator_category<Type> {};
- /**
- * @brief Helper variable template.
- * @tparam Type The type to test.
- */
- template<typename Type>
- inline constexpr bool is_iterator_v = is_iterator<Type>::value;
- /**
- * @brief Provides the member constant `value` to true if a given type is both
- * an empty and non-final class, false otherwise.
- * @tparam Type The type to test
- */
- template<typename Type>
- struct is_ebco_eligible
- : std::bool_constant<std::is_empty_v<Type> && !std::is_final_v<Type>> {};
- /**
- * @brief Helper variable template.
- * @tparam Type The type to test.
- */
- template<typename Type>
- inline constexpr bool is_ebco_eligible_v = is_ebco_eligible<Type>::value;
- /**
- * @brief Provides the member constant `value` to true if `Type::is_transparent`
- * is valid and denotes a type, false otherwise.
- * @tparam Type The type to test.
- */
- template<typename Type, typename = void>
- struct is_transparent: std::false_type {};
- /*! @copydoc is_transparent */
- template<typename Type>
- struct is_transparent<Type, std::void_t<typename Type::is_transparent>>: std::true_type {};
- /**
- * @brief Helper variable template.
- * @tparam Type The type to test.
- */
- template<typename Type>
- inline constexpr bool is_transparent_v = is_transparent<Type>::value;
- /*! @cond TURN_OFF_DOXYGEN */
- namespace internal {
- template<typename, typename = void>
- struct has_tuple_size_value: std::false_type {};
- template<typename Type>
- struct has_tuple_size_value<Type, std::void_t<decltype(std::tuple_size<const Type>::value)>>: std::true_type {};
- template<typename, typename = void>
- struct has_value_type: std::false_type {};
- template<typename Type>
- struct has_value_type<Type, std::void_t<typename Type::value_type>>: std::true_type {};
- template<typename>
- [[nodiscard]] constexpr bool dispatch_is_equality_comparable();
- template<typename Type, std::size_t... Index>
- [[nodiscard]] constexpr bool unpack_maybe_equality_comparable(std::index_sequence<Index...>) {
- return (dispatch_is_equality_comparable<std::tuple_element_t<Index, Type>>() && ...);
- }
- template<typename>
- [[nodiscard]] constexpr bool maybe_equality_comparable(char) {
- return false;
- }
- template<typename Type>
- [[nodiscard]] constexpr auto maybe_equality_comparable(int) -> decltype(std::declval<Type>() == std::declval<Type>()) {
- return true;
- }
- template<typename Type>
- [[nodiscard]] constexpr bool dispatch_is_equality_comparable() {
- // NOLINTBEGIN(modernize-use-transparent-functors)
- if constexpr(std::is_array_v<Type>) {
- return false;
- } else if constexpr(is_complete_v<std::tuple_size<std::remove_const_t<Type>>>) {
- if constexpr(has_tuple_size_value<Type>::value) {
- return maybe_equality_comparable<Type>(0) && unpack_maybe_equality_comparable<Type>(std::make_index_sequence<std::tuple_size<Type>::value>{});
- } else {
- return maybe_equality_comparable<Type>(0);
- }
- } else if constexpr(has_value_type<Type>::value) {
- if constexpr(is_iterator_v<Type> || std::is_same_v<typename Type::value_type, Type> || dispatch_is_equality_comparable<typename Type::value_type>()) {
- return maybe_equality_comparable<Type>(0);
- } else {
- return false;
- }
- } else {
- return maybe_equality_comparable<Type>(0);
- }
- // NOLINTEND(modernize-use-transparent-functors)
- }
- } // namespace internal
- /*! @endcond */
- /**
- * @brief Provides the member constant `value` to true if a given type is
- * equality comparable, false otherwise.
- * @tparam Type The type to test.
- */
- template<typename Type>
- struct is_equality_comparable: std::bool_constant<internal::dispatch_is_equality_comparable<Type>()> {};
- /*! @copydoc is_equality_comparable */
- template<typename Type>
- struct is_equality_comparable<const Type>: is_equality_comparable<Type> {};
- /**
- * @brief Helper variable template.
- * @tparam Type The type to test.
- */
- template<typename Type>
- inline constexpr bool is_equality_comparable_v = is_equality_comparable<Type>::value;
- /**
- * @brief Transcribes the constness of a type to another type.
- * @tparam To The type to which to transcribe the constness.
- * @tparam From The type from which to transcribe the constness.
- */
- template<typename To, typename From>
- struct constness_as {
- /*! @brief The type resulting from the transcription of the constness. */
- using type = std::remove_const_t<To>;
- };
- /*! @copydoc constness_as */
- template<typename To, typename From>
- struct constness_as<To, const From> {
- /*! @brief The type resulting from the transcription of the constness. */
- using type = const To;
- };
- /**
- * @brief Alias template to facilitate the transcription of the constness.
- * @tparam To The type to which to transcribe the constness.
- * @tparam From The type from which to transcribe the constness.
- */
- template<typename To, typename From>
- using constness_as_t = typename constness_as<To, From>::type;
- /**
- * @brief Extracts the class of a non-static member object or function.
- * @tparam Member A pointer to a non-static member object or function.
- */
- template<typename Member>
- class member_class {
- static_assert(std::is_member_pointer_v<Member>, "Invalid pointer type to non-static member object or function");
- template<typename Class, typename Ret, typename... Args>
- static Class *clazz(Ret (Class::*)(Args...));
- template<typename Class, typename Ret, typename... Args>
- static Class *clazz(Ret (Class::*)(Args...) const);
- template<typename Class, typename Type>
- static Class *clazz(Type Class::*);
- public:
- /*! @brief The class of the given non-static member object or function. */
- using type = std::remove_pointer_t<decltype(clazz(std::declval<Member>()))>;
- };
- /**
- * @brief Helper type.
- * @tparam Member A pointer to a non-static member object or function.
- */
- template<typename Member>
- using member_class_t = typename member_class<Member>::type;
- /**
- * @brief Extracts the n-th argument of a _callable_ type.
- * @tparam Index The index of the argument to extract.
- * @tparam Candidate A valid _callable_ type.
- */
- template<std::size_t Index, typename Candidate>
- class nth_argument {
- template<typename Ret, typename... Args>
- static constexpr type_list<Args...> pick_up(Ret (*)(Args...));
- template<typename Ret, typename Class, typename... Args>
- static constexpr type_list<Args...> pick_up(Ret (Class ::*)(Args...));
- template<typename Ret, typename Class, typename... Args>
- static constexpr type_list<Args...> pick_up(Ret (Class ::*)(Args...) const);
- template<typename Type, typename Class>
- static constexpr type_list<Type> pick_up(Type Class ::*);
- template<typename Type>
- static constexpr decltype(pick_up(&Type::operator())) pick_up(Type &&);
- public:
- /*! @brief N-th argument of the _callable_ type. */
- using type = type_list_element_t<Index, decltype(pick_up(std::declval<Candidate>()))>;
- };
- /**
- * @brief Helper type.
- * @tparam Index The index of the argument to extract.
- * @tparam Candidate A valid function, member function or data member type.
- */
- template<std::size_t Index, typename Candidate>
- using nth_argument_t = typename nth_argument<Index, Candidate>::type;
- } // namespace entt
- template<typename... Type>
- struct std::tuple_size<entt::type_list<Type...>>: std::integral_constant<std::size_t, entt::type_list<Type...>::size> {};
- template<std::size_t Index, typename... Type>
- struct std::tuple_element<Index, entt::type_list<Type...>>: entt::type_list_element<Index, entt::type_list<Type...>> {};
- template<auto... Value>
- struct std::tuple_size<entt::value_list<Value...>>: std::integral_constant<std::size_t, entt::value_list<Value...>::size> {};
- template<std::size_t Index, auto... Value>
- struct std::tuple_element<Index, entt::value_list<Value...>>: entt::value_list_element<Index, entt::value_list<Value...>> {};
- #endif
- // #include "fwd.hpp"
- #ifndef ENTT_CONTAINER_FWD_HPP
- #define ENTT_CONTAINER_FWD_HPP
- #include <functional>
- #include <memory>
- #include <utility>
- #include <vector>
- namespace entt {
- template<
- typename Key,
- typename Type,
- typename = std::hash<Key>,
- typename = std::equal_to<>,
- typename = std::allocator<std::pair<const Key, Type>>>
- class dense_map;
- template<
- typename Type,
- typename = std::hash<Type>,
- typename = std::equal_to<>,
- typename = std::allocator<Type>>
- class dense_set;
- template<typename...>
- class basic_table;
- /**
- * @brief Alias declaration for the most common use case.
- * @tparam Type Element types.
- */
- template<typename... Type>
- using table = basic_table<std::vector<Type>...>;
- } // namespace entt
- #endif
- namespace entt {
- /*! @cond TURN_OFF_DOXYGEN */
- namespace internal {
- static constexpr std::size_t dense_map_placeholder_position = (std::numeric_limits<std::size_t>::max)();
- template<typename Key, typename Type>
- struct dense_map_node final {
- using value_type = std::pair<Key, Type>;
- template<typename... Args>
- dense_map_node(const std::size_t pos, Args &&...args)
- : next{pos},
- element{std::forward<Args>(args)...} {}
- template<typename Allocator, typename... Args>
- dense_map_node(std::allocator_arg_t, const Allocator &allocator, const std::size_t pos, Args &&...args)
- : next{pos},
- element{entt::make_obj_using_allocator<value_type>(allocator, std::forward<Args>(args)...)} {}
- template<typename Allocator>
- dense_map_node(std::allocator_arg_t, const Allocator &allocator, const dense_map_node &other)
- : next{other.next},
- element{entt::make_obj_using_allocator<value_type>(allocator, other.element)} {}
- template<typename Allocator>
- dense_map_node(std::allocator_arg_t, const Allocator &allocator, dense_map_node &&other)
- : next{other.next},
- element{entt::make_obj_using_allocator<value_type>(allocator, std::move(other.element))} {}
- std::size_t next;
- value_type element;
- };
- template<typename It>
- class dense_map_iterator final {
- template<typename>
- friend class dense_map_iterator;
- using first_type = decltype(std::as_const(std::declval<It>()->element.first));
- using second_type = decltype((std::declval<It>()->element.second));
- public:
- using value_type = std::pair<first_type, second_type>;
- using pointer = input_iterator_pointer<value_type>;
- using reference = value_type;
- using difference_type = std::ptrdiff_t;
- using iterator_category = std::input_iterator_tag;
- using iterator_concept = std::random_access_iterator_tag;
- constexpr dense_map_iterator() noexcept
- : it{} {}
- constexpr dense_map_iterator(const It iter) noexcept
- : it{iter} {}
- template<typename Other, typename = std::enable_if_t<!std::is_same_v<It, Other> && std::is_constructible_v<It, Other>>>
- constexpr dense_map_iterator(const dense_map_iterator<Other> &other) noexcept
- : it{other.it} {}
- constexpr dense_map_iterator &operator++() noexcept {
- return ++it, *this;
- }
- constexpr dense_map_iterator operator++(int) noexcept {
- const dense_map_iterator orig = *this;
- return ++(*this), orig;
- }
- constexpr dense_map_iterator &operator--() noexcept {
- return --it, *this;
- }
- constexpr dense_map_iterator operator--(int) noexcept {
- const dense_map_iterator orig = *this;
- return operator--(), orig;
- }
- constexpr dense_map_iterator &operator+=(const difference_type value) noexcept {
- it += value;
- return *this;
- }
- constexpr dense_map_iterator operator+(const difference_type value) const noexcept {
- dense_map_iterator copy = *this;
- return (copy += value);
- }
- constexpr dense_map_iterator &operator-=(const difference_type value) noexcept {
- return (*this += -value);
- }
- constexpr dense_map_iterator operator-(const difference_type value) const noexcept {
- return (*this + -value);
- }
- [[nodiscard]] constexpr reference operator[](const difference_type value) const noexcept {
- return {it[value].element.first, it[value].element.second};
- }
- [[nodiscard]] constexpr pointer operator->() const noexcept {
- return operator*();
- }
- [[nodiscard]] constexpr reference operator*() const noexcept {
- return operator[](0);
- }
- template<typename Lhs, typename Rhs>
- friend constexpr std::ptrdiff_t operator-(const dense_map_iterator<Lhs> &, const dense_map_iterator<Rhs> &) noexcept;
- template<typename Lhs, typename Rhs>
- friend constexpr bool operator==(const dense_map_iterator<Lhs> &, const dense_map_iterator<Rhs> &) noexcept;
- template<typename Lhs, typename Rhs>
- friend constexpr bool operator<(const dense_map_iterator<Lhs> &, const dense_map_iterator<Rhs> &) noexcept;
- private:
- It it;
- };
- template<typename Lhs, typename Rhs>
- [[nodiscard]] constexpr std::ptrdiff_t operator-(const dense_map_iterator<Lhs> &lhs, const dense_map_iterator<Rhs> &rhs) noexcept {
- return lhs.it - rhs.it;
- }
- template<typename Lhs, typename Rhs>
- [[nodiscard]] constexpr bool operator==(const dense_map_iterator<Lhs> &lhs, const dense_map_iterator<Rhs> &rhs) noexcept {
- return lhs.it == rhs.it;
- }
- template<typename Lhs, typename Rhs>
- [[nodiscard]] constexpr bool operator!=(const dense_map_iterator<Lhs> &lhs, const dense_map_iterator<Rhs> &rhs) noexcept {
- return !(lhs == rhs);
- }
- template<typename Lhs, typename Rhs>
- [[nodiscard]] constexpr bool operator<(const dense_map_iterator<Lhs> &lhs, const dense_map_iterator<Rhs> &rhs) noexcept {
- return lhs.it < rhs.it;
- }
- template<typename Lhs, typename Rhs>
- [[nodiscard]] constexpr bool operator>(const dense_map_iterator<Lhs> &lhs, const dense_map_iterator<Rhs> &rhs) noexcept {
- return rhs < lhs;
- }
- template<typename Lhs, typename Rhs>
- [[nodiscard]] constexpr bool operator<=(const dense_map_iterator<Lhs> &lhs, const dense_map_iterator<Rhs> &rhs) noexcept {
- return !(lhs > rhs);
- }
- template<typename Lhs, typename Rhs>
- [[nodiscard]] constexpr bool operator>=(const dense_map_iterator<Lhs> &lhs, const dense_map_iterator<Rhs> &rhs) noexcept {
- return !(lhs < rhs);
- }
- template<typename It>
- class dense_map_local_iterator final {
- template<typename>
- friend class dense_map_local_iterator;
- using first_type = decltype(std::as_const(std::declval<It>()->element.first));
- using second_type = decltype((std::declval<It>()->element.second));
- public:
- using value_type = std::pair<first_type, second_type>;
- using pointer = input_iterator_pointer<value_type>;
- using reference = value_type;
- using difference_type = std::ptrdiff_t;
- using iterator_category = std::input_iterator_tag;
- using iterator_concept = std::forward_iterator_tag;
- constexpr dense_map_local_iterator() noexcept = default;
- constexpr dense_map_local_iterator(It iter, const std::size_t pos) noexcept
- : it{iter},
- offset{pos} {}
- template<typename Other, typename = std::enable_if_t<!std::is_same_v<It, Other> && std::is_constructible_v<It, Other>>>
- constexpr dense_map_local_iterator(const dense_map_local_iterator<Other> &other) noexcept
- : it{other.it},
- offset{other.offset} {}
- constexpr dense_map_local_iterator &operator++() noexcept {
- return (offset = it[static_cast<typename It::difference_type>(offset)].next), *this;
- }
- constexpr dense_map_local_iterator operator++(int) noexcept {
- const dense_map_local_iterator orig = *this;
- return ++(*this), orig;
- }
- [[nodiscard]] constexpr pointer operator->() const noexcept {
- return operator*();
- }
- [[nodiscard]] constexpr reference operator*() const noexcept {
- const auto idx = static_cast<typename It::difference_type>(offset);
- return {it[idx].element.first, it[idx].element.second};
- }
- [[nodiscard]] constexpr std::size_t index() const noexcept {
- return offset;
- }
- private:
- It it{};
- std::size_t offset{dense_map_placeholder_position};
- };
- template<typename Lhs, typename Rhs>
- [[nodiscard]] constexpr bool operator==(const dense_map_local_iterator<Lhs> &lhs, const dense_map_local_iterator<Rhs> &rhs) noexcept {
- return lhs.index() == rhs.index();
- }
- template<typename Lhs, typename Rhs>
- [[nodiscard]] constexpr bool operator!=(const dense_map_local_iterator<Lhs> &lhs, const dense_map_local_iterator<Rhs> &rhs) noexcept {
- return !(lhs == rhs);
- }
- } // namespace internal
- /*! @endcond */
- /**
- * @brief Associative container for key-value pairs with unique keys.
- *
- * Internally, elements are organized into buckets. Which bucket an element is
- * placed into depends entirely on the hash of its key. Keys with the same hash
- * code appear in the same bucket.
- *
- * @tparam Key Key type of the associative container.
- * @tparam Type Mapped type of the associative container.
- * @tparam Hash Type of function to use to hash the keys.
- * @tparam KeyEqual Type of function to use to compare the keys for equality.
- * @tparam Allocator Type of allocator used to manage memory and elements.
- */
- template<typename Key, typename Type, typename Hash, typename KeyEqual, typename Allocator>
- class dense_map {
- static constexpr float default_threshold = 0.875f;
- static constexpr std::size_t minimum_capacity = 8u;
- static constexpr std::size_t placeholder_position = internal::dense_map_placeholder_position;
- using node_type = internal::dense_map_node<Key, Type>;
- using alloc_traits = std::allocator_traits<Allocator>;
- static_assert(std::is_same_v<typename alloc_traits::value_type, std::pair<const Key, Type>>, "Invalid value type");
- using sparse_container_type = std::vector<std::size_t, typename alloc_traits::template rebind_alloc<std::size_t>>;
- using packed_container_type = std::vector<node_type, typename alloc_traits::template rebind_alloc<node_type>>;
- template<typename Other>
- [[nodiscard]] std::size_t key_to_bucket(const Other &key) const noexcept {
- // NOLINTNEXTLINE(cppcoreguidelines-pro-bounds-array-to-pointer-decay)
- return fast_mod(static_cast<size_type>(sparse.second()(key)), bucket_count());
- }
- template<typename Other>
- [[nodiscard]] auto constrained_find(const Other &key, const std::size_t bucket) {
- for(auto offset = sparse.first()[bucket]; offset != placeholder_position; offset = packed.first()[offset].next) {
- if(packed.second()(packed.first()[offset].element.first, key)) {
- return begin() + static_cast<typename iterator::difference_type>(offset);
- }
- }
- return end();
- }
- template<typename Other>
- [[nodiscard]] auto constrained_find(const Other &key, const std::size_t bucket) const {
- for(auto offset = sparse.first()[bucket]; offset != placeholder_position; offset = packed.first()[offset].next) {
- if(packed.second()(packed.first()[offset].element.first, key)) {
- return cbegin() + static_cast<typename const_iterator::difference_type>(offset);
- }
- }
- return cend();
- }
- template<typename Other, typename... Args>
- [[nodiscard]] auto insert_or_do_nothing(Other &&key, Args &&...args) {
- const auto index = key_to_bucket(key);
- if(auto it = constrained_find(key, index); it != end()) {
- return std::make_pair(it, false);
- }
- packed.first().emplace_back(sparse.first()[index], std::piecewise_construct, std::forward_as_tuple(std::forward<Other>(key)), std::forward_as_tuple(std::forward<Args>(args)...));
- sparse.first()[index] = packed.first().size() - 1u;
- rehash_if_required();
- return std::make_pair(--end(), true);
- }
- template<typename Other, typename Arg>
- [[nodiscard]] auto insert_or_overwrite(Other &&key, Arg &&value) {
- const auto index = key_to_bucket(key);
- if(auto it = constrained_find(key, index); it != end()) {
- it->second = std::forward<Arg>(value);
- return std::make_pair(it, false);
- }
- packed.first().emplace_back(sparse.first()[index], std::forward<Other>(key), std::forward<Arg>(value));
- sparse.first()[index] = packed.first().size() - 1u;
- rehash_if_required();
- return std::make_pair(--end(), true);
- }
- void move_and_pop(const std::size_t pos) {
- if(const auto last = size() - 1u; pos != last) {
- size_type *curr = &sparse.first()[key_to_bucket(packed.first().back().element.first)];
- packed.first()[pos] = std::move(packed.first().back());
- for(; *curr != last; curr = &packed.first()[*curr].next) {}
- *curr = pos;
- }
- packed.first().pop_back();
- }
- void rehash_if_required() {
- if(const auto bc = bucket_count(); size() > static_cast<size_type>(static_cast<float>(bc) * max_load_factor())) {
- rehash(bc * 2u);
- }
- }
- public:
- /*! @brief Allocator type. */
- using allocator_type = Allocator;
- /*! @brief Key type of the container. */
- using key_type = Key;
- /*! @brief Mapped type of the container. */
- using mapped_type = Type;
- /*! @brief Key-value type of the container. */
- using value_type = std::pair<const Key, Type>;
- /*! @brief Unsigned integer type. */
- using size_type = std::size_t;
- /*! @brief Signed integer type. */
- using difference_type = std::ptrdiff_t;
- /*! @brief Type of function to use to hash the keys. */
- using hasher = Hash;
- /*! @brief Type of function to use to compare the keys for equality. */
- using key_equal = KeyEqual;
- /*! @brief Input iterator type. */
- using iterator = internal::dense_map_iterator<typename packed_container_type::iterator>;
- /*! @brief Constant input iterator type. */
- using const_iterator = internal::dense_map_iterator<typename packed_container_type::const_iterator>;
- /*! @brief Input iterator type. */
- using local_iterator = internal::dense_map_local_iterator<typename packed_container_type::iterator>;
- /*! @brief Constant input iterator type. */
- using const_local_iterator = internal::dense_map_local_iterator<typename packed_container_type::const_iterator>;
- /*! @brief Default constructor. */
- dense_map()
- : dense_map{minimum_capacity} {}
- /**
- * @brief Constructs an empty container with a given allocator.
- * @param allocator The allocator to use.
- */
- explicit dense_map(const allocator_type &allocator)
- : dense_map{minimum_capacity, hasher{}, key_equal{}, allocator} {}
- /**
- * @brief Constructs an empty container with a given allocator and user
- * supplied minimal number of buckets.
- * @param cnt Minimal number of buckets.
- * @param allocator The allocator to use.
- */
- dense_map(const size_type cnt, const allocator_type &allocator)
- : dense_map{cnt, hasher{}, key_equal{}, allocator} {}
- /**
- * @brief Constructs an empty container with a given allocator, hash
- * function and user supplied minimal number of buckets.
- * @param cnt Minimal number of buckets.
- * @param hash Hash function to use.
- * @param allocator The allocator to use.
- */
- dense_map(const size_type cnt, const hasher &hash, const allocator_type &allocator)
- : dense_map{cnt, hash, key_equal{}, allocator} {}
- /**
- * @brief Constructs an empty container with a given allocator, hash
- * function, compare function and user supplied minimal number of buckets.
- * @param cnt Minimal number of buckets.
- * @param hash Hash function to use.
- * @param equal Compare function to use.
- * @param allocator The allocator to use.
- */
- explicit dense_map(const size_type cnt, const hasher &hash = hasher{}, const key_equal &equal = key_equal{}, const allocator_type &allocator = allocator_type{})
- : sparse{allocator, hash},
- packed{allocator, equal} {
- rehash(cnt);
- }
- /*! @brief Default copy constructor. */
- dense_map(const dense_map &) = default;
- /**
- * @brief Allocator-extended copy constructor.
- * @param other The instance to copy from.
- * @param allocator The allocator to use.
- */
- dense_map(const dense_map &other, const allocator_type &allocator)
- : sparse{std::piecewise_construct, std::forward_as_tuple(other.sparse.first(), allocator), std::forward_as_tuple(other.sparse.second())},
- packed{std::piecewise_construct, std::forward_as_tuple(other.packed.first(), allocator), std::forward_as_tuple(other.packed.second())},
- threshold{other.threshold} {}
- /*! @brief Default move constructor. */
- dense_map(dense_map &&) noexcept = default;
- /**
- * @brief Allocator-extended move constructor.
- * @param other The instance to move from.
- * @param allocator The allocator to use.
- */
- dense_map(dense_map &&other, const allocator_type &allocator)
- : sparse{std::piecewise_construct, std::forward_as_tuple(std::move(other.sparse.first()), allocator), std::forward_as_tuple(std::move(other.sparse.second()))},
- packed{std::piecewise_construct, std::forward_as_tuple(std::move(other.packed.first()), allocator), std::forward_as_tuple(std::move(other.packed.second()))},
- threshold{other.threshold} {}
- /*! @brief Default destructor. */
- ~dense_map() = default;
- /**
- * @brief Default copy assignment operator.
- * @return This container.
- */
- dense_map &operator=(const dense_map &) = default;
- /**
- * @brief Default move assignment operator.
- * @return This container.
- */
- dense_map &operator=(dense_map &&) noexcept = default;
- /**
- * @brief Exchanges the contents with those of a given container.
- * @param other Container to exchange the content with.
- */
- void swap(dense_map &other) noexcept {
- using std::swap;
- swap(sparse, other.sparse);
- swap(packed, other.packed);
- swap(threshold, other.threshold);
- }
- /**
- * @brief Returns the associated allocator.
- * @return The associated allocator.
- */
- [[nodiscard]] constexpr allocator_type get_allocator() const noexcept {
- return sparse.first().get_allocator();
- }
- /**
- * @brief Returns an iterator to the beginning.
- *
- * If the array is empty, the returned iterator will be equal to `end()`.
- *
- * @return An iterator to the first instance of the internal array.
- */
- [[nodiscard]] const_iterator cbegin() const noexcept {
- return packed.first().begin();
- }
- /*! @copydoc cbegin */
- [[nodiscard]] const_iterator begin() const noexcept {
- return cbegin();
- }
- /*! @copydoc begin */
- [[nodiscard]] iterator begin() noexcept {
- return packed.first().begin();
- }
- /**
- * @brief Returns an iterator to the end.
- * @return An iterator to the element following the last instance of the
- * internal array.
- */
- [[nodiscard]] const_iterator cend() const noexcept {
- return packed.first().end();
- }
- /*! @copydoc cend */
- [[nodiscard]] const_iterator end() const noexcept {
- return cend();
- }
- /*! @copydoc end */
- [[nodiscard]] iterator end() noexcept {
- return packed.first().end();
- }
- /**
- * @brief Checks whether a container is empty.
- * @return True if the container is empty, false otherwise.
- */
- [[nodiscard]] bool empty() const noexcept {
- return packed.first().empty();
- }
- /**
- * @brief Returns the number of elements in a container.
- * @return Number of elements in a container.
- */
- [[nodiscard]] size_type size() const noexcept {
- return packed.first().size();
- }
- /**
- * @brief Returns the maximum possible number of elements.
- * @return Maximum possible number of elements.
- */
- [[nodiscard]] size_type max_size() const noexcept {
- return packed.first().max_size();
- }
- /*! @brief Clears the container. */
- void clear() noexcept {
- sparse.first().clear();
- packed.first().clear();
- rehash(0u);
- }
- /**
- * @brief Inserts an element into the container, if the key does not exist.
- * @param value A key-value pair eventually convertible to the value type.
- * @return A pair consisting of an iterator to the inserted element (or to
- * the element that prevented the insertion) and a bool denoting whether the
- * insertion took place.
- */
- std::pair<iterator, bool> insert(const value_type &value) {
- return insert_or_do_nothing(value.first, value.second);
- }
- /*! @copydoc insert */
- std::pair<iterator, bool> insert(value_type &&value) {
- return insert_or_do_nothing(std::move(value.first), std::move(value.second));
- }
- /**
- * @copydoc insert
- * @tparam Arg Type of the key-value pair to insert into the container.
- */
- template<typename Arg>
- std::enable_if_t<std::is_constructible_v<value_type, Arg &&>, std::pair<iterator, bool>>
- insert(Arg &&value) {
- return insert_or_do_nothing(std::forward<Arg>(value).first, std::forward<Arg>(value).second);
- }
- /**
- * @brief Inserts elements into the container, if their keys do not exist.
- * @tparam It Type of input iterator.
- * @param first An iterator to the first element of the range of elements.
- * @param last An iterator past the last element of the range of elements.
- */
- template<typename It>
- void insert(It first, It last) {
- for(; first != last; ++first) {
- insert(*first);
- }
- }
- /**
- * @brief Inserts an element into the container or assigns to the current
- * element if the key already exists.
- * @tparam Arg Type of the value to insert or assign.
- * @param key A key used both to look up and to insert if not found.
- * @param value A value to insert or assign.
- * @return A pair consisting of an iterator to the element and a bool
- * denoting whether the insertion took place.
- */
- template<typename Arg>
- std::pair<iterator, bool> insert_or_assign(const key_type &key, Arg &&value) {
- return insert_or_overwrite(key, std::forward<Arg>(value));
- }
- /*! @copydoc insert_or_assign */
- template<typename Arg>
- std::pair<iterator, bool> insert_or_assign(key_type &&key, Arg &&value) {
- return insert_or_overwrite(std::move(key), std::forward<Arg>(value));
- }
- /**
- * @brief Constructs an element in-place, if the key does not exist.
- *
- * The element is also constructed when the container already has the key,
- * in which case the newly constructed object is destroyed immediately.
- *
- * @tparam Args Types of arguments to forward to the constructor of the
- * element.
- * @param args Arguments to forward to the constructor of the element.
- * @return A pair consisting of an iterator to the inserted element (or to
- * the element that prevented the insertion) and a bool denoting whether the
- * insertion took place.
- */
- template<typename... Args>
- std::pair<iterator, bool> emplace([[maybe_unused]] Args &&...args) {
- if constexpr(sizeof...(Args) == 0u) {
- return insert_or_do_nothing(key_type{});
- } else if constexpr(sizeof...(Args) == 1u) {
- return insert_or_do_nothing(std::forward<Args>(args).first..., std::forward<Args>(args).second...);
- } else if constexpr(sizeof...(Args) == 2u) {
- return insert_or_do_nothing(std::forward<Args>(args)...);
- } else {
- auto &node = packed.first().emplace_back(packed.first().size(), std::forward<Args>(args)...);
- const auto index = key_to_bucket(node.element.first);
- if(auto it = constrained_find(node.element.first, index); it != end()) {
- packed.first().pop_back();
- return std::make_pair(it, false);
- }
- std::swap(node.next, sparse.first()[index]);
- rehash_if_required();
- return std::make_pair(--end(), true);
- }
- }
- /**
- * @brief Inserts in-place if the key does not exist, does nothing if the
- * key exists.
- * @tparam Args Types of arguments to forward to the constructor of the
- * element.
- * @param key A key used both to look up and to insert if not found.
- * @param args Arguments to forward to the constructor of the element.
- * @return A pair consisting of an iterator to the inserted element (or to
- * the element that prevented the insertion) and a bool denoting whether the
- * insertion took place.
- */
- template<typename... Args>
- std::pair<iterator, bool> try_emplace(const key_type &key, Args &&...args) {
- return insert_or_do_nothing(key, std::forward<Args>(args)...);
- }
- /*! @copydoc try_emplace */
- template<typename... Args>
- std::pair<iterator, bool> try_emplace(key_type &&key, Args &&...args) {
- return insert_or_do_nothing(std::move(key), std::forward<Args>(args)...);
- }
- /**
- * @brief Removes an element from a given position.
- * @param pos An iterator to the element to remove.
- * @return An iterator following the removed element.
- */
- iterator erase(const_iterator pos) {
- const auto diff = pos - cbegin();
- erase(pos->first);
- return begin() + diff;
- }
- /**
- * @brief Removes the given elements from a container.
- * @param first An iterator to the first element of the range of elements.
- * @param last An iterator past the last element of the range of elements.
- * @return An iterator following the last removed element.
- */
- iterator erase(const_iterator first, const_iterator last) {
- const auto dist = first - cbegin();
- for(auto from = last - cbegin(); from != dist; --from) {
- erase(packed.first()[static_cast<size_type>(from) - 1u].element.first);
- }
- return (begin() + dist);
- }
- /**
- * @brief Removes the element associated with a given key.
- * @param key A key value of an element to remove.
- * @return Number of elements removed (either 0 or 1).
- */
- size_type erase(const key_type &key) {
- for(size_type *curr = &sparse.first()[key_to_bucket(key)]; *curr != placeholder_position; curr = &packed.first()[*curr].next) {
- if(packed.second()(packed.first()[*curr].element.first, key)) {
- const auto index = *curr;
- *curr = packed.first()[*curr].next;
- move_and_pop(index);
- return 1u;
- }
- }
- return 0u;
- }
- /**
- * @brief Accesses a given element with bounds checking.
- * @param key A key of an element to find.
- * @return A reference to the mapped value of the requested element.
- */
- [[nodiscard]] mapped_type &at(const key_type &key) {
- auto it = find(key);
- ENTT_ASSERT(it != end(), "Invalid key");
- return it->second;
- }
- /*! @copydoc at */
- [[nodiscard]] const mapped_type &at(const key_type &key) const {
- auto it = find(key);
- ENTT_ASSERT(it != cend(), "Invalid key");
- return it->second;
- }
- /**
- * @brief Accesses a given element with bounds checking.
- * @tparam Other Type of the key of an element to find.
- * @param key A key of an element to find.
- * @return A reference to the mapped value of the requested element.
- */
- template<typename Other>
- [[nodiscard]] std::enable_if_t<is_transparent_v<hasher> && is_transparent_v<key_equal>, std::conditional_t<false, Other, mapped_type const &>>
- at(const Other &key) const {
- auto it = find(key);
- ENTT_ASSERT(it != cend(), "Invalid key");
- return it->second;
- }
- /*! @copydoc at */
- template<typename Other>
- [[nodiscard]] std::enable_if_t<is_transparent_v<hasher> && is_transparent_v<key_equal>, std::conditional_t<false, Other, mapped_type &>>
- at(const Other &key) {
- auto it = find(key);
- ENTT_ASSERT(it != end(), "Invalid key");
- return it->second;
- }
- /**
- * @brief Accesses or inserts a given element.
- * @param key A key of an element to find or insert.
- * @return A reference to the mapped value of the requested element.
- */
- [[nodiscard]] mapped_type &operator[](const key_type &key) {
- return insert_or_do_nothing(key).first->second;
- }
- /**
- * @brief Accesses or inserts a given element.
- * @param key A key of an element to find or insert.
- * @return A reference to the mapped value of the requested element.
- */
- [[nodiscard]] mapped_type &operator[](key_type &&key) {
- return insert_or_do_nothing(std::move(key)).first->second;
- }
- /**
- * @brief Returns the number of elements matching a key (either 1 or 0).
- * @param key Key value of an element to search for.
- * @return Number of elements matching the key (either 1 or 0).
- */
- [[nodiscard]] size_type count(const key_type &key) const {
- return find(key) != end();
- }
- /**
- * @brief Returns the number of elements matching a key (either 1 or 0).
- * @tparam Other Type of the key value of an element to search for.
- * @param key Key value of an element to search for.
- * @return Number of elements matching the key (either 1 or 0).
- */
- template<typename Other>
- [[nodiscard]] std::enable_if_t<is_transparent_v<hasher> && is_transparent_v<key_equal>, std::conditional_t<false, Other, size_type>>
- count(const Other &key) const {
- return find(key) != end();
- }
- /**
- * @brief Finds an element with a given key.
- * @param key Key value of an element to search for.
- * @return An iterator to an element with the given key. If no such element
- * is found, a past-the-end iterator is returned.
- */
- [[nodiscard]] iterator find(const key_type &key) {
- return constrained_find(key, key_to_bucket(key));
- }
- /*! @copydoc find */
- [[nodiscard]] const_iterator find(const key_type &key) const {
- return constrained_find(key, key_to_bucket(key));
- }
- /**
- * @brief Finds an element with a key that compares _equivalent_ to a given
- * key.
- * @tparam Other Type of the key value of an element to search for.
- * @param key Key value of an element to search for.
- * @return An iterator to an element with the given key. If no such element
- * is found, a past-the-end iterator is returned.
- */
- template<typename Other>
- [[nodiscard]] std::enable_if_t<is_transparent_v<hasher> && is_transparent_v<key_equal>, std::conditional_t<false, Other, iterator>>
- find(const Other &key) {
- return constrained_find(key, key_to_bucket(key));
- }
- /*! @copydoc find */
- template<typename Other>
- [[nodiscard]] std::enable_if_t<is_transparent_v<hasher> && is_transparent_v<key_equal>, std::conditional_t<false, Other, const_iterator>>
- find(const Other &key) const {
- return constrained_find(key, key_to_bucket(key));
- }
- /**
- * @brief Returns a range containing all elements with a given key.
- * @param key Key value of an element to search for.
- * @return A pair of iterators pointing to the first element and past the
- * last element of the range.
- */
- [[nodiscard]] std::pair<iterator, iterator> equal_range(const key_type &key) {
- const auto it = find(key);
- return {it, it + !(it == end())};
- }
- /*! @copydoc equal_range */
- [[nodiscard]] std::pair<const_iterator, const_iterator> equal_range(const key_type &key) const {
- const auto it = find(key);
- return {it, it + !(it == cend())};
- }
- /**
- * @brief Returns a range containing all elements that compare _equivalent_
- * to a given key.
- * @tparam Other Type of an element to search for.
- * @param key Key value of an element to search for.
- * @return A pair of iterators pointing to the first element and past the
- * last element of the range.
- */
- template<typename Other>
- [[nodiscard]] std::enable_if_t<is_transparent_v<hasher> && is_transparent_v<key_equal>, std::conditional_t<false, Other, std::pair<iterator, iterator>>>
- equal_range(const Other &key) {
- const auto it = find(key);
- return {it, it + !(it == end())};
- }
- /*! @copydoc equal_range */
- template<typename Other>
- [[nodiscard]] std::enable_if_t<is_transparent_v<hasher> && is_transparent_v<key_equal>, std::conditional_t<false, Other, std::pair<const_iterator, const_iterator>>>
- equal_range(const Other &key) const {
- const auto it = find(key);
- return {it, it + !(it == cend())};
- }
- /**
- * @brief Checks if the container contains an element with a given key.
- * @param key Key value of an element to search for.
- * @return True if there is such an element, false otherwise.
- */
- [[nodiscard]] bool contains(const key_type &key) const {
- return (find(key) != cend());
- }
- /**
- * @brief Checks if the container contains an element with a key that
- * compares _equivalent_ to a given value.
- * @tparam Other Type of the key value of an element to search for.
- * @param key Key value of an element to search for.
- * @return True if there is such an element, false otherwise.
- */
- template<typename Other>
- [[nodiscard]] std::enable_if_t<is_transparent_v<hasher> && is_transparent_v<key_equal>, std::conditional_t<false, Other, bool>>
- contains(const Other &key) const {
- return (find(key) != cend());
- }
- /**
- * @brief Returns an iterator to the beginning of a given bucket.
- * @param index An index of a bucket to access.
- * @return An iterator to the beginning of the given bucket.
- */
- [[nodiscard]] const_local_iterator cbegin(const size_type index) const {
- return {packed.first().begin(), sparse.first()[index]};
- }
- /**
- * @brief Returns an iterator to the beginning of a given bucket.
- * @param index An index of a bucket to access.
- * @return An iterator to the beginning of the given bucket.
- */
- [[nodiscard]] const_local_iterator begin(const size_type index) const {
- return cbegin(index);
- }
- /**
- * @brief Returns an iterator to the beginning of a given bucket.
- * @param index An index of a bucket to access.
- * @return An iterator to the beginning of the given bucket.
- */
- [[nodiscard]] local_iterator begin(const size_type index) {
- return {packed.first().begin(), sparse.first()[index]};
- }
- /**
- * @brief Returns an iterator to the end of a given bucket.
- * @param index An index of a bucket to access.
- * @return An iterator to the end of the given bucket.
- */
- [[nodiscard]] const_local_iterator cend([[maybe_unused]] const size_type index) const {
- return {};
- }
- /**
- * @brief Returns an iterator to the end of a given bucket.
- * @param index An index of a bucket to access.
- * @return An iterator to the end of the given bucket.
- */
- [[nodiscard]] const_local_iterator end(const size_type index) const {
- return cend(index);
- }
- /**
- * @brief Returns an iterator to the end of a given bucket.
- * @param index An index of a bucket to access.
- * @return An iterator to the end of the given bucket.
- */
- [[nodiscard]] local_iterator end([[maybe_unused]] const size_type index) {
- return {};
- }
- /**
- * @brief Returns the number of buckets.
- * @return The number of buckets.
- */
- [[nodiscard]] size_type bucket_count() const {
- return sparse.first().size();
- }
- /**
- * @brief Returns the maximum number of buckets.
- * @return The maximum number of buckets.
- */
- [[nodiscard]] size_type max_bucket_count() const {
- return sparse.first().max_size();
- }
- /**
- * @brief Returns the number of elements in a given bucket.
- * @param index The index of the bucket to examine.
- * @return The number of elements in the given bucket.
- */
- [[nodiscard]] size_type bucket_size(const size_type index) const {
- return static_cast<size_type>(std::distance(begin(index), end(index)));
- }
- /**
- * @brief Returns the bucket for a given key.
- * @param key The value of the key to examine.
- * @return The bucket for the given key.
- */
- [[nodiscard]] size_type bucket(const key_type &key) const {
- return key_to_bucket(key);
- }
- /**
- * @brief Returns the average number of elements per bucket.
- * @return The average number of elements per bucket.
- */
- [[nodiscard]] float load_factor() const {
- return static_cast<float>(size()) / static_cast<float>(bucket_count());
- }
- /**
- * @brief Returns the maximum average number of elements per bucket.
- * @return The maximum average number of elements per bucket.
- */
- [[nodiscard]] float max_load_factor() const {
- return threshold;
- }
- /**
- * @brief Sets the desired maximum average number of elements per bucket.
- * @param value A desired maximum average number of elements per bucket.
- */
- void max_load_factor(const float value) {
- ENTT_ASSERT(value > 0.f, "Invalid load factor");
- threshold = value;
- rehash(0u);
- }
- /**
- * @brief Reserves at least the specified number of buckets and regenerates
- * the hash table.
- * @param cnt New number of buckets.
- */
- void rehash(const size_type cnt) {
- auto value = cnt > minimum_capacity ? cnt : minimum_capacity;
- const auto cap = static_cast<size_type>(static_cast<float>(size()) / max_load_factor());
- value = value > cap ? value : cap;
- if(const auto sz = next_power_of_two(value); sz != bucket_count()) {
- sparse.first().resize(sz);
- for(auto &&elem: sparse.first()) {
- elem = placeholder_position;
- }
- for(size_type pos{}, last = size(); pos < last; ++pos) {
- const auto index = key_to_bucket(packed.first()[pos].element.first);
- packed.first()[pos].next = std::exchange(sparse.first()[index], pos);
- }
- }
- }
- /**
- * @brief Reserves space for at least the specified number of elements and
- * regenerates the hash table.
- * @param cnt New number of elements.
- */
- void reserve(const size_type cnt) {
- packed.first().reserve(cnt);
- rehash(static_cast<size_type>(std::ceil(static_cast<float>(cnt) / max_load_factor())));
- }
- /**
- * @brief Returns the function used to hash the keys.
- * @return The function used to hash the keys.
- */
- [[nodiscard]] hasher hash_function() const {
- return sparse.second();
- }
- /**
- * @brief Returns the function used to compare keys for equality.
- * @return The function used to compare keys for equality.
- */
- [[nodiscard]] key_equal key_eq() const {
- return packed.second();
- }
- private:
- compressed_pair<sparse_container_type, hasher> sparse;
- compressed_pair<packed_container_type, key_equal> packed;
- float threshold{default_threshold};
- };
- } // namespace entt
- /*! @cond TURN_OFF_DOXYGEN */
- namespace std {
- template<typename Key, typename Value, typename Allocator>
- struct uses_allocator<entt::internal::dense_map_node<Key, Value>, Allocator>
- : std::true_type {};
- } // namespace std
- /*! @endcond */
- #endif
- // #include "../core/compressed_pair.hpp"
- #ifndef ENTT_CORE_COMPRESSED_PAIR_HPP
- #define ENTT_CORE_COMPRESSED_PAIR_HPP
- #include <cstddef>
- #include <tuple>
- #include <type_traits>
- #include <utility>
- // #include "fwd.hpp"
- // #include "type_traits.hpp"
- #ifndef ENTT_CORE_TYPE_TRAITS_HPP
- #define ENTT_CORE_TYPE_TRAITS_HPP
- #include <cstddef>
- #include <iterator>
- #include <tuple>
- #include <type_traits>
- #include <utility>
- // #include "../config/config.h"
- // #include "fwd.hpp"
- namespace entt {
- /**
- * @brief Utility class to disambiguate overloaded functions.
- * @tparam N Number of choices available.
- */
- template<std::size_t N>
- struct choice_t
- // unfortunately, doxygen cannot parse such a construct
- : /*! @cond TURN_OFF_DOXYGEN */ choice_t<N - 1> /*! @endcond */
- {};
- /*! @copybrief choice_t */
- template<>
- struct choice_t<0> {};
- /**
- * @brief Variable template for the choice trick.
- * @tparam N Number of choices available.
- */
- template<std::size_t N>
- inline constexpr choice_t<N> choice{};
- /**
- * @brief Identity type trait.
- *
- * Useful to establish non-deduced contexts in template argument deduction
- * (waiting for C++20) or to provide types through function arguments.
- *
- * @tparam Type A type.
- */
- template<typename Type>
- struct type_identity {
- /*! @brief Identity type. */
- using type = Type;
- };
- /**
- * @brief Helper type.
- * @tparam Type A type.
- */
- template<typename Type>
- using type_identity_t = typename type_identity<Type>::type;
- /**
- * @brief A type-only `sizeof` wrapper that returns 0 where `sizeof` complains.
- * @tparam Type The type of which to return the size.
- */
- template<typename Type, typename = void>
- struct size_of: std::integral_constant<std::size_t, 0u> {};
- /*! @copydoc size_of */
- template<typename Type>
- struct size_of<Type, std::void_t<decltype(sizeof(Type))>>
- // NOLINTNEXTLINE(bugprone-sizeof-expression)
- : std::integral_constant<std::size_t, sizeof(Type)> {};
- /**
- * @brief Helper variable template.
- * @tparam Type The type of which to return the size.
- */
- template<typename Type>
- inline constexpr std::size_t size_of_v = size_of<Type>::value;
- /**
- * @brief Using declaration to be used to _repeat_ the same type a number of
- * times equal to the size of a given parameter pack.
- * @tparam Type A type to repeat.
- */
- template<typename Type, typename>
- using unpack_as_type = Type;
- /**
- * @brief Helper variable template to be used to _repeat_ the same value a
- * number of times equal to the size of a given parameter pack.
- * @tparam Value A value to repeat.
- */
- template<auto Value, typename>
- inline constexpr auto unpack_as_value = Value;
- /**
- * @brief Wraps a static constant.
- * @tparam Value A static constant.
- */
- template<auto Value>
- using integral_constant = std::integral_constant<decltype(Value), Value>;
- /**
- * @brief Alias template to facilitate the creation of named values.
- * @tparam Value A constant value at least convertible to `id_type`.
- */
- template<id_type Value>
- using tag = integral_constant<Value>;
- /**
- * @brief A class to use to push around lists of types, nothing more.
- * @tparam Type Types provided by the type list.
- */
- template<typename... Type>
- struct type_list {
- /*! @brief Type list type. */
- using type = type_list;
- /*! @brief Compile-time number of elements in the type list. */
- static constexpr auto size = sizeof...(Type);
- };
- /*! @brief Primary template isn't defined on purpose. */
- template<std::size_t, typename>
- struct type_list_element;
- /**
- * @brief Provides compile-time indexed access to the types of a type list.
- * @tparam Index Index of the type to return.
- * @tparam First First type provided by the type list.
- * @tparam Other Other types provided by the type list.
- */
- template<std::size_t Index, typename First, typename... Other>
- struct type_list_element<Index, type_list<First, Other...>>
- : type_list_element<Index - 1u, type_list<Other...>> {};
- /**
- * @brief Provides compile-time indexed access to the types of a type list.
- * @tparam First First type provided by the type list.
- * @tparam Other Other types provided by the type list.
- */
- template<typename First, typename... Other>
- struct type_list_element<0u, type_list<First, Other...>> {
- /*! @brief Searched type. */
- using type = First;
- };
- /**
- * @brief Helper type.
- * @tparam Index Index of the type to return.
- * @tparam List Type list to search into.
- */
- template<std::size_t Index, typename List>
- using type_list_element_t = typename type_list_element<Index, List>::type;
- /*! @brief Primary template isn't defined on purpose. */
- template<typename, typename>
- struct type_list_index;
- /**
- * @brief Provides compile-time type access to the types of a type list.
- * @tparam Type Type to look for and for which to return the index.
- * @tparam First First type provided by the type list.
- * @tparam Other Other types provided by the type list.
- */
- template<typename Type, typename First, typename... Other>
- struct type_list_index<Type, type_list<First, Other...>> {
- /*! @brief Unsigned integer type. */
- using value_type = std::size_t;
- /*! @brief Compile-time position of the given type in the sublist. */
- static constexpr value_type value = 1u + type_list_index<Type, type_list<Other...>>::value;
- };
- /**
- * @brief Provides compile-time type access to the types of a type list.
- * @tparam Type Type to look for and for which to return the index.
- * @tparam Other Other types provided by the type list.
- */
- template<typename Type, typename... Other>
- struct type_list_index<Type, type_list<Type, Other...>> {
- static_assert(type_list_index<Type, type_list<Other...>>::value == sizeof...(Other), "Non-unique type");
- /*! @brief Unsigned integer type. */
- using value_type = std::size_t;
- /*! @brief Compile-time position of the given type in the sublist. */
- static constexpr value_type value = 0u;
- };
- /**
- * @brief Provides compile-time type access to the types of a type list.
- * @tparam Type Type to look for and for which to return the index.
- */
- template<typename Type>
- struct type_list_index<Type, type_list<>> {
- /*! @brief Unsigned integer type. */
- using value_type = std::size_t;
- /*! @brief Compile-time position of the given type in the sublist. */
- static constexpr value_type value = 0u;
- };
- /**
- * @brief Helper variable template.
- * @tparam List Type list.
- * @tparam Type Type to look for and for which to return the index.
- */
- template<typename Type, typename List>
- inline constexpr std::size_t type_list_index_v = type_list_index<Type, List>::value;
- /**
- * @brief Concatenates multiple type lists.
- * @tparam Type Types provided by the first type list.
- * @tparam Other Types provided by the second type list.
- * @return A type list composed by the types of both the type lists.
- */
- template<typename... Type, typename... Other>
- constexpr type_list<Type..., Other...> operator+(type_list<Type...>, type_list<Other...>) {
- return {};
- }
- /*! @brief Primary template isn't defined on purpose. */
- template<typename...>
- struct type_list_cat;
- /*! @brief Concatenates multiple type lists. */
- template<>
- struct type_list_cat<> {
- /*! @brief A type list composed by the types of all the type lists. */
- using type = type_list<>;
- };
- /**
- * @brief Concatenates multiple type lists.
- * @tparam Type Types provided by the first type list.
- * @tparam Other Types provided by the second type list.
- * @tparam List Other type lists, if any.
- */
- template<typename... Type, typename... Other, typename... List>
- struct type_list_cat<type_list<Type...>, type_list<Other...>, List...> {
- /*! @brief A type list composed by the types of all the type lists. */
- using type = typename type_list_cat<type_list<Type..., Other...>, List...>::type;
- };
- /**
- * @brief Concatenates multiple type lists.
- * @tparam Type Types provided by the type list.
- */
- template<typename... Type>
- struct type_list_cat<type_list<Type...>> {
- /*! @brief A type list composed by the types of all the type lists. */
- using type = type_list<Type...>;
- };
- /**
- * @brief Helper type.
- * @tparam List Type lists to concatenate.
- */
- template<typename... List>
- using type_list_cat_t = typename type_list_cat<List...>::type;
- /*! @cond TURN_OFF_DOXYGEN */
- namespace internal {
- template<typename...>
- struct type_list_unique;
- template<typename First, typename... Other, typename... Type>
- struct type_list_unique<type_list<First, Other...>, Type...>
- : std::conditional_t<(std::is_same_v<First, Type> || ...), type_list_unique<type_list<Other...>, Type...>, type_list_unique<type_list<Other...>, Type..., First>> {};
- template<typename... Type>
- struct type_list_unique<type_list<>, Type...> {
- using type = type_list<Type...>;
- };
- } // namespace internal
- /*! @endcond */
- /**
- * @brief Removes duplicates types from a type list.
- * @tparam List Type list.
- */
- template<typename List>
- struct type_list_unique {
- /*! @brief A type list without duplicate types. */
- using type = typename internal::type_list_unique<List>::type;
- };
- /**
- * @brief Helper type.
- * @tparam List Type list.
- */
- template<typename List>
- using type_list_unique_t = typename type_list_unique<List>::type;
- /**
- * @brief Provides the member constant `value` to true if a type list contains a
- * given type, false otherwise.
- * @tparam List Type list.
- * @tparam Type Type to look for.
- */
- template<typename List, typename Type>
- struct type_list_contains;
- /**
- * @copybrief type_list_contains
- * @tparam Type Types provided by the type list.
- * @tparam Other Type to look for.
- */
- template<typename... Type, typename Other>
- struct type_list_contains<type_list<Type...>, Other>
- : std::bool_constant<(std::is_same_v<Type, Other> || ...)> {};
- /**
- * @brief Helper variable template.
- * @tparam List Type list.
- * @tparam Type Type to look for.
- */
- template<typename List, typename Type>
- inline constexpr bool type_list_contains_v = type_list_contains<List, Type>::value;
- /*! @brief Primary template isn't defined on purpose. */
- template<typename...>
- struct type_list_diff;
- /**
- * @brief Computes the difference between two type lists.
- * @tparam Type Types provided by the first type list.
- * @tparam Other Types provided by the second type list.
- */
- template<typename... Type, typename... Other>
- struct type_list_diff<type_list<Type...>, type_list<Other...>> {
- /*! @brief A type list that is the difference between the two type lists. */
- using type = type_list_cat_t<std::conditional_t<type_list_contains_v<type_list<Other...>, Type>, type_list<>, type_list<Type>>...>;
- };
- /**
- * @brief Helper type.
- * @tparam List Type lists between which to compute the difference.
- */
- template<typename... List>
- using type_list_diff_t = typename type_list_diff<List...>::type;
- /*! @brief Primary template isn't defined on purpose. */
- template<typename, template<typename...> class>
- struct type_list_transform;
- /**
- * @brief Applies a given _function_ to a type list and generate a new list.
- * @tparam Type Types provided by the type list.
- * @tparam Op Unary operation as template class with a type member named `type`.
- */
- template<typename... Type, template<typename...> class Op>
- struct type_list_transform<type_list<Type...>, Op> {
- /*! @brief Resulting type list after applying the transform function. */
- // NOLINTNEXTLINE(modernize-type-traits)
- using type = type_list<typename Op<Type>::type...>;
- };
- /**
- * @brief Helper type.
- * @tparam List Type list.
- * @tparam Op Unary operation as template class with a type member named `type`.
- */
- template<typename List, template<typename...> class Op>
- using type_list_transform_t = typename type_list_transform<List, Op>::type;
- /**
- * @brief A class to use to push around lists of constant values, nothing more.
- * @tparam Value Values provided by the value list.
- */
- template<auto... Value>
- struct value_list {
- /*! @brief Value list type. */
- using type = value_list;
- /*! @brief Compile-time number of elements in the value list. */
- static constexpr auto size = sizeof...(Value);
- };
- /*! @brief Primary template isn't defined on purpose. */
- template<std::size_t, typename>
- struct value_list_element;
- /**
- * @brief Provides compile-time indexed access to the values of a value list.
- * @tparam Index Index of the value to return.
- * @tparam Value First value provided by the value list.
- * @tparam Other Other values provided by the value list.
- */
- template<std::size_t Index, auto Value, auto... Other>
- struct value_list_element<Index, value_list<Value, Other...>>
- : value_list_element<Index - 1u, value_list<Other...>> {};
- /**
- * @brief Provides compile-time indexed access to the types of a type list.
- * @tparam Value First value provided by the value list.
- * @tparam Other Other values provided by the value list.
- */
- template<auto Value, auto... Other>
- struct value_list_element<0u, value_list<Value, Other...>> {
- /*! @brief Searched type. */
- using type = decltype(Value);
- /*! @brief Searched value. */
- static constexpr auto value = Value;
- };
- /**
- * @brief Helper type.
- * @tparam Index Index of the type to return.
- * @tparam List Value list to search into.
- */
- template<std::size_t Index, typename List>
- using value_list_element_t = typename value_list_element<Index, List>::type;
- /**
- * @brief Helper type.
- * @tparam Index Index of the value to return.
- * @tparam List Value list to search into.
- */
- template<std::size_t Index, typename List>
- inline constexpr auto value_list_element_v = value_list_element<Index, List>::value;
- /*! @brief Primary template isn't defined on purpose. */
- template<auto, typename>
- struct value_list_index;
- /**
- * @brief Provides compile-time type access to the values of a value list.
- * @tparam Value Value to look for and for which to return the index.
- * @tparam First First value provided by the value list.
- * @tparam Other Other values provided by the value list.
- */
- template<auto Value, auto First, auto... Other>
- struct value_list_index<Value, value_list<First, Other...>> {
- /*! @brief Unsigned integer type. */
- using value_type = std::size_t;
- /*! @brief Compile-time position of the given value in the sublist. */
- static constexpr value_type value = 1u + value_list_index<Value, value_list<Other...>>::value;
- };
- /**
- * @brief Provides compile-time type access to the values of a value list.
- * @tparam Value Value to look for and for which to return the index.
- * @tparam Other Other values provided by the value list.
- */
- template<auto Value, auto... Other>
- struct value_list_index<Value, value_list<Value, Other...>> {
- static_assert(value_list_index<Value, value_list<Other...>>::value == sizeof...(Other), "Non-unique type");
- /*! @brief Unsigned integer type. */
- using value_type = std::size_t;
- /*! @brief Compile-time position of the given value in the sublist. */
- static constexpr value_type value = 0u;
- };
- /**
- * @brief Provides compile-time type access to the values of a value list.
- * @tparam Value Value to look for and for which to return the index.
- */
- template<auto Value>
- struct value_list_index<Value, value_list<>> {
- /*! @brief Unsigned integer type. */
- using value_type = std::size_t;
- /*! @brief Compile-time position of the given type in the sublist. */
- static constexpr value_type value = 0u;
- };
- /**
- * @brief Helper variable template.
- * @tparam List Value list.
- * @tparam Value Value to look for and for which to return the index.
- */
- template<auto Value, typename List>
- inline constexpr std::size_t value_list_index_v = value_list_index<Value, List>::value;
- /**
- * @brief Concatenates multiple value lists.
- * @tparam Value Values provided by the first value list.
- * @tparam Other Values provided by the second value list.
- * @return A value list composed by the values of both the value lists.
- */
- template<auto... Value, auto... Other>
- constexpr value_list<Value..., Other...> operator+(value_list<Value...>, value_list<Other...>) {
- return {};
- }
- /*! @brief Primary template isn't defined on purpose. */
- template<typename...>
- struct value_list_cat;
- /*! @brief Concatenates multiple value lists. */
- template<>
- struct value_list_cat<> {
- /*! @brief A value list composed by the values of all the value lists. */
- using type = value_list<>;
- };
- /**
- * @brief Concatenates multiple value lists.
- * @tparam Value Values provided by the first value list.
- * @tparam Other Values provided by the second value list.
- * @tparam List Other value lists, if any.
- */
- template<auto... Value, auto... Other, typename... List>
- struct value_list_cat<value_list<Value...>, value_list<Other...>, List...> {
- /*! @brief A value list composed by the values of all the value lists. */
- using type = typename value_list_cat<value_list<Value..., Other...>, List...>::type;
- };
- /**
- * @brief Concatenates multiple value lists.
- * @tparam Value Values provided by the value list.
- */
- template<auto... Value>
- struct value_list_cat<value_list<Value...>> {
- /*! @brief A value list composed by the values of all the value lists. */
- using type = value_list<Value...>;
- };
- /**
- * @brief Helper type.
- * @tparam List Value lists to concatenate.
- */
- template<typename... List>
- using value_list_cat_t = typename value_list_cat<List...>::type;
- /*! @brief Primary template isn't defined on purpose. */
- template<typename>
- struct value_list_unique;
- /**
- * @brief Removes duplicates values from a value list.
- * @tparam Value One of the values provided by the given value list.
- * @tparam Other The other values provided by the given value list.
- */
- template<auto Value, auto... Other>
- struct value_list_unique<value_list<Value, Other...>> {
- /*! @brief A value list without duplicate types. */
- using type = std::conditional_t<
- ((Value == Other) || ...),
- typename value_list_unique<value_list<Other...>>::type,
- value_list_cat_t<value_list<Value>, typename value_list_unique<value_list<Other...>>::type>>;
- };
- /*! @brief Removes duplicates values from a value list. */
- template<>
- struct value_list_unique<value_list<>> {
- /*! @brief A value list without duplicate types. */
- using type = value_list<>;
- };
- /**
- * @brief Helper type.
- * @tparam Type A value list.
- */
- template<typename Type>
- using value_list_unique_t = typename value_list_unique<Type>::type;
- /**
- * @brief Provides the member constant `value` to true if a value list contains
- * a given value, false otherwise.
- * @tparam List Value list.
- * @tparam Value Value to look for.
- */
- template<typename List, auto Value>
- struct value_list_contains;
- /**
- * @copybrief value_list_contains
- * @tparam Value Values provided by the value list.
- * @tparam Other Value to look for.
- */
- template<auto... Value, auto Other>
- struct value_list_contains<value_list<Value...>, Other>
- : std::bool_constant<((Value == Other) || ...)> {};
- /**
- * @brief Helper variable template.
- * @tparam List Value list.
- * @tparam Value Value to look for.
- */
- template<typename List, auto Value>
- inline constexpr bool value_list_contains_v = value_list_contains<List, Value>::value;
- /*! @brief Primary template isn't defined on purpose. */
- template<typename...>
- struct value_list_diff;
- /**
- * @brief Computes the difference between two value lists.
- * @tparam Value Values provided by the first value list.
- * @tparam Other Values provided by the second value list.
- */
- template<auto... Value, auto... Other>
- struct value_list_diff<value_list<Value...>, value_list<Other...>> {
- /*! @brief A value list that is the difference between the two value lists. */
- using type = value_list_cat_t<std::conditional_t<value_list_contains_v<value_list<Other...>, Value>, value_list<>, value_list<Value>>...>;
- };
- /**
- * @brief Helper type.
- * @tparam List Value lists between which to compute the difference.
- */
- template<typename... List>
- using value_list_diff_t = typename value_list_diff<List...>::type;
- /*! @brief Same as std::is_invocable, but with tuples. */
- template<typename, typename>
- struct is_applicable: std::false_type {};
- /**
- * @copybrief is_applicable
- * @tparam Func A valid function type.
- * @tparam Tuple Tuple-like type.
- * @tparam Args The list of arguments to use to probe the function type.
- */
- template<typename Func, template<typename...> class Tuple, typename... Args>
- struct is_applicable<Func, Tuple<Args...>>: std::is_invocable<Func, Args...> {};
- /**
- * @copybrief is_applicable
- * @tparam Func A valid function type.
- * @tparam Tuple Tuple-like type.
- * @tparam Args The list of arguments to use to probe the function type.
- */
- template<typename Func, template<typename...> class Tuple, typename... Args>
- struct is_applicable<Func, const Tuple<Args...>>: std::is_invocable<Func, Args...> {};
- /**
- * @brief Helper variable template.
- * @tparam Func A valid function type.
- * @tparam Args The list of arguments to use to probe the function type.
- */
- template<typename Func, typename Args>
- inline constexpr bool is_applicable_v = is_applicable<Func, Args>::value;
- /*! @brief Same as std::is_invocable_r, but with tuples for arguments. */
- template<typename, typename, typename>
- struct is_applicable_r: std::false_type {};
- /**
- * @copybrief is_applicable_r
- * @tparam Ret The type to which the return type of the function should be
- * convertible.
- * @tparam Func A valid function type.
- * @tparam Args The list of arguments to use to probe the function type.
- */
- template<typename Ret, typename Func, typename... Args>
- struct is_applicable_r<Ret, Func, std::tuple<Args...>>: std::is_invocable_r<Ret, Func, Args...> {};
- /**
- * @brief Helper variable template.
- * @tparam Ret The type to which the return type of the function should be
- * convertible.
- * @tparam Func A valid function type.
- * @tparam Args The list of arguments to use to probe the function type.
- */
- template<typename Ret, typename Func, typename Args>
- inline constexpr bool is_applicable_r_v = is_applicable_r<Ret, Func, Args>::value;
- /**
- * @brief Provides the member constant `value` to true if a given type is
- * complete, false otherwise.
- * @tparam Type The type to test.
- */
- template<typename Type, typename = void>
- struct is_complete: std::false_type {};
- /*! @copydoc is_complete */
- template<typename Type>
- struct is_complete<Type, std::void_t<decltype(sizeof(Type))>>: std::true_type {};
- /**
- * @brief Helper variable template.
- * @tparam Type The type to test.
- */
- template<typename Type>
- inline constexpr bool is_complete_v = is_complete<Type>::value;
- /**
- * @brief Provides the member constant `value` to true if a given type is an
- * iterator, false otherwise.
- * @tparam Type The type to test.
- */
- template<typename Type, typename = void>
- struct is_iterator: std::false_type {};
- /*! @cond TURN_OFF_DOXYGEN */
- namespace internal {
- template<typename, typename = void>
- struct has_iterator_category: std::false_type {};
- template<typename Type>
- struct has_iterator_category<Type, std::void_t<typename std::iterator_traits<Type>::iterator_category>>: std::true_type {};
- } // namespace internal
- /*! @endcond */
- /*! @copydoc is_iterator */
- template<typename Type>
- struct is_iterator<Type, std::enable_if_t<!std::is_void_v<std::remove_const_t<std::remove_pointer_t<Type>>>>>
- : internal::has_iterator_category<Type> {};
- /**
- * @brief Helper variable template.
- * @tparam Type The type to test.
- */
- template<typename Type>
- inline constexpr bool is_iterator_v = is_iterator<Type>::value;
- /**
- * @brief Provides the member constant `value` to true if a given type is both
- * an empty and non-final class, false otherwise.
- * @tparam Type The type to test
- */
- template<typename Type>
- struct is_ebco_eligible
- : std::bool_constant<std::is_empty_v<Type> && !std::is_final_v<Type>> {};
- /**
- * @brief Helper variable template.
- * @tparam Type The type to test.
- */
- template<typename Type>
- inline constexpr bool is_ebco_eligible_v = is_ebco_eligible<Type>::value;
- /**
- * @brief Provides the member constant `value` to true if `Type::is_transparent`
- * is valid and denotes a type, false otherwise.
- * @tparam Type The type to test.
- */
- template<typename Type, typename = void>
- struct is_transparent: std::false_type {};
- /*! @copydoc is_transparent */
- template<typename Type>
- struct is_transparent<Type, std::void_t<typename Type::is_transparent>>: std::true_type {};
- /**
- * @brief Helper variable template.
- * @tparam Type The type to test.
- */
- template<typename Type>
- inline constexpr bool is_transparent_v = is_transparent<Type>::value;
- /*! @cond TURN_OFF_DOXYGEN */
- namespace internal {
- template<typename, typename = void>
- struct has_tuple_size_value: std::false_type {};
- template<typename Type>
- struct has_tuple_size_value<Type, std::void_t<decltype(std::tuple_size<const Type>::value)>>: std::true_type {};
- template<typename, typename = void>
- struct has_value_type: std::false_type {};
- template<typename Type>
- struct has_value_type<Type, std::void_t<typename Type::value_type>>: std::true_type {};
- template<typename>
- [[nodiscard]] constexpr bool dispatch_is_equality_comparable();
- template<typename Type, std::size_t... Index>
- [[nodiscard]] constexpr bool unpack_maybe_equality_comparable(std::index_sequence<Index...>) {
- return (dispatch_is_equality_comparable<std::tuple_element_t<Index, Type>>() && ...);
- }
- template<typename>
- [[nodiscard]] constexpr bool maybe_equality_comparable(char) {
- return false;
- }
- template<typename Type>
- [[nodiscard]] constexpr auto maybe_equality_comparable(int) -> decltype(std::declval<Type>() == std::declval<Type>()) {
- return true;
- }
- template<typename Type>
- [[nodiscard]] constexpr bool dispatch_is_equality_comparable() {
- // NOLINTBEGIN(modernize-use-transparent-functors)
- if constexpr(std::is_array_v<Type>) {
- return false;
- } else if constexpr(is_complete_v<std::tuple_size<std::remove_const_t<Type>>>) {
- if constexpr(has_tuple_size_value<Type>::value) {
- return maybe_equality_comparable<Type>(0) && unpack_maybe_equality_comparable<Type>(std::make_index_sequence<std::tuple_size<Type>::value>{});
- } else {
- return maybe_equality_comparable<Type>(0);
- }
- } else if constexpr(has_value_type<Type>::value) {
- if constexpr(is_iterator_v<Type> || std::is_same_v<typename Type::value_type, Type> || dispatch_is_equality_comparable<typename Type::value_type>()) {
- return maybe_equality_comparable<Type>(0);
- } else {
- return false;
- }
- } else {
- return maybe_equality_comparable<Type>(0);
- }
- // NOLINTEND(modernize-use-transparent-functors)
- }
- } // namespace internal
- /*! @endcond */
- /**
- * @brief Provides the member constant `value` to true if a given type is
- * equality comparable, false otherwise.
- * @tparam Type The type to test.
- */
- template<typename Type>
- struct is_equality_comparable: std::bool_constant<internal::dispatch_is_equality_comparable<Type>()> {};
- /*! @copydoc is_equality_comparable */
- template<typename Type>
- struct is_equality_comparable<const Type>: is_equality_comparable<Type> {};
- /**
- * @brief Helper variable template.
- * @tparam Type The type to test.
- */
- template<typename Type>
- inline constexpr bool is_equality_comparable_v = is_equality_comparable<Type>::value;
- /**
- * @brief Transcribes the constness of a type to another type.
- * @tparam To The type to which to transcribe the constness.
- * @tparam From The type from which to transcribe the constness.
- */
- template<typename To, typename From>
- struct constness_as {
- /*! @brief The type resulting from the transcription of the constness. */
- using type = std::remove_const_t<To>;
- };
- /*! @copydoc constness_as */
- template<typename To, typename From>
- struct constness_as<To, const From> {
- /*! @brief The type resulting from the transcription of the constness. */
- using type = const To;
- };
- /**
- * @brief Alias template to facilitate the transcription of the constness.
- * @tparam To The type to which to transcribe the constness.
- * @tparam From The type from which to transcribe the constness.
- */
- template<typename To, typename From>
- using constness_as_t = typename constness_as<To, From>::type;
- /**
- * @brief Extracts the class of a non-static member object or function.
- * @tparam Member A pointer to a non-static member object or function.
- */
- template<typename Member>
- class member_class {
- static_assert(std::is_member_pointer_v<Member>, "Invalid pointer type to non-static member object or function");
- template<typename Class, typename Ret, typename... Args>
- static Class *clazz(Ret (Class::*)(Args...));
- template<typename Class, typename Ret, typename... Args>
- static Class *clazz(Ret (Class::*)(Args...) const);
- template<typename Class, typename Type>
- static Class *clazz(Type Class::*);
- public:
- /*! @brief The class of the given non-static member object or function. */
- using type = std::remove_pointer_t<decltype(clazz(std::declval<Member>()))>;
- };
- /**
- * @brief Helper type.
- * @tparam Member A pointer to a non-static member object or function.
- */
- template<typename Member>
- using member_class_t = typename member_class<Member>::type;
- /**
- * @brief Extracts the n-th argument of a _callable_ type.
- * @tparam Index The index of the argument to extract.
- * @tparam Candidate A valid _callable_ type.
- */
- template<std::size_t Index, typename Candidate>
- class nth_argument {
- template<typename Ret, typename... Args>
- static constexpr type_list<Args...> pick_up(Ret (*)(Args...));
- template<typename Ret, typename Class, typename... Args>
- static constexpr type_list<Args...> pick_up(Ret (Class ::*)(Args...));
- template<typename Ret, typename Class, typename... Args>
- static constexpr type_list<Args...> pick_up(Ret (Class ::*)(Args...) const);
- template<typename Type, typename Class>
- static constexpr type_list<Type> pick_up(Type Class ::*);
- template<typename Type>
- static constexpr decltype(pick_up(&Type::operator())) pick_up(Type &&);
- public:
- /*! @brief N-th argument of the _callable_ type. */
- using type = type_list_element_t<Index, decltype(pick_up(std::declval<Candidate>()))>;
- };
- /**
- * @brief Helper type.
- * @tparam Index The index of the argument to extract.
- * @tparam Candidate A valid function, member function or data member type.
- */
- template<std::size_t Index, typename Candidate>
- using nth_argument_t = typename nth_argument<Index, Candidate>::type;
- } // namespace entt
- template<typename... Type>
- struct std::tuple_size<entt::type_list<Type...>>: std::integral_constant<std::size_t, entt::type_list<Type...>::size> {};
- template<std::size_t Index, typename... Type>
- struct std::tuple_element<Index, entt::type_list<Type...>>: entt::type_list_element<Index, entt::type_list<Type...>> {};
- template<auto... Value>
- struct std::tuple_size<entt::value_list<Value...>>: std::integral_constant<std::size_t, entt::value_list<Value...>::size> {};
- template<std::size_t Index, auto... Value>
- struct std::tuple_element<Index, entt::value_list<Value...>>: entt::value_list_element<Index, entt::value_list<Value...>> {};
- #endif
- namespace entt {
- /*! @cond TURN_OFF_DOXYGEN */
- namespace internal {
- template<typename Type, std::size_t, typename = void>
- struct compressed_pair_element {
- using reference = Type &;
- using const_reference = const Type &;
- template<typename Dummy = Type, typename = std::enable_if_t<std::is_default_constructible_v<Dummy>>>
- // NOLINTNEXTLINE(modernize-use-equals-default)
- constexpr compressed_pair_element() noexcept(std::is_nothrow_default_constructible_v<Type>) {}
- template<typename Arg, typename = std::enable_if_t<!std::is_same_v<std::remove_const_t<std::remove_reference_t<Arg>>, compressed_pair_element>>>
- constexpr compressed_pair_element(Arg &&arg) noexcept(std::is_nothrow_constructible_v<Type, Arg>)
- : value{std::forward<Arg>(arg)} {}
- template<typename... Args, std::size_t... Index>
- constexpr compressed_pair_element(std::tuple<Args...> args, std::index_sequence<Index...>) noexcept(std::is_nothrow_constructible_v<Type, Args...>)
- : value{std::forward<Args>(std::get<Index>(args))...} {}
- [[nodiscard]] constexpr reference get() noexcept {
- return value;
- }
- [[nodiscard]] constexpr const_reference get() const noexcept {
- return value;
- }
- private:
- Type value{};
- };
- template<typename Type, std::size_t Tag>
- struct compressed_pair_element<Type, Tag, std::enable_if_t<is_ebco_eligible_v<Type>>>: Type {
- using reference = Type &;
- using const_reference = const Type &;
- using base_type = Type;
- template<typename Dummy = Type, typename = std::enable_if_t<std::is_default_constructible_v<Dummy>>>
- constexpr compressed_pair_element() noexcept(std::is_nothrow_default_constructible_v<base_type>)
- : base_type{} {}
- template<typename Arg, typename = std::enable_if_t<!std::is_same_v<std::remove_const_t<std::remove_reference_t<Arg>>, compressed_pair_element>>>
- constexpr compressed_pair_element(Arg &&arg) noexcept(std::is_nothrow_constructible_v<base_type, Arg>)
- : base_type{std::forward<Arg>(arg)} {}
- template<typename... Args, std::size_t... Index>
- constexpr compressed_pair_element(std::tuple<Args...> args, std::index_sequence<Index...>) noexcept(std::is_nothrow_constructible_v<base_type, Args...>)
- : base_type{std::forward<Args>(std::get<Index>(args))...} {}
- [[nodiscard]] constexpr reference get() noexcept {
- return *this;
- }
- [[nodiscard]] constexpr const_reference get() const noexcept {
- return *this;
- }
- };
- } // namespace internal
- /*! @endcond */
- /**
- * @brief A compressed pair.
- *
- * A pair that exploits the _Empty Base Class Optimization_ (or _EBCO_) to
- * reduce its final size to a minimum.
- *
- * @tparam First The type of the first element that the pair stores.
- * @tparam Second The type of the second element that the pair stores.
- */
- template<typename First, typename Second>
- class compressed_pair final
- : internal::compressed_pair_element<First, 0u>,
- internal::compressed_pair_element<Second, 1u> {
- using first_base = internal::compressed_pair_element<First, 0u>;
- using second_base = internal::compressed_pair_element<Second, 1u>;
- public:
- /*! @brief The type of the first element that the pair stores. */
- using first_type = First;
- /*! @brief The type of the second element that the pair stores. */
- using second_type = Second;
- /**
- * @brief Default constructor, conditionally enabled.
- *
- * This constructor is only available when the types that the pair stores
- * are both at least default constructible.
- *
- * @tparam Dummy Dummy template parameter used for internal purposes.
- */
- template<bool Dummy = true, typename = std::enable_if_t<Dummy && std::is_default_constructible_v<first_type> && std::is_default_constructible_v<second_type>>>
- constexpr compressed_pair() noexcept(std::is_nothrow_default_constructible_v<first_base> && std::is_nothrow_default_constructible_v<second_base>)
- : first_base{},
- second_base{} {}
- /**
- * @brief Copy constructor.
- * @param other The instance to copy from.
- */
- constexpr compressed_pair(const compressed_pair &other) = default;
- /**
- * @brief Move constructor.
- * @param other The instance to move from.
- */
- constexpr compressed_pair(compressed_pair &&other) noexcept = default;
- /**
- * @brief Constructs a pair from its values.
- * @tparam Arg Type of value to use to initialize the first element.
- * @tparam Other Type of value to use to initialize the second element.
- * @param arg Value to use to initialize the first element.
- * @param other Value to use to initialize the second element.
- */
- template<typename Arg, typename Other>
- constexpr compressed_pair(Arg &&arg, Other &&other) noexcept(std::is_nothrow_constructible_v<first_base, Arg> && std::is_nothrow_constructible_v<second_base, Other>)
- : first_base{std::forward<Arg>(arg)},
- second_base{std::forward<Other>(other)} {}
- /**
- * @brief Constructs a pair by forwarding the arguments to its parts.
- * @tparam Args Types of arguments to use to initialize the first element.
- * @tparam Other Types of arguments to use to initialize the second element.
- * @param args Arguments to use to initialize the first element.
- * @param other Arguments to use to initialize the second element.
- */
- template<typename... Args, typename... Other>
- constexpr compressed_pair(std::piecewise_construct_t, std::tuple<Args...> args, std::tuple<Other...> other) noexcept(std::is_nothrow_constructible_v<first_base, Args...> && std::is_nothrow_constructible_v<second_base, Other...>)
- : first_base{std::move(args), std::index_sequence_for<Args...>{}},
- second_base{std::move(other), std::index_sequence_for<Other...>{}} {}
- /*! @brief Default destructor. */
- ~compressed_pair() = default;
- /**
- * @brief Copy assignment operator.
- * @param other The instance to copy from.
- * @return This compressed pair object.
- */
- constexpr compressed_pair &operator=(const compressed_pair &other) = default;
- /**
- * @brief Move assignment operator.
- * @param other The instance to move from.
- * @return This compressed pair object.
- */
- constexpr compressed_pair &operator=(compressed_pair &&other) noexcept = default;
- /**
- * @brief Returns the first element that a pair stores.
- * @return The first element that a pair stores.
- */
- [[nodiscard]] constexpr first_type &first() noexcept {
- return static_cast<first_base &>(*this).get();
- }
- /*! @copydoc first */
- [[nodiscard]] constexpr const first_type &first() const noexcept {
- return static_cast<const first_base &>(*this).get();
- }
- /**
- * @brief Returns the second element that a pair stores.
- * @return The second element that a pair stores.
- */
- [[nodiscard]] constexpr second_type &second() noexcept {
- return static_cast<second_base &>(*this).get();
- }
- /*! @copydoc second */
- [[nodiscard]] constexpr const second_type &second() const noexcept {
- return static_cast<const second_base &>(*this).get();
- }
- /**
- * @brief Swaps two compressed pair objects.
- * @param other The compressed pair to swap with.
- */
- constexpr void swap(compressed_pair &other) noexcept {
- using std::swap;
- swap(first(), other.first());
- swap(second(), other.second());
- }
- /**
- * @brief Extracts an element from the compressed pair.
- * @tparam Index An integer value that is either 0 or 1.
- * @return Returns a reference to the first element if `Index` is 0 and a
- * reference to the second element if `Index` is 1.
- */
- template<std::size_t Index>
- [[nodiscard]] constexpr decltype(auto) get() noexcept {
- if constexpr(Index == 0u) {
- return first();
- } else {
- static_assert(Index == 1u, "Index out of bounds");
- return second();
- }
- }
- /*! @copydoc get */
- template<std::size_t Index>
- [[nodiscard]] constexpr decltype(auto) get() const noexcept {
- if constexpr(Index == 0u) {
- return first();
- } else {
- static_assert(Index == 1u, "Index out of bounds");
- return second();
- }
- }
- };
- /**
- * @brief Deduction guide.
- * @tparam Type Type of value to use to initialize the first element.
- * @tparam Other Type of value to use to initialize the second element.
- */
- template<typename Type, typename Other>
- compressed_pair(Type &&, Other &&) -> compressed_pair<std::decay_t<Type>, std::decay_t<Other>>;
- /**
- * @brief Swaps two compressed pair objects.
- * @tparam First The type of the first element that the pairs store.
- * @tparam Second The type of the second element that the pairs store.
- * @param lhs A valid compressed pair object.
- * @param rhs A valid compressed pair object.
- */
- template<typename First, typename Second>
- constexpr void swap(compressed_pair<First, Second> &lhs, compressed_pair<First, Second> &rhs) noexcept {
- lhs.swap(rhs);
- }
- } // namespace entt
- namespace std {
- /**
- * @brief `std::tuple_size` specialization for `compressed_pair`s.
- * @tparam First The type of the first element that the pair stores.
- * @tparam Second The type of the second element that the pair stores.
- */
- template<typename First, typename Second>
- struct tuple_size<entt::compressed_pair<First, Second>>: integral_constant<size_t, 2u> {};
- /**
- * @brief `std::tuple_element` specialization for `compressed_pair`s.
- * @tparam Index The index of the type to return.
- * @tparam First The type of the first element that the pair stores.
- * @tparam Second The type of the second element that the pair stores.
- */
- template<size_t Index, typename First, typename Second>
- struct tuple_element<Index, entt::compressed_pair<First, Second>>: conditional<Index == 0u, First, Second> {
- static_assert(Index < 2u, "Index out of bounds");
- };
- } // namespace std
- #endif
- // #include "../core/fwd.hpp"
- #ifndef ENTT_CORE_FWD_HPP
- #define ENTT_CORE_FWD_HPP
- #include <cstddef>
- #include <cstdint>
- // #include "../config/config.h"
- namespace entt {
- /*! @brief Possible modes of an any object. */
- enum class any_policy : std::uint8_t {
- /*! @brief Default mode, no element available. */
- empty,
- /*! @brief Owning mode, dynamically allocated element. */
- dynamic,
- /*! @brief Owning mode, embedded element. */
- embedded,
- /*! @brief Aliasing mode, non-const reference. */
- ref,
- /*! @brief Const aliasing mode, const reference. */
- cref
- };
- // NOLINTNEXTLINE(cppcoreguidelines-avoid-c-arrays, modernize-avoid-c-arrays)
- template<std::size_t Len = sizeof(double[2]), std::size_t = alignof(double[2])>
- class basic_any;
- /*! @brief Alias declaration for type identifiers. */
- using id_type = ENTT_ID_TYPE;
- /*! @brief Alias declaration for the most common use case. */
- using any = basic_any<>;
- template<typename, typename>
- class compressed_pair;
- template<typename>
- class basic_hashed_string;
- /*! @brief Aliases for common character types. */
- using hashed_string = basic_hashed_string<char>;
- /*! @brief Aliases for common character types. */
- using hashed_wstring = basic_hashed_string<wchar_t>;
- // NOLINTNEXTLINE(bugprone-forward-declaration-namespace)
- struct type_info;
- } // namespace entt
- #endif
- // #include "../core/type_info.hpp"
- #ifndef ENTT_CORE_TYPE_INFO_HPP
- #define ENTT_CORE_TYPE_INFO_HPP
- #include <string_view>
- #include <type_traits>
- #include <utility>
- // #include "../config/config.h"
- // #include "fwd.hpp"
- // #include "hashed_string.hpp"
- #ifndef ENTT_CORE_HASHED_STRING_HPP
- #define ENTT_CORE_HASHED_STRING_HPP
- #include <cstddef>
- #include <cstdint>
- // #include "fwd.hpp"
- namespace entt {
- /*! @cond TURN_OFF_DOXYGEN */
- namespace internal {
- template<typename = id_type>
- struct fnv_1a_params;
- template<>
- struct fnv_1a_params<std::uint32_t> {
- static constexpr auto offset = 2166136261;
- static constexpr auto prime = 16777619;
- };
- template<>
- struct fnv_1a_params<std::uint64_t> {
- static constexpr auto offset = 14695981039346656037ull;
- static constexpr auto prime = 1099511628211ull;
- };
- template<typename Char>
- struct basic_hashed_string {
- using value_type = Char;
- using size_type = std::size_t;
- using hash_type = id_type;
- const value_type *repr{};
- hash_type hash{fnv_1a_params<>::offset};
- size_type length{};
- };
- } // namespace internal
- /*! @endcond */
- /**
- * @brief Zero overhead unique identifier.
- *
- * A hashed string is a compile-time tool that allows users to use
- * human-readable identifiers in the codebase while using their numeric
- * counterparts at runtime.<br/>
- * Because of that, a hashed string can also be used in constant expressions if
- * required.
- *
- * @warning
- * This class doesn't take ownership of user-supplied strings nor does it make a
- * copy of them.
- *
- * @tparam Char Character type.
- */
- template<typename Char>
- class basic_hashed_string: internal::basic_hashed_string<Char> {
- using base_type = internal::basic_hashed_string<Char>;
- using params = internal::fnv_1a_params<>;
- struct const_wrapper {
- // non-explicit constructor on purpose
- constexpr const_wrapper(const typename base_type::value_type *str) noexcept
- : repr{str} {}
- const typename base_type::value_type *repr;
- };
- public:
- /*! @brief Character type. */
- using value_type = typename base_type::value_type;
- /*! @brief Unsigned integer type. */
- using size_type = typename base_type::size_type;
- /*! @brief Unsigned integer type. */
- using hash_type = typename base_type::hash_type;
- /**
- * @brief Returns directly the numeric representation of a string view.
- * @param str Human-readable identifier.
- * @param len Length of the string to hash.
- * @return The numeric representation of the string.
- */
- [[nodiscard]] static constexpr hash_type value(const value_type *str, const size_type len) noexcept {
- return basic_hashed_string{str, len};
- }
- /**
- * @brief Returns directly the numeric representation of a string.
- * @tparam N Number of characters of the identifier.
- * @param str Human-readable identifier.
- * @return The numeric representation of the string.
- */
- template<std::size_t N>
- // NOLINTNEXTLINE(cppcoreguidelines-avoid-c-arrays, modernize-avoid-c-arrays)
- [[nodiscard]] static ENTT_CONSTEVAL hash_type value(const value_type (&str)[N]) noexcept {
- return basic_hashed_string{str};
- }
- /**
- * @brief Returns directly the numeric representation of a string.
- * @param wrapper Helps achieving the purpose by relying on overloading.
- * @return The numeric representation of the string.
- */
- [[nodiscard]] static constexpr hash_type value(const_wrapper wrapper) noexcept {
- return basic_hashed_string{wrapper};
- }
- /*! @brief Constructs an empty hashed string. */
- constexpr basic_hashed_string() noexcept
- : basic_hashed_string{nullptr, 0u} {}
- /**
- * @brief Constructs a hashed string from a string view.
- * @param str Human-readable identifier.
- * @param len Length of the string to hash.
- */
- constexpr basic_hashed_string(const value_type *str, const size_type len) noexcept
- // NOLINTNEXTLINE(cppcoreguidelines-pro-bounds-array-to-pointer-decay)
- : base_type{str} {
- // NOLINTBEGIN(cppcoreguidelines-pro-bounds-pointer-arithmetic)
- for(; base_type::length < len; ++base_type::length) {
- base_type::hash = (base_type::hash ^ static_cast<id_type>(str[base_type::length])) * params::prime;
- }
- // NOLINTEND(cppcoreguidelines-pro-bounds-pointer-arithmetic)
- }
- /**
- * @brief Constructs a hashed string from an array of const characters.
- * @tparam N Number of characters of the identifier.
- * @param str Human-readable identifier.
- */
- template<std::size_t N>
- // NOLINTNEXTLINE(cppcoreguidelines-avoid-c-arrays, modernize-avoid-c-arrays)
- ENTT_CONSTEVAL basic_hashed_string(const value_type (&str)[N]) noexcept
- // NOLINTNEXTLINE(cppcoreguidelines-pro-bounds-array-to-pointer-decay)
- : base_type{str} {
- for(; str[base_type::length]; ++base_type::length) {
- base_type::hash = (base_type::hash ^ static_cast<id_type>(str[base_type::length])) * params::prime;
- }
- }
- /**
- * @brief Explicit constructor on purpose to avoid constructing a hashed
- * string directly from a `const value_type *`.
- *
- * @warning
- * The lifetime of the string is not extended nor is it copied.
- *
- * @param wrapper Helps achieving the purpose by relying on overloading.
- */
- explicit constexpr basic_hashed_string(const_wrapper wrapper) noexcept
- : base_type{wrapper.repr} {
- // NOLINTBEGIN(cppcoreguidelines-pro-bounds-pointer-arithmetic)
- for(; wrapper.repr[base_type::length]; ++base_type::length) {
- base_type::hash = (base_type::hash ^ static_cast<id_type>(wrapper.repr[base_type::length])) * params::prime;
- }
- // NOLINTEND(cppcoreguidelines-pro-bounds-pointer-arithmetic)
- }
- /**
- * @brief Returns the size of a hashed string.
- * @return The size of the hashed string.
- */
- [[nodiscard]] constexpr size_type size() const noexcept {
- return base_type::length;
- }
- /**
- * @brief Returns the human-readable representation of a hashed string.
- * @return The string used to initialize the hashed string.
- */
- [[nodiscard]] constexpr const value_type *data() const noexcept {
- return base_type::repr;
- }
- /**
- * @brief Returns the numeric representation of a hashed string.
- * @return The numeric representation of the hashed string.
- */
- [[nodiscard]] constexpr hash_type value() const noexcept {
- return base_type::hash;
- }
- /*! @copydoc data */
- [[nodiscard]] explicit constexpr operator const value_type *() const noexcept {
- return data();
- }
- /**
- * @brief Returns the numeric representation of a hashed string.
- * @return The numeric representation of the hashed string.
- */
- [[nodiscard]] constexpr operator hash_type() const noexcept {
- return value();
- }
- };
- /**
- * @brief Deduction guide.
- * @tparam Char Character type.
- * @param str Human-readable identifier.
- * @param len Length of the string to hash.
- */
- template<typename Char>
- basic_hashed_string(const Char *str, std::size_t len) -> basic_hashed_string<Char>;
- /**
- * @brief Deduction guide.
- * @tparam Char Character type.
- * @tparam N Number of characters of the identifier.
- * @param str Human-readable identifier.
- */
- template<typename Char, std::size_t N>
- // NOLINTNEXTLINE(cppcoreguidelines-avoid-c-arrays, modernize-avoid-c-arrays)
- basic_hashed_string(const Char (&str)[N]) -> basic_hashed_string<Char>;
- /**
- * @brief Compares two hashed strings.
- * @tparam Char Character type.
- * @param lhs A valid hashed string.
- * @param rhs A valid hashed string.
- * @return True if the two hashed strings are identical, false otherwise.
- */
- template<typename Char>
- [[nodiscard]] constexpr bool operator==(const basic_hashed_string<Char> &lhs, const basic_hashed_string<Char> &rhs) noexcept {
- return lhs.value() == rhs.value();
- }
- /**
- * @brief Compares two hashed strings.
- * @tparam Char Character type.
- * @param lhs A valid hashed string.
- * @param rhs A valid hashed string.
- * @return True if the two hashed strings differ, false otherwise.
- */
- template<typename Char>
- [[nodiscard]] constexpr bool operator!=(const basic_hashed_string<Char> &lhs, const basic_hashed_string<Char> &rhs) noexcept {
- return !(lhs == rhs);
- }
- /**
- * @brief Compares two hashed strings.
- * @tparam Char Character type.
- * @param lhs A valid hashed string.
- * @param rhs A valid hashed string.
- * @return True if the first element is less than the second, false otherwise.
- */
- template<typename Char>
- [[nodiscard]] constexpr bool operator<(const basic_hashed_string<Char> &lhs, const basic_hashed_string<Char> &rhs) noexcept {
- return lhs.value() < rhs.value();
- }
- /**
- * @brief Compares two hashed strings.
- * @tparam Char Character type.
- * @param lhs A valid hashed string.
- * @param rhs A valid hashed string.
- * @return True if the first element is less than or equal to the second, false
- * otherwise.
- */
- template<typename Char>
- [[nodiscard]] constexpr bool operator<=(const basic_hashed_string<Char> &lhs, const basic_hashed_string<Char> &rhs) noexcept {
- return !(rhs < lhs);
- }
- /**
- * @brief Compares two hashed strings.
- * @tparam Char Character type.
- * @param lhs A valid hashed string.
- * @param rhs A valid hashed string.
- * @return True if the first element is greater than the second, false
- * otherwise.
- */
- template<typename Char>
- [[nodiscard]] constexpr bool operator>(const basic_hashed_string<Char> &lhs, const basic_hashed_string<Char> &rhs) noexcept {
- return rhs < lhs;
- }
- /**
- * @brief Compares two hashed strings.
- * @tparam Char Character type.
- * @param lhs A valid hashed string.
- * @param rhs A valid hashed string.
- * @return True if the first element is greater than or equal to the second,
- * false otherwise.
- */
- template<typename Char>
- [[nodiscard]] constexpr bool operator>=(const basic_hashed_string<Char> &lhs, const basic_hashed_string<Char> &rhs) noexcept {
- return !(lhs < rhs);
- }
- inline namespace literals {
- /**
- * @brief User defined literal for hashed strings.
- * @param str The literal without its suffix.
- * @return A properly initialized hashed string.
- */
- [[nodiscard]] ENTT_CONSTEVAL hashed_string operator""_hs(const char *str, std::size_t) noexcept {
- return hashed_string{str};
- }
- /**
- * @brief User defined literal for hashed wstrings.
- * @param str The literal without its suffix.
- * @return A properly initialized hashed wstring.
- */
- [[nodiscard]] ENTT_CONSTEVAL hashed_wstring operator""_hws(const wchar_t *str, std::size_t) noexcept {
- return hashed_wstring{str};
- }
- } // namespace literals
- } // namespace entt
- #endif
- namespace entt {
- /*! @cond TURN_OFF_DOXYGEN */
- namespace internal {
- struct ENTT_API type_index final {
- [[nodiscard]] static id_type next() noexcept {
- static ENTT_MAYBE_ATOMIC(id_type) value{};
- return value++;
- }
- };
- template<typename Type>
- [[nodiscard]] constexpr const char *pretty_function() noexcept {
- #if defined ENTT_PRETTY_FUNCTION
- return static_cast<const char *>(ENTT_PRETTY_FUNCTION);
- #else
- return "";
- #endif
- }
- template<typename Type>
- [[nodiscard]] constexpr auto stripped_type_name() noexcept {
- #if defined ENTT_PRETTY_FUNCTION
- const std::string_view full_name{pretty_function<Type>()};
- auto first = full_name.find_first_not_of(' ', full_name.find_first_of(ENTT_PRETTY_FUNCTION_PREFIX) + 1);
- auto value = full_name.substr(first, full_name.find_last_of(ENTT_PRETTY_FUNCTION_SUFFIX) - first);
- return value;
- #else
- return std::string_view{};
- #endif
- }
- template<typename Type, auto = stripped_type_name<Type>().find_first_of('.')>
- [[nodiscard]] constexpr std::string_view type_name(int) noexcept {
- constexpr auto value = stripped_type_name<Type>();
- return value;
- }
- template<typename Type>
- [[nodiscard]] std::string_view type_name(char) noexcept {
- static const auto value = stripped_type_name<Type>();
- return value;
- }
- template<typename Type, auto = stripped_type_name<Type>().find_first_of('.')>
- [[nodiscard]] constexpr id_type type_hash(int) noexcept {
- constexpr auto stripped = stripped_type_name<Type>();
- constexpr auto value = hashed_string::value(stripped.data(), stripped.size());
- return value;
- }
- template<typename Type>
- [[nodiscard]] id_type type_hash(char) noexcept {
- static const auto value = [](const auto stripped) {
- return hashed_string::value(stripped.data(), stripped.size());
- }(stripped_type_name<Type>());
- return value;
- }
- } // namespace internal
- /*! @endcond */
- /**
- * @brief Type sequential identifier.
- * @tparam Type Type for which to generate a sequential identifier.
- */
- template<typename Type, typename = void>
- struct ENTT_API type_index final {
- /**
- * @brief Returns the sequential identifier of a given type.
- * @return The sequential identifier of a given type.
- */
- [[nodiscard]] static id_type value() noexcept {
- static const id_type value = internal::type_index::next();
- return value;
- }
- /*! @copydoc value */
- [[nodiscard]] constexpr operator id_type() const noexcept {
- return value();
- }
- };
- /**
- * @brief Type hash.
- * @tparam Type Type for which to generate a hash value.
- */
- template<typename Type, typename = void>
- struct type_hash final {
- /**
- * @brief Returns the numeric representation of a given type.
- * @return The numeric representation of the given type.
- */
- #if defined ENTT_PRETTY_FUNCTION
- [[nodiscard]] static constexpr id_type value() noexcept {
- return internal::type_hash<Type>(0);
- #else
- [[nodiscard]] static constexpr id_type value() noexcept {
- return type_index<Type>::value();
- #endif
- }
- /*! @copydoc value */
- [[nodiscard]] constexpr operator id_type() const noexcept {
- return value();
- }
- };
- /**
- * @brief Type name.
- * @tparam Type Type for which to generate a name.
- */
- template<typename Type, typename = void>
- struct type_name final {
- /**
- * @brief Returns the name of a given type.
- * @return The name of the given type.
- */
- [[nodiscard]] static constexpr std::string_view value() noexcept {
- return internal::type_name<Type>(0);
- }
- /*! @copydoc value */
- [[nodiscard]] constexpr operator std::string_view() const noexcept {
- return value();
- }
- };
- /*! @brief Implementation specific information about a type. */
- struct type_info final {
- /**
- * @brief Constructs a type info object for a given type.
- * @tparam Type Type for which to construct a type info object.
- */
- template<typename Type>
- // NOLINTBEGIN(modernize-use-transparent-functors)
- constexpr type_info(std::in_place_type_t<Type>) noexcept
- : seq{type_index<std::remove_const_t<std::remove_reference_t<Type>>>::value()},
- identifier{type_hash<std::remove_const_t<std::remove_reference_t<Type>>>::value()},
- alias{type_name<std::remove_const_t<std::remove_reference_t<Type>>>::value()} {}
- // NOLINTEND(modernize-use-transparent-functors)
- /**
- * @brief Type index.
- * @return Type index.
- */
- [[nodiscard]] constexpr id_type index() const noexcept {
- return seq;
- }
- /**
- * @brief Type hash.
- * @return Type hash.
- */
- [[nodiscard]] constexpr id_type hash() const noexcept {
- return identifier;
- }
- /**
- * @brief Type name.
- * @return Type name.
- */
- [[nodiscard]] constexpr std::string_view name() const noexcept {
- return alias;
- }
- private:
- id_type seq;
- id_type identifier;
- std::string_view alias;
- };
- /**
- * @brief Compares the contents of two type info objects.
- * @param lhs A type info object.
- * @param rhs A type info object.
- * @return True if the two type info objects are identical, false otherwise.
- */
- [[nodiscard]] constexpr bool operator==(const type_info &lhs, const type_info &rhs) noexcept {
- return lhs.hash() == rhs.hash();
- }
- /**
- * @brief Compares the contents of two type info objects.
- * @param lhs A type info object.
- * @param rhs A type info object.
- * @return True if the two type info objects differ, false otherwise.
- */
- [[nodiscard]] constexpr bool operator!=(const type_info &lhs, const type_info &rhs) noexcept {
- return !(lhs == rhs);
- }
- /**
- * @brief Compares two type info objects.
- * @param lhs A valid type info object.
- * @param rhs A valid type info object.
- * @return True if the first element is less than the second, false otherwise.
- */
- [[nodiscard]] constexpr bool operator<(const type_info &lhs, const type_info &rhs) noexcept {
- return lhs.index() < rhs.index();
- }
- /**
- * @brief Compares two type info objects.
- * @param lhs A valid type info object.
- * @param rhs A valid type info object.
- * @return True if the first element is less than or equal to the second, false
- * otherwise.
- */
- [[nodiscard]] constexpr bool operator<=(const type_info &lhs, const type_info &rhs) noexcept {
- return !(rhs < lhs);
- }
- /**
- * @brief Compares two type info objects.
- * @param lhs A valid type info object.
- * @param rhs A valid type info object.
- * @return True if the first element is greater than the second, false
- * otherwise.
- */
- [[nodiscard]] constexpr bool operator>(const type_info &lhs, const type_info &rhs) noexcept {
- return rhs < lhs;
- }
- /**
- * @brief Compares two type info objects.
- * @param lhs A valid type info object.
- * @param rhs A valid type info object.
- * @return True if the first element is greater than or equal to the second,
- * false otherwise.
- */
- [[nodiscard]] constexpr bool operator>=(const type_info &lhs, const type_info &rhs) noexcept {
- return !(lhs < rhs);
- }
- /**
- * @brief Returns the type info object associated to a given type.
- *
- * The returned element refers to an object with static storage duration.<br/>
- * The type doesn't need to be a complete type. If the type is a reference, the
- * result refers to the referenced type. In all cases, top-level cv-qualifiers
- * are ignored.
- *
- * @tparam Type Type for which to generate a type info object.
- * @return A reference to a properly initialized type info object.
- */
- template<typename Type>
- [[nodiscard]] const type_info &type_id() noexcept {
- if constexpr(std::is_same_v<Type, std::remove_const_t<std::remove_reference_t<Type>>>) {
- static const type_info instance{std::in_place_type<Type>};
- return instance;
- } else {
- return type_id<std::remove_const_t<std::remove_reference_t<Type>>>();
- }
- }
- /*! @copydoc type_id */
- template<typename Type>
- // NOLINTNEXTLINE(cppcoreguidelines-missing-std-forward)
- [[nodiscard]] const type_info &type_id(Type &&) noexcept {
- return type_id<std::remove_const_t<std::remove_reference_t<Type>>>();
- }
- } // namespace entt
- #endif
- // #include "../core/utility.hpp"
- #ifndef ENTT_CORE_UTILITY_HPP
- #define ENTT_CORE_UTILITY_HPP
- #include <type_traits>
- #include <utility>
- namespace entt {
- /*! @brief Identity function object (waiting for C++20). */
- struct identity {
- /*! @brief Indicates that this is a transparent function object. */
- using is_transparent = void;
- /**
- * @brief Returns its argument unchanged.
- * @tparam Type Type of the argument.
- * @param value The actual argument.
- * @return The submitted value as-is.
- */
- template<typename Type>
- [[nodiscard]] constexpr Type &&operator()(Type &&value) const noexcept {
- return std::forward<Type>(value);
- }
- };
- /**
- * @brief Constant utility to disambiguate overloaded members of a class.
- * @tparam Type Type of the desired overload.
- * @tparam Class Type of class to which the member belongs.
- * @param member A valid pointer to a member.
- * @return Pointer to the member.
- */
- template<typename Type, typename Class>
- [[nodiscard]] constexpr auto overload(Type Class::*member) noexcept {
- return member;
- }
- /**
- * @brief Constant utility to disambiguate overloaded functions.
- * @tparam Func Function type of the desired overload.
- * @param func A valid pointer to a function.
- * @return Pointer to the function.
- */
- template<typename Func>
- [[nodiscard]] constexpr auto overload(Func *func) noexcept {
- return func;
- }
- /**
- * @brief Helper type for visitors.
- * @tparam Func Types of function objects.
- */
- template<typename... Func>
- struct overloaded: Func... {
- using Func::operator()...;
- };
- /**
- * @brief Deduction guide.
- * @tparam Func Types of function objects.
- */
- template<typename... Func>
- overloaded(Func...) -> overloaded<Func...>;
- /**
- * @brief Basic implementation of a y-combinator.
- * @tparam Func Type of a potentially recursive function.
- */
- template<typename Func>
- struct y_combinator {
- /**
- * @brief Constructs a y-combinator from a given function.
- * @param recursive A potentially recursive function.
- */
- constexpr y_combinator(Func recursive) noexcept(std::is_nothrow_move_constructible_v<Func>)
- : func{std::move(recursive)} {}
- /**
- * @brief Invokes a y-combinator and therefore its underlying function.
- * @tparam Args Types of arguments to use to invoke the underlying function.
- * @param args Parameters to use to invoke the underlying function.
- * @return Return value of the underlying function, if any.
- */
- template<typename... Args>
- constexpr decltype(auto) operator()(Args &&...args) const noexcept(std::is_nothrow_invocable_v<Func, const y_combinator &, Args...>) {
- return func(*this, std::forward<Args>(args)...);
- }
- /*! @copydoc operator()() */
- template<typename... Args>
- constexpr decltype(auto) operator()(Args &&...args) noexcept(std::is_nothrow_invocable_v<Func, y_combinator &, Args...>) {
- return func(*this, std::forward<Args>(args)...);
- }
- private:
- Func func;
- };
- } // namespace entt
- #endif
- // #include "fwd.hpp"
- // #include "sigh.hpp"
- #ifndef ENTT_SIGNAL_SIGH_HPP
- #define ENTT_SIGNAL_SIGH_HPP
- #include <cstddef>
- #include <memory>
- #include <type_traits>
- #include <utility>
- #include <vector>
- // #include "delegate.hpp"
- #ifndef ENTT_SIGNAL_DELEGATE_HPP
- #define ENTT_SIGNAL_DELEGATE_HPP
- #include <cstddef>
- #include <functional>
- #include <tuple>
- #include <type_traits>
- #include <utility>
- // #include "../config/config.h"
- // #include "../core/type_traits.hpp"
- // #include "fwd.hpp"
- namespace entt {
- /*! @cond TURN_OFF_DOXYGEN */
- namespace internal {
- template<typename Ret, typename... Args>
- constexpr auto function_pointer(Ret (*)(Args...)) -> Ret (*)(Args...);
- template<typename Ret, typename Type, typename... Args, typename Other>
- constexpr auto function_pointer(Ret (*)(Type, Args...), Other &&) -> Ret (*)(Args...);
- template<typename Class, typename Ret, typename... Args, typename... Other>
- constexpr auto function_pointer(Ret (Class::*)(Args...), Other &&...) -> Ret (*)(Args...);
- template<typename Class, typename Ret, typename... Args, typename... Other>
- constexpr auto function_pointer(Ret (Class::*)(Args...) const, Other &&...) -> Ret (*)(Args...);
- template<typename Class, typename Type, typename... Other, typename = std::enable_if_t<std::is_member_object_pointer_v<Type Class::*>>>
- constexpr auto function_pointer(Type Class::*, Other &&...) -> Type (*)();
- template<typename... Type>
- using function_pointer_t = decltype(function_pointer(std::declval<Type>()...));
- template<typename... Class, typename Ret, typename... Args>
- [[nodiscard]] constexpr auto index_sequence_for(Ret (*)(Args...)) {
- return std::index_sequence_for<Class..., Args...>{};
- }
- } // namespace internal
- /*! @endcond */
- /**
- * @brief Basic delegate implementation.
- *
- * Primary template isn't defined on purpose. All the specializations give a
- * compile-time error unless the template parameter is a function type.
- */
- template<typename>
- class delegate;
- /**
- * @brief Utility class to use to send around functions and members.
- *
- * Unmanaged delegate for function pointers and members. Users of this class are
- * in charge of disconnecting instances before deleting them.
- *
- * A delegate can be used as a general purpose invoker without memory overhead
- * for free functions possibly with payloads and bound or unbound members.
- *
- * @tparam Ret Return type of a function type.
- * @tparam Args Types of arguments of a function type.
- */
- template<typename Ret, typename... Args>
- class delegate<Ret(Args...)> {
- using return_type = std::remove_const_t<Ret>;
- using delegate_type = return_type(const void *, Args...);
- template<auto Candidate, std::size_t... Index>
- [[nodiscard]] auto wrap(std::index_sequence<Index...>) noexcept {
- return [](const void *, Args... args) -> return_type {
- [[maybe_unused]] const auto arguments = std::forward_as_tuple(std::forward<Args>(args)...);
- [[maybe_unused]] constexpr auto offset = !std::is_invocable_r_v<Ret, decltype(Candidate), type_list_element_t<Index, type_list<Args...>>...> * (sizeof...(Args) - sizeof...(Index));
- return static_cast<Ret>(std::invoke(Candidate, std::forward<type_list_element_t<Index + offset, type_list<Args...>>>(std::get<Index + offset>(arguments))...));
- };
- }
- template<auto Candidate, typename Type, std::size_t... Index>
- [[nodiscard]] auto wrap(Type &, std::index_sequence<Index...>) noexcept {
- return [](const void *payload, Args... args) -> return_type {
- Type *curr = static_cast<Type *>(const_cast<constness_as_t<void, Type> *>(payload));
- [[maybe_unused]] const auto arguments = std::forward_as_tuple(std::forward<Args>(args)...);
- [[maybe_unused]] constexpr auto offset = !std::is_invocable_r_v<Ret, decltype(Candidate), Type &, type_list_element_t<Index, type_list<Args...>>...> * (sizeof...(Args) - sizeof...(Index));
- return static_cast<Ret>(std::invoke(Candidate, *curr, std::forward<type_list_element_t<Index + offset, type_list<Args...>>>(std::get<Index + offset>(arguments))...));
- };
- }
- template<auto Candidate, typename Type, std::size_t... Index>
- [[nodiscard]] auto wrap(Type *, std::index_sequence<Index...>) noexcept {
- return [](const void *payload, Args... args) -> return_type {
- Type *curr = static_cast<Type *>(const_cast<constness_as_t<void, Type> *>(payload));
- [[maybe_unused]] const auto arguments = std::forward_as_tuple(std::forward<Args>(args)...);
- [[maybe_unused]] constexpr auto offset = !std::is_invocable_r_v<Ret, decltype(Candidate), Type *, type_list_element_t<Index, type_list<Args...>>...> * (sizeof...(Args) - sizeof...(Index));
- return static_cast<Ret>(std::invoke(Candidate, curr, std::forward<type_list_element_t<Index + offset, type_list<Args...>>>(std::get<Index + offset>(arguments))...));
- };
- }
- public:
- /*! @brief Function type of the contained target. */
- using function_type = Ret(const void *, Args...);
- /*! @brief Function type of the delegate. */
- using type = Ret(Args...);
- /*! @brief Return type of the delegate. */
- using result_type = Ret;
- /*! @brief Default constructor. */
- delegate() noexcept = default;
- /**
- * @brief Constructs a delegate with a given object or payload, if any.
- * @tparam Candidate Function or member to connect to the delegate.
- * @tparam Type Type of class or type of payload, if any.
- * @param value_or_instance Optional valid object that fits the purpose.
- */
- template<auto Candidate, typename... Type>
- delegate(connect_arg_t<Candidate>, Type &&...value_or_instance) noexcept {
- connect<Candidate>(std::forward<Type>(value_or_instance)...);
- }
- /**
- * @brief Constructs a delegate and connects an user defined function with
- * optional payload.
- * @param function Function to connect to the delegate.
- * @param payload User defined arbitrary data.
- */
- delegate(function_type *function, const void *payload = nullptr) noexcept {
- connect(function, payload);
- }
- /**
- * @brief Connects a free function or an unbound member to a delegate.
- * @tparam Candidate Function or member to connect to the delegate.
- */
- template<auto Candidate>
- void connect() noexcept {
- instance = nullptr;
- if constexpr(std::is_invocable_r_v<Ret, decltype(Candidate), Args...>) {
- fn = [](const void *, Args... args) -> return_type {
- return Ret(std::invoke(Candidate, std::forward<Args>(args)...));
- };
- } else if constexpr(std::is_member_pointer_v<decltype(Candidate)>) {
- fn = wrap<Candidate>(internal::index_sequence_for<type_list_element_t<0, type_list<Args...>>>(internal::function_pointer_t<decltype(Candidate)>{}));
- } else {
- fn = wrap<Candidate>(internal::index_sequence_for(internal::function_pointer_t<decltype(Candidate)>{}));
- }
- }
- /**
- * @brief Connects a free function with payload or a bound member to a
- * delegate.
- *
- * The delegate isn't responsible for the connected object or the payload.
- * Users must always guarantee that the lifetime of the instance overcomes
- * the one of the delegate.<br/>
- * When used to connect a free function with payload, its signature must be
- * such that the instance is the first argument before the ones used to
- * define the delegate itself.
- *
- * @tparam Candidate Function or member to connect to the delegate.
- * @tparam Type Type of class or type of payload.
- * @param value_or_instance A valid reference that fits the purpose.
- */
- template<auto Candidate, typename Type>
- void connect(Type &value_or_instance) noexcept {
- instance = &value_or_instance;
- if constexpr(std::is_invocable_r_v<Ret, decltype(Candidate), Type &, Args...>) {
- fn = [](const void *payload, Args... args) -> return_type {
- Type *curr = static_cast<Type *>(const_cast<constness_as_t<void, Type> *>(payload));
- return Ret(std::invoke(Candidate, *curr, std::forward<Args>(args)...));
- };
- } else {
- fn = wrap<Candidate>(value_or_instance, internal::index_sequence_for(internal::function_pointer_t<decltype(Candidate), Type>{}));
- }
- }
- /**
- * @brief Connects a free function with payload or a bound member to a
- * delegate.
- *
- * @sa connect(Type &)
- *
- * @tparam Candidate Function or member to connect to the delegate.
- * @tparam Type Type of class or type of payload.
- * @param value_or_instance A valid pointer that fits the purpose.
- */
- template<auto Candidate, typename Type>
- void connect(Type *value_or_instance) noexcept {
- instance = value_or_instance;
- if constexpr(std::is_invocable_r_v<Ret, decltype(Candidate), Type *, Args...>) {
- fn = [](const void *payload, Args... args) -> return_type {
- Type *curr = static_cast<Type *>(const_cast<constness_as_t<void, Type> *>(payload));
- return Ret(std::invoke(Candidate, curr, std::forward<Args>(args)...));
- };
- } else {
- fn = wrap<Candidate>(value_or_instance, internal::index_sequence_for(internal::function_pointer_t<decltype(Candidate), Type>{}));
- }
- }
- /**
- * @brief Connects an user defined function with optional payload to a
- * delegate.
- *
- * The delegate isn't responsible for the connected object or the payload.
- * Users must always guarantee that the lifetime of an instance overcomes
- * the one of the delegate.<br/>
- * The payload is returned as the first argument to the target function in
- * all cases.
- *
- * @param function Function to connect to the delegate.
- * @param payload User defined arbitrary data.
- */
- void connect(function_type *function, const void *payload = nullptr) noexcept {
- ENTT_ASSERT(function != nullptr, "Uninitialized function pointer");
- instance = payload;
- fn = function;
- }
- /**
- * @brief Resets a delegate.
- *
- * After a reset, a delegate cannot be invoked anymore.
- */
- void reset() noexcept {
- instance = nullptr;
- fn = nullptr;
- }
- /**
- * @brief Returns a pointer to the stored callable function target, if any.
- * @return An opaque pointer to the stored callable function target.
- */
- [[nodiscard]] function_type *target() const noexcept {
- return fn;
- }
- /**
- * @brief Returns the instance or the payload linked to a delegate, if any.
- * @return An opaque pointer to the underlying data.
- */
- [[nodiscard]] const void *data() const noexcept {
- return instance;
- }
- /**
- * @brief Triggers a delegate.
- *
- * The delegate invokes the underlying function and returns the result.
- *
- * @warning
- * Attempting to trigger an invalid delegate results in undefined
- * behavior.
- *
- * @param args Arguments to use to invoke the underlying function.
- * @return The value returned by the underlying function.
- */
- Ret operator()(Args... args) const {
- ENTT_ASSERT(static_cast<bool>(*this), "Uninitialized delegate");
- return fn(instance, std::forward<Args>(args)...);
- }
- /**
- * @brief Checks whether a delegate actually stores a listener.
- * @return False if the delegate is empty, true otherwise.
- */
- [[nodiscard]] explicit operator bool() const noexcept {
- // no need to also test instance
- return !(fn == nullptr);
- }
- /**
- * @brief Compares the contents of two delegates.
- * @param other Delegate with which to compare.
- * @return False if the two contents differ, true otherwise.
- */
- [[nodiscard]] bool operator==(const delegate<Ret(Args...)> &other) const noexcept {
- return fn == other.fn && instance == other.instance;
- }
- private:
- const void *instance{};
- delegate_type *fn{};
- };
- /**
- * @brief Compares the contents of two delegates.
- * @tparam Ret Return type of a function type.
- * @tparam Args Types of arguments of a function type.
- * @param lhs A valid delegate object.
- * @param rhs A valid delegate object.
- * @return True if the two contents differ, false otherwise.
- */
- template<typename Ret, typename... Args>
- [[nodiscard]] bool operator!=(const delegate<Ret(Args...)> &lhs, const delegate<Ret(Args...)> &rhs) noexcept {
- return !(lhs == rhs);
- }
- /**
- * @brief Deduction guide.
- * @tparam Candidate Function or member to connect to the delegate.
- */
- template<auto Candidate>
- delegate(connect_arg_t<Candidate>) -> delegate<std::remove_pointer_t<internal::function_pointer_t<decltype(Candidate)>>>;
- /**
- * @brief Deduction guide.
- * @tparam Candidate Function or member to connect to the delegate.
- * @tparam Type Type of class or type of payload.
- */
- template<auto Candidate, typename Type>
- delegate(connect_arg_t<Candidate>, Type &&) -> delegate<std::remove_pointer_t<internal::function_pointer_t<decltype(Candidate), Type>>>;
- /**
- * @brief Deduction guide.
- * @tparam Ret Return type of a function type.
- * @tparam Args Types of arguments of a function type.
- */
- template<typename Ret, typename... Args>
- delegate(Ret (*)(const void *, Args...), const void * = nullptr) -> delegate<Ret(Args...)>;
- } // namespace entt
- #endif
- // #include "fwd.hpp"
- namespace entt {
- /**
- * @brief Sink class.
- *
- * Primary template isn't defined on purpose. All the specializations give a
- * compile-time error unless the template parameter is a function type.
- *
- * @tparam Type A valid signal handler type.
- */
- template<typename Type>
- class sink;
- /**
- * @brief Unmanaged signal handler.
- *
- * Primary template isn't defined on purpose. All the specializations give a
- * compile-time error unless the template parameter is a function type.
- *
- * @tparam Type A valid function type.
- * @tparam Allocator Type of allocator used to manage memory and elements.
- */
- template<typename Type, typename Allocator>
- class sigh;
- /**
- * @brief Unmanaged signal handler.
- *
- * It works directly with references to classes and pointers to member functions
- * as well as pointers to free functions. Users of this class are in charge of
- * disconnecting instances before deleting them.
- *
- * This class serves mainly two purposes:
- *
- * * Creating signals to use later to notify a bunch of listeners.
- * * Collecting results from a set of functions like in a voting system.
- *
- * @tparam Ret Return type of a function type.
- * @tparam Args Types of arguments of a function type.
- * @tparam Allocator Type of allocator used to manage memory and elements.
- */
- template<typename Ret, typename... Args, typename Allocator>
- class sigh<Ret(Args...), Allocator> {
- friend class sink<sigh<Ret(Args...), Allocator>>;
- using alloc_traits = std::allocator_traits<Allocator>;
- using delegate_type = delegate<Ret(Args...)>;
- using container_type = std::vector<delegate_type, typename alloc_traits::template rebind_alloc<delegate_type>>;
- public:
- /*! @brief Allocator type. */
- using allocator_type = Allocator;
- /*! @brief Unsigned integer type. */
- using size_type = std::size_t;
- /*! @brief Sink type. */
- using sink_type = sink<sigh<Ret(Args...), Allocator>>;
- /*! @brief Default constructor. */
- sigh() noexcept(noexcept(allocator_type{}))
- : sigh{allocator_type{}} {}
- /**
- * @brief Constructs a signal handler with a given allocator.
- * @param allocator The allocator to use.
- */
- explicit sigh(const allocator_type &allocator) noexcept
- : calls{allocator} {}
- /**
- * @brief Copy constructor.
- * @param other The instance to copy from.
- */
- sigh(const sigh &other)
- : calls{other.calls} {}
- /**
- * @brief Allocator-extended copy constructor.
- * @param other The instance to copy from.
- * @param allocator The allocator to use.
- */
- sigh(const sigh &other, const allocator_type &allocator)
- : calls{other.calls, allocator} {}
- /**
- * @brief Move constructor.
- * @param other The instance to move from.
- */
- sigh(sigh &&other) noexcept
- : calls{std::move(other.calls)} {}
- /**
- * @brief Allocator-extended move constructor.
- * @param other The instance to move from.
- * @param allocator The allocator to use.
- */
- sigh(sigh &&other, const allocator_type &allocator)
- : calls{std::move(other.calls), allocator} {}
- /*! @brief Default destructor. */
- ~sigh() = default;
- /**
- * @brief Copy assignment operator.
- * @param other The instance to copy from.
- * @return This signal handler.
- */
- sigh &operator=(const sigh &other) {
- calls = other.calls;
- return *this;
- }
- /**
- * @brief Move assignment operator.
- * @param other The instance to move from.
- * @return This signal handler.
- */
- sigh &operator=(sigh &&other) noexcept {
- swap(other);
- return *this;
- }
- /**
- * @brief Exchanges the contents with those of a given signal handler.
- * @param other Signal handler to exchange the content with.
- */
- void swap(sigh &other) noexcept {
- using std::swap;
- swap(calls, other.calls);
- }
- /**
- * @brief Returns the associated allocator.
- * @return The associated allocator.
- */
- [[nodiscard]] constexpr allocator_type get_allocator() const noexcept {
- return calls.get_allocator();
- }
- /**
- * @brief Number of listeners connected to the signal.
- * @return Number of listeners currently connected.
- */
- [[nodiscard]] size_type size() const noexcept {
- return calls.size();
- }
- /**
- * @brief Returns false if at least a listener is connected to the signal.
- * @return True if the signal has no listeners connected, false otherwise.
- */
- [[nodiscard]] bool empty() const noexcept {
- return calls.empty();
- }
- /**
- * @brief Triggers a signal.
- *
- * All the listeners are notified. Order isn't guaranteed.
- *
- * @param args Arguments to use to invoke listeners.
- */
- void publish(Args... args) const {
- for(auto pos = calls.size(); pos; --pos) {
- calls[pos - 1u](args...);
- }
- }
- /**
- * @brief Collects return values from the listeners.
- *
- * The collector must expose a call operator with the following properties:
- *
- * * The return type is either `void` or such that it's convertible to
- * `bool`. In the second case, a true value will stop the iteration.
- * * The list of parameters is empty if `Ret` is `void`, otherwise it
- * contains a single element such that `Ret` is convertible to it.
- *
- * @tparam Func Type of collector to use, if any.
- * @param func A valid function object.
- * @param args Arguments to use to invoke listeners.
- */
- template<typename Func>
- void collect(Func func, Args... args) const {
- for(auto pos = calls.size(); pos; --pos) {
- if constexpr(std::is_void_v<Ret> || !std::is_invocable_v<Func, Ret>) {
- calls[pos - 1u](args...);
- if constexpr(std::is_invocable_r_v<bool, Func>) {
- if(func()) {
- break;
- }
- } else {
- func();
- }
- } else {
- if constexpr(std::is_invocable_r_v<bool, Func, Ret>) {
- if(func(calls[pos - 1u](args...))) {
- break;
- }
- } else {
- func(calls[pos - 1u](args...));
- }
- }
- }
- }
- private:
- container_type calls;
- };
- /**
- * @brief Connection class.
- *
- * Opaque object the aim of which is to allow users to release an already
- * estabilished connection without having to keep a reference to the signal or
- * the sink that generated it.
- */
- class connection {
- template<typename>
- friend class sink;
- connection(delegate<void(void *)> fn, void *ref)
- : disconnect{fn}, signal{ref} {}
- public:
- /*! @brief Default constructor. */
- connection()
- : signal{} {}
- /**
- * @brief Checks whether a connection is properly initialized.
- * @return True if the connection is properly initialized, false otherwise.
- */
- [[nodiscard]] explicit operator bool() const noexcept {
- return static_cast<bool>(disconnect);
- }
- /*! @brief Breaks the connection. */
- void release() {
- if(disconnect) {
- disconnect(signal);
- disconnect.reset();
- }
- }
- private:
- delegate<void(void *)> disconnect;
- void *signal;
- };
- /**
- * @brief Scoped connection class.
- *
- * Opaque object the aim of which is to allow users to release an already
- * estabilished connection without having to keep a reference to the signal or
- * the sink that generated it.<br/>
- * A scoped connection automatically breaks the link between the two objects
- * when it goes out of scope.
- */
- struct scoped_connection {
- /*! @brief Default constructor. */
- scoped_connection() = default;
- /**
- * @brief Constructs a scoped connection from a basic connection.
- * @param other A valid connection object.
- */
- scoped_connection(const connection &other)
- : conn{other} {}
- /*! @brief Default copy constructor, deleted on purpose. */
- scoped_connection(const scoped_connection &) = delete;
- /**
- * @brief Move constructor.
- * @param other The scoped connection to move from.
- */
- scoped_connection(scoped_connection &&other) noexcept
- : conn{std::exchange(other.conn, {})} {}
- /*! @brief Automatically breaks the link on destruction. */
- ~scoped_connection() {
- conn.release();
- }
- /**
- * @brief Default copy assignment operator, deleted on purpose.
- * @return This scoped connection.
- */
- scoped_connection &operator=(const scoped_connection &) = delete;
- /**
- * @brief Move assignment operator.
- * @param other The scoped connection to move from.
- * @return This scoped connection.
- */
- scoped_connection &operator=(scoped_connection &&other) noexcept {
- conn = std::exchange(other.conn, {});
- return *this;
- }
- /**
- * @brief Acquires a connection.
- * @param other The connection object to acquire.
- * @return This scoped connection.
- */
- scoped_connection &operator=(connection other) {
- conn = other;
- return *this;
- }
- /**
- * @brief Checks whether a scoped connection is properly initialized.
- * @return True if the connection is properly initialized, false otherwise.
- */
- [[nodiscard]] explicit operator bool() const noexcept {
- return static_cast<bool>(conn);
- }
- /*! @brief Breaks the connection. */
- void release() {
- conn.release();
- }
- private:
- connection conn;
- };
- /**
- * @brief Sink class.
- *
- * A sink is used to connect listeners to signals and to disconnect them.<br/>
- * The function type for a listener is the one of the signal to which it
- * belongs.
- *
- * The clear separation between a signal and a sink permits to store the former
- * as private data member without exposing the publish functionality to the
- * users of the class.
- *
- * @warning
- * Lifetime of a sink must not overcome that of the signal to which it refers.
- * In any other case, attempting to use a sink results in undefined behavior.
- *
- * @tparam Ret Return type of a function type.
- * @tparam Args Types of arguments of a function type.
- * @tparam Allocator Type of allocator used to manage memory and elements.
- */
- template<typename Ret, typename... Args, typename Allocator>
- class sink<sigh<Ret(Args...), Allocator>> {
- using signal_type = sigh<Ret(Args...), Allocator>;
- using delegate_type = typename signal_type::delegate_type;
- using difference_type = typename signal_type::container_type::difference_type;
- template<auto Candidate, typename Type>
- static void release(Type value_or_instance, void *signal) {
- sink{*static_cast<signal_type *>(signal)}.disconnect<Candidate>(value_or_instance);
- }
- template<auto Candidate>
- static void release(void *signal) {
- sink{*static_cast<signal_type *>(signal)}.disconnect<Candidate>();
- }
- template<typename Func>
- void disconnect_if(Func callback) {
- auto &ref = signal_or_assert();
- for(auto pos = ref.calls.size(); pos; --pos) {
- if(auto &elem = ref.calls[pos - 1u]; callback(elem)) {
- elem = std::move(ref.calls.back());
- ref.calls.pop_back();
- }
- }
- }
- [[nodiscard]] auto &signal_or_assert() const noexcept {
- ENTT_ASSERT(signal != nullptr, "Invalid pointer to signal");
- return *signal;
- }
- public:
- /*! @brief Constructs an invalid sink. */
- sink() noexcept
- : signal{} {}
- /**
- * @brief Constructs a sink that is allowed to modify a given signal.
- * @param ref A valid reference to a signal object.
- */
- sink(sigh<Ret(Args...), Allocator> &ref) noexcept
- : signal{&ref} {}
- /**
- * @brief Returns false if at least a listener is connected to the sink.
- * @return True if the sink has no listeners connected, false otherwise.
- */
- [[nodiscard]] bool empty() const noexcept {
- return signal_or_assert().calls.empty();
- }
- /**
- * @brief Connects a free function or an unbound member to a signal.
- * @tparam Candidate Function or member to connect to the signal.
- * @return A properly initialized connection object.
- */
- template<auto Candidate>
- connection connect() {
- disconnect<Candidate>();
- delegate_type call{};
- call.template connect<Candidate>();
- signal_or_assert().calls.push_back(std::move(call));
- delegate<void(void *)> conn{};
- conn.template connect<&release<Candidate>>();
- return {conn, signal};
- }
- /**
- * @brief Connects a free function with payload or a bound member to a
- * signal.
- *
- * The signal isn't responsible for the connected object or the payload.
- * Users must always guarantee that the lifetime of the instance overcomes
- * the one of the signal.<br/>
- * When used to connect a free function with payload, its signature must be
- * such that the instance is the first argument before the ones used to
- * define the signal itself.
- *
- * @tparam Candidate Function or member to connect to the signal.
- * @tparam Type Type of class or type of payload.
- * @param value_or_instance A valid reference that fits the purpose.
- * @return A properly initialized connection object.
- */
- template<auto Candidate, typename Type>
- connection connect(Type &value_or_instance) {
- disconnect<Candidate>(value_or_instance);
- delegate_type call{};
- call.template connect<Candidate>(value_or_instance);
- signal_or_assert().calls.push_back(std::move(call));
- delegate<void(void *)> conn{};
- conn.template connect<&release<Candidate, Type &>>(value_or_instance);
- return {conn, signal};
- }
- /**
- * @brief Connects a free function with payload or a bound member to a
- * signal.
- *
- * @sa connect(Type &)
- *
- * @tparam Candidate Function or member to connect to the signal.
- * @tparam Type Type of class or type of payload.
- * @param value_or_instance A valid pointer that fits the purpose.
- * @return A properly initialized connection object.
- */
- template<auto Candidate, typename Type>
- connection connect(Type *value_or_instance) {
- disconnect<Candidate>(value_or_instance);
- delegate_type call{};
- call.template connect<Candidate>(value_or_instance);
- signal_or_assert().calls.push_back(std::move(call));
- delegate<void(void *)> conn{};
- conn.template connect<&release<Candidate, Type *>>(value_or_instance);
- return {conn, signal};
- }
- /**
- * @brief Disconnects a free function or an unbound member from a signal.
- * @tparam Candidate Function or member to disconnect from the signal.
- */
- template<auto Candidate>
- void disconnect() {
- delegate_type call{};
- call.template connect<Candidate>();
- disconnect_if([&call](const auto &elem) { return elem == call; });
- }
- /**
- * @brief Disconnects a free function with payload or a bound member from a
- * signal.
- *
- * The signal isn't responsible for the connected object or the payload.
- * Users must always guarantee that the lifetime of the instance overcomes
- * the one of the signal.<br/>
- * When used to connect a free function with payload, its signature must be
- * such that the instance is the first argument before the ones used to
- * define the signal itself.
- *
- * @tparam Candidate Function or member to disconnect from the signal.
- * @tparam Type Type of class or type of payload, if any.
- * @param value_or_instance A valid reference that fits the purpose.
- */
- template<auto Candidate, typename Type>
- void disconnect(Type &value_or_instance) {
- delegate_type call{};
- call.template connect<Candidate>(value_or_instance);
- disconnect_if([&call](const auto &elem) { return elem == call; });
- }
- /**
- * @brief Disconnects a free function with payload or a bound member from a
- * signal.
- *
- * @sa disconnect(Type &)
- *
- * @tparam Candidate Function or member to disconnect from the signal.
- * @tparam Type Type of class or type of payload, if any.
- * @param value_or_instance A valid pointer that fits the purpose.
- */
- template<auto Candidate, typename Type>
- void disconnect(Type *value_or_instance) {
- delegate_type call{};
- call.template connect<Candidate>(value_or_instance);
- disconnect_if([&call](const auto &elem) { return elem == call; });
- }
- /**
- * @brief Disconnects free functions with payload or bound members from a
- * signal.
- * @param value_or_instance A valid object that fits the purpose.
- */
- void disconnect(const void *value_or_instance) {
- ENTT_ASSERT(value_or_instance != nullptr, "Invalid value or instance");
- disconnect_if([value_or_instance](const auto &elem) { return elem.data() == value_or_instance; });
- }
- /*! @brief Disconnects all the listeners from a signal. */
- void disconnect() {
- signal_or_assert().calls.clear();
- }
- /**
- * @brief Returns true if a sink is correctly initialized, false otherwise.
- * @return True if a sink is correctly initialized, false otherwise.
- */
- [[nodiscard]] explicit operator bool() const noexcept {
- return signal != nullptr;
- }
- private:
- signal_type *signal;
- };
- /**
- * @brief Deduction guide.
- *
- * It allows to deduce the signal handler type of a sink directly from the
- * signal it refers to.
- *
- * @tparam Ret Return type of a function type.
- * @tparam Args Types of arguments of a function type.
- * @tparam Allocator Type of allocator used to manage memory and elements.
- */
- template<typename Ret, typename... Args, typename Allocator>
- sink(sigh<Ret(Args...), Allocator> &) -> sink<sigh<Ret(Args...), Allocator>>;
- } // namespace entt
- #endif
- namespace entt {
- /*! @cond TURN_OFF_DOXYGEN */
- namespace internal {
- struct basic_dispatcher_handler {
- virtual ~basic_dispatcher_handler() = default;
- virtual void publish() = 0;
- virtual void disconnect(void *) = 0;
- virtual void clear() noexcept = 0;
- [[nodiscard]] virtual std::size_t size() const noexcept = 0;
- };
- template<typename Type, typename Allocator>
- class dispatcher_handler final: public basic_dispatcher_handler {
- static_assert(std::is_same_v<Type, std::decay_t<Type>>, "Invalid type");
- using alloc_traits = std::allocator_traits<Allocator>;
- using signal_type = sigh<void(Type &), Allocator>;
- using container_type = std::vector<Type, typename alloc_traits::template rebind_alloc<Type>>;
- public:
- using allocator_type = Allocator;
- dispatcher_handler(const allocator_type &allocator)
- : signal{allocator},
- events{allocator} {}
- void publish() override {
- const auto length = events.size();
- for(std::size_t pos{}; pos < length; ++pos) {
- signal.publish(events[pos]);
- }
- events.erase(events.cbegin(), events.cbegin() + static_cast<typename container_type::difference_type>(length));
- }
- void disconnect(void *instance) override {
- bucket().disconnect(instance);
- }
- void clear() noexcept override {
- events.clear();
- }
- [[nodiscard]] auto bucket() noexcept {
- return typename signal_type::sink_type{signal};
- }
- void trigger(Type event) {
- signal.publish(event);
- }
- template<typename... Args>
- void enqueue(Args &&...args) {
- if constexpr(std::is_aggregate_v<Type> && (sizeof...(Args) != 0u || !std::is_default_constructible_v<Type>)) {
- events.push_back(Type{std::forward<Args>(args)...});
- } else {
- events.emplace_back(std::forward<Args>(args)...);
- }
- }
- [[nodiscard]] std::size_t size() const noexcept override {
- return events.size();
- }
- private:
- signal_type signal;
- container_type events;
- };
- } // namespace internal
- /*! @endcond */
- /**
- * @brief Basic dispatcher implementation.
- *
- * A dispatcher can be used either to trigger an immediate event or to enqueue
- * events to be published all together once per tick.<br/>
- * Listeners are provided in the form of member functions. For each event of
- * type `Type`, listeners are such that they can be invoked with an argument of
- * type `Type &`, no matter what the return type is.
- *
- * The dispatcher creates instances of the `sigh` class internally. Refer to the
- * documentation of the latter for more details.
- *
- * @tparam Allocator Type of allocator used to manage memory and elements.
- */
- template<typename Allocator>
- class basic_dispatcher {
- template<typename Type>
- using handler_type = internal::dispatcher_handler<Type, Allocator>;
- using key_type = id_type;
- // std::shared_ptr because of its type erased allocator which is useful here
- using mapped_type = std::shared_ptr<internal::basic_dispatcher_handler>;
- using alloc_traits = std::allocator_traits<Allocator>;
- using container_allocator = typename alloc_traits::template rebind_alloc<std::pair<const key_type, mapped_type>>;
- using container_type = dense_map<key_type, mapped_type, identity, std::equal_to<>, container_allocator>;
- template<typename Type>
- [[nodiscard]] handler_type<Type> &assure(const id_type id) {
- static_assert(std::is_same_v<Type, std::decay_t<Type>>, "Non-decayed types not allowed");
- auto &&ptr = pools.first()[id];
- if(!ptr) {
- const auto &allocator = get_allocator();
- ptr = std::allocate_shared<handler_type<Type>>(allocator, allocator);
- }
- return static_cast<handler_type<Type> &>(*ptr);
- }
- template<typename Type>
- [[nodiscard]] const handler_type<Type> *assure(const id_type id) const {
- static_assert(std::is_same_v<Type, std::decay_t<Type>>, "Non-decayed types not allowed");
- if(auto it = pools.first().find(id); it != pools.first().cend()) {
- return static_cast<const handler_type<Type> *>(it->second.get());
- }
- return nullptr;
- }
- public:
- /*! @brief Allocator type. */
- using allocator_type = Allocator;
- /*! @brief Unsigned integer type. */
- using size_type = std::size_t;
- /*! @brief Default constructor. */
- basic_dispatcher()
- : basic_dispatcher{allocator_type{}} {}
- /**
- * @brief Constructs a dispatcher with a given allocator.
- * @param allocator The allocator to use.
- */
- explicit basic_dispatcher(const allocator_type &allocator)
- : pools{allocator, allocator} {}
- /*! @brief Default copy constructor, deleted on purpose. */
- basic_dispatcher(const basic_dispatcher &) = delete;
- /**
- * @brief Move constructor.
- * @param other The instance to move from.
- */
- basic_dispatcher(basic_dispatcher &&other) noexcept
- : pools{std::move(other.pools)} {}
- /**
- * @brief Allocator-extended move constructor.
- * @param other The instance to move from.
- * @param allocator The allocator to use.
- */
- basic_dispatcher(basic_dispatcher &&other, const allocator_type &allocator)
- : pools{container_type{std::move(other.pools.first()), allocator}, allocator} {
- ENTT_ASSERT(alloc_traits::is_always_equal::value || get_allocator() == other.get_allocator(), "Copying a dispatcher is not allowed");
- }
- /*! @brief Default destructor. */
- ~basic_dispatcher() = default;
- /**
- * @brief Default copy assignment operator, deleted on purpose.
- * @return This dispatcher.
- */
- basic_dispatcher &operator=(const basic_dispatcher &) = delete;
- /**
- * @brief Move assignment operator.
- * @param other The instance to move from.
- * @return This dispatcher.
- */
- basic_dispatcher &operator=(basic_dispatcher &&other) noexcept {
- ENTT_ASSERT(alloc_traits::is_always_equal::value || get_allocator() == other.get_allocator(), "Copying a dispatcher is not allowed");
- swap(other);
- return *this;
- }
- /**
- * @brief Exchanges the contents with those of a given dispatcher.
- * @param other Dispatcher to exchange the content with.
- */
- void swap(basic_dispatcher &other) noexcept {
- using std::swap;
- swap(pools, other.pools);
- }
- /**
- * @brief Returns the associated allocator.
- * @return The associated allocator.
- */
- [[nodiscard]] constexpr allocator_type get_allocator() const noexcept {
- return pools.second();
- }
- /**
- * @brief Returns the number of pending events for a given type.
- * @tparam Type Type of event for which to return the count.
- * @param id Name used to map the event queue within the dispatcher.
- * @return The number of pending events for the given type.
- */
- template<typename Type>
- [[nodiscard]] size_type size(const id_type id = type_hash<Type>::value()) const noexcept {
- const auto *cpool = assure<std::decay_t<Type>>(id);
- return cpool ? cpool->size() : 0u;
- }
- /**
- * @brief Returns the total number of pending events.
- * @return The total number of pending events.
- */
- [[nodiscard]] size_type size() const noexcept {
- size_type count{};
- for(auto &&cpool: pools.first()) {
- count += cpool.second->size();
- }
- return count;
- }
- /**
- * @brief Returns a sink object for the given event and queue.
- *
- * A sink is an opaque object used to connect listeners to events.
- *
- * The function type for a listener is _compatible_ with:
- *
- * @code{.cpp}
- * void(Type &);
- * @endcode
- *
- * The order of invocation of the listeners isn't guaranteed.
- *
- * @sa sink
- *
- * @tparam Type Type of event of which to get the sink.
- * @param id Name used to map the event queue within the dispatcher.
- * @return A temporary sink object.
- */
- template<typename Type>
- [[nodiscard]] auto sink(const id_type id = type_hash<Type>::value()) {
- return assure<Type>(id).bucket();
- }
- /**
- * @brief Triggers an immediate event of a given type.
- * @tparam Type Type of event to trigger.
- * @param value An instance of the given type of event.
- */
- template<typename Type>
- void trigger(Type &&value = {}) {
- trigger(type_hash<std::decay_t<Type>>::value(), std::forward<Type>(value));
- }
- /**
- * @brief Triggers an immediate event on a queue of a given type.
- * @tparam Type Type of event to trigger.
- * @param value An instance of the given type of event.
- * @param id Name used to map the event queue within the dispatcher.
- */
- template<typename Type>
- void trigger(const id_type id, Type &&value = {}) {
- assure<std::decay_t<Type>>(id).trigger(std::forward<Type>(value));
- }
- /**
- * @brief Enqueues an event of the given type.
- * @tparam Type Type of event to enqueue.
- * @tparam Args Types of arguments to use to construct the event.
- * @param args Arguments to use to construct the event.
- */
- template<typename Type, typename... Args>
- void enqueue(Args &&...args) {
- enqueue_hint<Type>(type_hash<Type>::value(), std::forward<Args>(args)...);
- }
- /**
- * @brief Enqueues an event of the given type.
- * @tparam Type Type of event to enqueue.
- * @param value An instance of the given type of event.
- */
- template<typename Type>
- void enqueue(Type &&value) {
- enqueue_hint(type_hash<std::decay_t<Type>>::value(), std::forward<Type>(value));
- }
- /**
- * @brief Enqueues an event of the given type.
- * @tparam Type Type of event to enqueue.
- * @tparam Args Types of arguments to use to construct the event.
- * @param id Name used to map the event queue within the dispatcher.
- * @param args Arguments to use to construct the event.
- */
- template<typename Type, typename... Args>
- void enqueue_hint(const id_type id, Args &&...args) {
- assure<Type>(id).enqueue(std::forward<Args>(args)...);
- }
- /**
- * @brief Enqueues an event of the given type.
- * @tparam Type Type of event to enqueue.
- * @param id Name used to map the event queue within the dispatcher.
- * @param value An instance of the given type of event.
- */
- template<typename Type>
- void enqueue_hint(const id_type id, Type &&value) {
- assure<std::decay_t<Type>>(id).enqueue(std::forward<Type>(value));
- }
- /**
- * @brief Utility function to disconnect everything related to a given value
- * or instance from a dispatcher.
- * @tparam Type Type of class or type of payload.
- * @param value_or_instance A valid object that fits the purpose.
- */
- template<typename Type>
- void disconnect(Type &value_or_instance) {
- disconnect(&value_or_instance);
- }
- /**
- * @brief Utility function to disconnect everything related to a given value
- * or instance from a dispatcher.
- * @tparam Type Type of class or type of payload.
- * @param value_or_instance A valid object that fits the purpose.
- */
- template<typename Type>
- void disconnect(Type *value_or_instance) {
- for(auto &&cpool: pools.first()) {
- cpool.second->disconnect(value_or_instance);
- }
- }
- /**
- * @brief Discards all the events stored so far in a given queue.
- * @tparam Type Type of event to discard.
- * @param id Name used to map the event queue within the dispatcher.
- */
- template<typename Type>
- void clear(const id_type id = type_hash<Type>::value()) {
- assure<Type>(id).clear();
- }
- /*! @brief Discards all the events queued so far. */
- void clear() noexcept {
- for(auto &&cpool: pools.first()) {
- cpool.second->clear();
- }
- }
- /**
- * @brief Delivers all the pending events of a given queue.
- * @tparam Type Type of event to send.
- * @param id Name used to map the event queue within the dispatcher.
- */
- template<typename Type>
- void update(const id_type id = type_hash<Type>::value()) {
- assure<Type>(id).publish();
- }
- /*! @brief Delivers all the pending events. */
- void update() const {
- for(auto &&cpool: pools.first()) {
- cpool.second->publish();
- }
- }
- private:
- compressed_pair<container_type, allocator_type> pools;
- };
- } // namespace entt
- #endif
- // #include "signal/emitter.hpp"
- #ifndef ENTT_SIGNAL_EMITTER_HPP
- #define ENTT_SIGNAL_EMITTER_HPP
- #include <functional>
- #include <type_traits>
- #include <utility>
- // #include "../container/dense_map.hpp"
- // #include "../core/compressed_pair.hpp"
- // #include "../core/fwd.hpp"
- // #include "../core/type_info.hpp"
- // #include "../core/utility.hpp"
- // #include "fwd.hpp"
- namespace entt {
- /**
- * @brief General purpose event emitter.
- *
- * To create an emitter type, derived classes must inherit from the base as:
- *
- * @code{.cpp}
- * struct my_emitter: emitter<my_emitter> {
- * // ...
- * }
- * @endcode
- *
- * Handlers for the different events are created internally on the fly. It's not
- * required to specify in advance the full list of accepted events.<br/>
- * Moreover, whenever an event is published, an emitter also passes a reference
- * to itself to its listeners.
- *
- * @tparam Derived Emitter type.
- * @tparam Allocator Type of allocator used to manage memory and elements.
- */
- template<typename Derived, typename Allocator>
- class emitter {
- using key_type = id_type;
- using mapped_type = std::function<void(void *)>;
- using alloc_traits = std::allocator_traits<Allocator>;
- using container_allocator = typename alloc_traits::template rebind_alloc<std::pair<const key_type, mapped_type>>;
- using container_type = dense_map<key_type, mapped_type, identity, std::equal_to<>, container_allocator>;
- public:
- /*! @brief Allocator type. */
- using allocator_type = Allocator;
- /*! @brief Unsigned integer type. */
- using size_type = std::size_t;
- /*! @brief Default constructor. */
- emitter()
- : emitter{allocator_type{}} {}
- /**
- * @brief Constructs an emitter with a given allocator.
- * @param allocator The allocator to use.
- */
- explicit emitter(const allocator_type &allocator)
- : handlers{allocator, allocator} {}
- /*! @brief Default copy constructor, deleted on purpose. */
- emitter(const emitter &) = delete;
- /**
- * @brief Move constructor.
- * @param other The instance to move from.
- */
- emitter(emitter &&other) noexcept
- : handlers{std::move(other.handlers)} {}
- /**
- * @brief Allocator-extended move constructor.
- * @param other The instance to move from.
- * @param allocator The allocator to use.
- */
- emitter(emitter &&other, const allocator_type &allocator)
- : handlers{container_type{std::move(other.handlers.first()), allocator}, allocator} {
- ENTT_ASSERT(alloc_traits::is_always_equal::value || handlers.second() == other.handlers.second(), "Copying an emitter is not allowed");
- }
- /*! @brief Default destructor. */
- virtual ~emitter() {
- static_assert(std::is_base_of_v<emitter<Derived, Allocator>, Derived>, "Invalid emitter type");
- }
- /**
- * @brief Default copy assignment operator, deleted on purpose.
- * @return This emitter.
- */
- emitter &operator=(const emitter &) = delete;
- /**
- * @brief Move assignment operator.
- * @param other The instance to move from.
- * @return This emitter.
- */
- emitter &operator=(emitter &&other) noexcept {
- ENTT_ASSERT(alloc_traits::is_always_equal::value || handlers.second() == other.handlers.second(), "Copying an emitter is not allowed");
- swap(other);
- return *this;
- }
- /**
- * @brief Exchanges the contents with those of a given emitter.
- * @param other Emitter to exchange the content with.
- */
- void swap(emitter &other) noexcept {
- using std::swap;
- swap(handlers, other.handlers);
- }
- /**
- * @brief Returns the associated allocator.
- * @return The associated allocator.
- */
- [[nodiscard]] constexpr allocator_type get_allocator() const noexcept {
- return handlers.second();
- }
- /**
- * @brief Publishes a given event.
- * @tparam Type Type of event to trigger.
- * @param value An instance of the given type of event.
- */
- template<typename Type>
- void publish(Type value) {
- if(const auto id = type_id<Type>().hash(); handlers.first().contains(id)) {
- handlers.first()[id](&value);
- }
- }
- /**
- * @brief Registers a listener with the event emitter.
- * @tparam Type Type of event to which to connect the listener.
- * @param func The listener to register.
- */
- template<typename Type>
- void on(std::function<void(Type &, Derived &)> func) {
- handlers.first().insert_or_assign(type_id<Type>().hash(), [func = std::move(func), this](void *value) {
- func(*static_cast<Type *>(value), static_cast<Derived &>(*this));
- });
- }
- /**
- * @brief Disconnects a listener from the event emitter.
- * @tparam Type Type of event of the listener.
- */
- template<typename Type>
- void erase() {
- handlers.first().erase(type_hash<std::remove_const_t<std::remove_reference_t<Type>>>::value());
- }
- /*! @brief Disconnects all the listeners. */
- void clear() noexcept {
- handlers.first().clear();
- }
- /**
- * @brief Checks if there are listeners registered for the specific event.
- * @tparam Type Type of event to test.
- * @return True if there are no listeners registered, false otherwise.
- */
- template<typename Type>
- [[nodiscard]] bool contains() const {
- return handlers.first().contains(type_hash<std::remove_const_t<std::remove_reference_t<Type>>>::value());
- }
- /**
- * @brief Checks if there are listeners registered with the event emitter.
- * @return True if there are no listeners registered, false otherwise.
- */
- [[nodiscard]] bool empty() const noexcept {
- return handlers.first().empty();
- }
- private:
- compressed_pair<container_type, allocator_type> handlers;
- };
- } // namespace entt
- #endif
- // #include "signal/sigh.hpp"
- #ifndef ENTT_SIGNAL_SIGH_HPP
- #define ENTT_SIGNAL_SIGH_HPP
- #include <cstddef>
- #include <memory>
- #include <type_traits>
- #include <utility>
- #include <vector>
- // #include "delegate.hpp"
- // #include "fwd.hpp"
- namespace entt {
- /**
- * @brief Sink class.
- *
- * Primary template isn't defined on purpose. All the specializations give a
- * compile-time error unless the template parameter is a function type.
- *
- * @tparam Type A valid signal handler type.
- */
- template<typename Type>
- class sink;
- /**
- * @brief Unmanaged signal handler.
- *
- * Primary template isn't defined on purpose. All the specializations give a
- * compile-time error unless the template parameter is a function type.
- *
- * @tparam Type A valid function type.
- * @tparam Allocator Type of allocator used to manage memory and elements.
- */
- template<typename Type, typename Allocator>
- class sigh;
- /**
- * @brief Unmanaged signal handler.
- *
- * It works directly with references to classes and pointers to member functions
- * as well as pointers to free functions. Users of this class are in charge of
- * disconnecting instances before deleting them.
- *
- * This class serves mainly two purposes:
- *
- * * Creating signals to use later to notify a bunch of listeners.
- * * Collecting results from a set of functions like in a voting system.
- *
- * @tparam Ret Return type of a function type.
- * @tparam Args Types of arguments of a function type.
- * @tparam Allocator Type of allocator used to manage memory and elements.
- */
- template<typename Ret, typename... Args, typename Allocator>
- class sigh<Ret(Args...), Allocator> {
- friend class sink<sigh<Ret(Args...), Allocator>>;
- using alloc_traits = std::allocator_traits<Allocator>;
- using delegate_type = delegate<Ret(Args...)>;
- using container_type = std::vector<delegate_type, typename alloc_traits::template rebind_alloc<delegate_type>>;
- public:
- /*! @brief Allocator type. */
- using allocator_type = Allocator;
- /*! @brief Unsigned integer type. */
- using size_type = std::size_t;
- /*! @brief Sink type. */
- using sink_type = sink<sigh<Ret(Args...), Allocator>>;
- /*! @brief Default constructor. */
- sigh() noexcept(noexcept(allocator_type{}))
- : sigh{allocator_type{}} {}
- /**
- * @brief Constructs a signal handler with a given allocator.
- * @param allocator The allocator to use.
- */
- explicit sigh(const allocator_type &allocator) noexcept
- : calls{allocator} {}
- /**
- * @brief Copy constructor.
- * @param other The instance to copy from.
- */
- sigh(const sigh &other)
- : calls{other.calls} {}
- /**
- * @brief Allocator-extended copy constructor.
- * @param other The instance to copy from.
- * @param allocator The allocator to use.
- */
- sigh(const sigh &other, const allocator_type &allocator)
- : calls{other.calls, allocator} {}
- /**
- * @brief Move constructor.
- * @param other The instance to move from.
- */
- sigh(sigh &&other) noexcept
- : calls{std::move(other.calls)} {}
- /**
- * @brief Allocator-extended move constructor.
- * @param other The instance to move from.
- * @param allocator The allocator to use.
- */
- sigh(sigh &&other, const allocator_type &allocator)
- : calls{std::move(other.calls), allocator} {}
- /*! @brief Default destructor. */
- ~sigh() = default;
- /**
- * @brief Copy assignment operator.
- * @param other The instance to copy from.
- * @return This signal handler.
- */
- sigh &operator=(const sigh &other) {
- calls = other.calls;
- return *this;
- }
- /**
- * @brief Move assignment operator.
- * @param other The instance to move from.
- * @return This signal handler.
- */
- sigh &operator=(sigh &&other) noexcept {
- swap(other);
- return *this;
- }
- /**
- * @brief Exchanges the contents with those of a given signal handler.
- * @param other Signal handler to exchange the content with.
- */
- void swap(sigh &other) noexcept {
- using std::swap;
- swap(calls, other.calls);
- }
- /**
- * @brief Returns the associated allocator.
- * @return The associated allocator.
- */
- [[nodiscard]] constexpr allocator_type get_allocator() const noexcept {
- return calls.get_allocator();
- }
- /**
- * @brief Number of listeners connected to the signal.
- * @return Number of listeners currently connected.
- */
- [[nodiscard]] size_type size() const noexcept {
- return calls.size();
- }
- /**
- * @brief Returns false if at least a listener is connected to the signal.
- * @return True if the signal has no listeners connected, false otherwise.
- */
- [[nodiscard]] bool empty() const noexcept {
- return calls.empty();
- }
- /**
- * @brief Triggers a signal.
- *
- * All the listeners are notified. Order isn't guaranteed.
- *
- * @param args Arguments to use to invoke listeners.
- */
- void publish(Args... args) const {
- for(auto pos = calls.size(); pos; --pos) {
- calls[pos - 1u](args...);
- }
- }
- /**
- * @brief Collects return values from the listeners.
- *
- * The collector must expose a call operator with the following properties:
- *
- * * The return type is either `void` or such that it's convertible to
- * `bool`. In the second case, a true value will stop the iteration.
- * * The list of parameters is empty if `Ret` is `void`, otherwise it
- * contains a single element such that `Ret` is convertible to it.
- *
- * @tparam Func Type of collector to use, if any.
- * @param func A valid function object.
- * @param args Arguments to use to invoke listeners.
- */
- template<typename Func>
- void collect(Func func, Args... args) const {
- for(auto pos = calls.size(); pos; --pos) {
- if constexpr(std::is_void_v<Ret> || !std::is_invocable_v<Func, Ret>) {
- calls[pos - 1u](args...);
- if constexpr(std::is_invocable_r_v<bool, Func>) {
- if(func()) {
- break;
- }
- } else {
- func();
- }
- } else {
- if constexpr(std::is_invocable_r_v<bool, Func, Ret>) {
- if(func(calls[pos - 1u](args...))) {
- break;
- }
- } else {
- func(calls[pos - 1u](args...));
- }
- }
- }
- }
- private:
- container_type calls;
- };
- /**
- * @brief Connection class.
- *
- * Opaque object the aim of which is to allow users to release an already
- * estabilished connection without having to keep a reference to the signal or
- * the sink that generated it.
- */
- class connection {
- template<typename>
- friend class sink;
- connection(delegate<void(void *)> fn, void *ref)
- : disconnect{fn}, signal{ref} {}
- public:
- /*! @brief Default constructor. */
- connection()
- : signal{} {}
- /**
- * @brief Checks whether a connection is properly initialized.
- * @return True if the connection is properly initialized, false otherwise.
- */
- [[nodiscard]] explicit operator bool() const noexcept {
- return static_cast<bool>(disconnect);
- }
- /*! @brief Breaks the connection. */
- void release() {
- if(disconnect) {
- disconnect(signal);
- disconnect.reset();
- }
- }
- private:
- delegate<void(void *)> disconnect;
- void *signal;
- };
- /**
- * @brief Scoped connection class.
- *
- * Opaque object the aim of which is to allow users to release an already
- * estabilished connection without having to keep a reference to the signal or
- * the sink that generated it.<br/>
- * A scoped connection automatically breaks the link between the two objects
- * when it goes out of scope.
- */
- struct scoped_connection {
- /*! @brief Default constructor. */
- scoped_connection() = default;
- /**
- * @brief Constructs a scoped connection from a basic connection.
- * @param other A valid connection object.
- */
- scoped_connection(const connection &other)
- : conn{other} {}
- /*! @brief Default copy constructor, deleted on purpose. */
- scoped_connection(const scoped_connection &) = delete;
- /**
- * @brief Move constructor.
- * @param other The scoped connection to move from.
- */
- scoped_connection(scoped_connection &&other) noexcept
- : conn{std::exchange(other.conn, {})} {}
- /*! @brief Automatically breaks the link on destruction. */
- ~scoped_connection() {
- conn.release();
- }
- /**
- * @brief Default copy assignment operator, deleted on purpose.
- * @return This scoped connection.
- */
- scoped_connection &operator=(const scoped_connection &) = delete;
- /**
- * @brief Move assignment operator.
- * @param other The scoped connection to move from.
- * @return This scoped connection.
- */
- scoped_connection &operator=(scoped_connection &&other) noexcept {
- conn = std::exchange(other.conn, {});
- return *this;
- }
- /**
- * @brief Acquires a connection.
- * @param other The connection object to acquire.
- * @return This scoped connection.
- */
- scoped_connection &operator=(connection other) {
- conn = other;
- return *this;
- }
- /**
- * @brief Checks whether a scoped connection is properly initialized.
- * @return True if the connection is properly initialized, false otherwise.
- */
- [[nodiscard]] explicit operator bool() const noexcept {
- return static_cast<bool>(conn);
- }
- /*! @brief Breaks the connection. */
- void release() {
- conn.release();
- }
- private:
- connection conn;
- };
- /**
- * @brief Sink class.
- *
- * A sink is used to connect listeners to signals and to disconnect them.<br/>
- * The function type for a listener is the one of the signal to which it
- * belongs.
- *
- * The clear separation between a signal and a sink permits to store the former
- * as private data member without exposing the publish functionality to the
- * users of the class.
- *
- * @warning
- * Lifetime of a sink must not overcome that of the signal to which it refers.
- * In any other case, attempting to use a sink results in undefined behavior.
- *
- * @tparam Ret Return type of a function type.
- * @tparam Args Types of arguments of a function type.
- * @tparam Allocator Type of allocator used to manage memory and elements.
- */
- template<typename Ret, typename... Args, typename Allocator>
- class sink<sigh<Ret(Args...), Allocator>> {
- using signal_type = sigh<Ret(Args...), Allocator>;
- using delegate_type = typename signal_type::delegate_type;
- using difference_type = typename signal_type::container_type::difference_type;
- template<auto Candidate, typename Type>
- static void release(Type value_or_instance, void *signal) {
- sink{*static_cast<signal_type *>(signal)}.disconnect<Candidate>(value_or_instance);
- }
- template<auto Candidate>
- static void release(void *signal) {
- sink{*static_cast<signal_type *>(signal)}.disconnect<Candidate>();
- }
- template<typename Func>
- void disconnect_if(Func callback) {
- auto &ref = signal_or_assert();
- for(auto pos = ref.calls.size(); pos; --pos) {
- if(auto &elem = ref.calls[pos - 1u]; callback(elem)) {
- elem = std::move(ref.calls.back());
- ref.calls.pop_back();
- }
- }
- }
- [[nodiscard]] auto &signal_or_assert() const noexcept {
- ENTT_ASSERT(signal != nullptr, "Invalid pointer to signal");
- return *signal;
- }
- public:
- /*! @brief Constructs an invalid sink. */
- sink() noexcept
- : signal{} {}
- /**
- * @brief Constructs a sink that is allowed to modify a given signal.
- * @param ref A valid reference to a signal object.
- */
- sink(sigh<Ret(Args...), Allocator> &ref) noexcept
- : signal{&ref} {}
- /**
- * @brief Returns false if at least a listener is connected to the sink.
- * @return True if the sink has no listeners connected, false otherwise.
- */
- [[nodiscard]] bool empty() const noexcept {
- return signal_or_assert().calls.empty();
- }
- /**
- * @brief Connects a free function or an unbound member to a signal.
- * @tparam Candidate Function or member to connect to the signal.
- * @return A properly initialized connection object.
- */
- template<auto Candidate>
- connection connect() {
- disconnect<Candidate>();
- delegate_type call{};
- call.template connect<Candidate>();
- signal_or_assert().calls.push_back(std::move(call));
- delegate<void(void *)> conn{};
- conn.template connect<&release<Candidate>>();
- return {conn, signal};
- }
- /**
- * @brief Connects a free function with payload or a bound member to a
- * signal.
- *
- * The signal isn't responsible for the connected object or the payload.
- * Users must always guarantee that the lifetime of the instance overcomes
- * the one of the signal.<br/>
- * When used to connect a free function with payload, its signature must be
- * such that the instance is the first argument before the ones used to
- * define the signal itself.
- *
- * @tparam Candidate Function or member to connect to the signal.
- * @tparam Type Type of class or type of payload.
- * @param value_or_instance A valid reference that fits the purpose.
- * @return A properly initialized connection object.
- */
- template<auto Candidate, typename Type>
- connection connect(Type &value_or_instance) {
- disconnect<Candidate>(value_or_instance);
- delegate_type call{};
- call.template connect<Candidate>(value_or_instance);
- signal_or_assert().calls.push_back(std::move(call));
- delegate<void(void *)> conn{};
- conn.template connect<&release<Candidate, Type &>>(value_or_instance);
- return {conn, signal};
- }
- /**
- * @brief Connects a free function with payload or a bound member to a
- * signal.
- *
- * @sa connect(Type &)
- *
- * @tparam Candidate Function or member to connect to the signal.
- * @tparam Type Type of class or type of payload.
- * @param value_or_instance A valid pointer that fits the purpose.
- * @return A properly initialized connection object.
- */
- template<auto Candidate, typename Type>
- connection connect(Type *value_or_instance) {
- disconnect<Candidate>(value_or_instance);
- delegate_type call{};
- call.template connect<Candidate>(value_or_instance);
- signal_or_assert().calls.push_back(std::move(call));
- delegate<void(void *)> conn{};
- conn.template connect<&release<Candidate, Type *>>(value_or_instance);
- return {conn, signal};
- }
- /**
- * @brief Disconnects a free function or an unbound member from a signal.
- * @tparam Candidate Function or member to disconnect from the signal.
- */
- template<auto Candidate>
- void disconnect() {
- delegate_type call{};
- call.template connect<Candidate>();
- disconnect_if([&call](const auto &elem) { return elem == call; });
- }
- /**
- * @brief Disconnects a free function with payload or a bound member from a
- * signal.
- *
- * The signal isn't responsible for the connected object or the payload.
- * Users must always guarantee that the lifetime of the instance overcomes
- * the one of the signal.<br/>
- * When used to connect a free function with payload, its signature must be
- * such that the instance is the first argument before the ones used to
- * define the signal itself.
- *
- * @tparam Candidate Function or member to disconnect from the signal.
- * @tparam Type Type of class or type of payload, if any.
- * @param value_or_instance A valid reference that fits the purpose.
- */
- template<auto Candidate, typename Type>
- void disconnect(Type &value_or_instance) {
- delegate_type call{};
- call.template connect<Candidate>(value_or_instance);
- disconnect_if([&call](const auto &elem) { return elem == call; });
- }
- /**
- * @brief Disconnects a free function with payload or a bound member from a
- * signal.
- *
- * @sa disconnect(Type &)
- *
- * @tparam Candidate Function or member to disconnect from the signal.
- * @tparam Type Type of class or type of payload, if any.
- * @param value_or_instance A valid pointer that fits the purpose.
- */
- template<auto Candidate, typename Type>
- void disconnect(Type *value_or_instance) {
- delegate_type call{};
- call.template connect<Candidate>(value_or_instance);
- disconnect_if([&call](const auto &elem) { return elem == call; });
- }
- /**
- * @brief Disconnects free functions with payload or bound members from a
- * signal.
- * @param value_or_instance A valid object that fits the purpose.
- */
- void disconnect(const void *value_or_instance) {
- ENTT_ASSERT(value_or_instance != nullptr, "Invalid value or instance");
- disconnect_if([value_or_instance](const auto &elem) { return elem.data() == value_or_instance; });
- }
- /*! @brief Disconnects all the listeners from a signal. */
- void disconnect() {
- signal_or_assert().calls.clear();
- }
- /**
- * @brief Returns true if a sink is correctly initialized, false otherwise.
- * @return True if a sink is correctly initialized, false otherwise.
- */
- [[nodiscard]] explicit operator bool() const noexcept {
- return signal != nullptr;
- }
- private:
- signal_type *signal;
- };
- /**
- * @brief Deduction guide.
- *
- * It allows to deduce the signal handler type of a sink directly from the
- * signal it refers to.
- *
- * @tparam Ret Return type of a function type.
- * @tparam Args Types of arguments of a function type.
- * @tparam Allocator Type of allocator used to manage memory and elements.
- */
- template<typename Ret, typename... Args, typename Allocator>
- sink(sigh<Ret(Args...), Allocator> &) -> sink<sigh<Ret(Args...), Allocator>>;
- } // namespace entt
- #endif
- // IWYU pragma: end_exports
|